Skip to content
← Back

src/semantic/delegate_push_candidates.ghul

1
namespace Semantic is
2
use Types.Type;
3
4
// Decides whether a named-delegate formal that a plain
5
// assignability check rejects is worth pushing as a constraint
6
// and re-walking the argument under - a bare function reference,
7
// or a lambda literal that resolved to its own native shape
8
// before the delegate slot was known. `Func`/`Action` slots never
9
// reach here: `DELEGATE_SHAPE.is_named_delegate` answers false
10
// for them, so they keep going through the ordinary function-type
11
// assignability path.
12
class DELEGATE_PUSH_CANDIDATES(
13
_delegate_shape: DELEGATE_SHAPE,
14
_innate_symbol_lookup: Lookups.InnateSymbolLookup
15
) is
16
super();
17
18
init(..) is
19
si
20
21
// `formal` is a named delegate `actual` isn't already
22
// assignable to, but which `actual` could satisfy once its
23
// own call shape is pushed against the delegate's invoke
24
// shape and re-walked.
25
is_push_candidate(formal: Type, actual: Type) -> bool is
26
if !_delegate_shape.is_named_delegate(formal) \/ formal.is_assignable_from(actual) then
27
return false;
28
fi
29
30
if !actual.is_function then
31
return false;
32
fi
33
34
let shape = _delegate_shape.try_get_function_type(formal, _innate_symbol_lookup);
35
36
return shape? /\ shape.is_assignable_from(actual);
37
si
38
39
// True when pushing `candidate`'s own formal types onto the
40
// current actuals stands a chance of resolving a named-
41
// delegate mismatch that a plain assignability check missed
42
// on the first walk.
43
has_push_mismatch(candidate: Symbols.Function, argument_types: Collections.LIST[Type]) -> bool is
44
for i in 0..argument_types.count do
45
if is_push_candidate(candidate.arguments[i], argument_types[i]) then
46
return true;
47
fi
48
od
49
50
return false;
51
si
52
53
// Same shape as a plain single-arity-candidate search, for
54
// when that search finds nothing because more than one
55
// arity-matching overload exists (`List[T].sort` has both
56
// `Sort(Comparison[T])` and `Sort(IComparer[T])`). A named
57
// delegate formal narrows the field: an overload whose
58
// mismatched argument isn't even delegate-pushable is
59
// rejected outright, so genuine ambiguity between two
60
// delegate-shaped formals both able to accept the actual
61
// still falls through to null - only a group that resolves to
62
// exactly one push-worthy overload is picked here.
63
find_single_pushable_candidate(
64
group: Symbols.FUNCTION_GROUP,
65
argument_types: Collections.LIST[Type],
66
want_instance: bool
67
) -> Symbols.Function? is
68
let result: Symbols.Function? mut = null;
69
let count mut = 0;
70
71
for f in group.functions do
72
if !want_instance /\ f.is_instance then
73
continue;
74
fi
75
76
if !f.are_arguments_declared then
77
continue;
78
fi
79
80
if f.arguments.count != argument_types.count then
81
continue;
82
fi
83
84
let compatible mut = true;
85
let any_pushed mut = false;
86
87
for i in 0..argument_types.count do
88
let formal = f.arguments[i];
89
let actual = argument_types[i];
90
91
if formal.is_assignable_from(actual) then
92
continue;
93
fi
94
95
if is_push_candidate(formal, actual) then
96
any_pushed = true;
97
continue;
98
fi
99
100
compatible = false;
101
od
102
103
if compatible /\ any_pushed then
104
result = f;
105
count = count + 1;
106
fi
107
od
108
109
if count == 1 then
110
return result;
111
fi
112
113
return null;
114
si
115
si
116
si