Skip to content
← Back

src/semantic/settled_placeholder_resolver.ghul

1
namespace Semantic is
2
use Semantic.Types.Type;
3
4
// Collapses inference placeholders to the concrete types their
5
// origins have settled on, recursing through composite types.
6
//
7
// A composite type assembled while inference is still running
8
// (a tuple's element types, a closure's argument types, a LUB
9
// candidate) captures whatever its parts were typed as on that
10
// iteration - including raw placeholders. The origin Variable
11
// goes on to settle, but nothing rewrites the composite, so it
12
// keeps pointing at the placeholder. Types routed through this
13
// resolver pick up the settled types instead, which is what
14
// keeps a placeholder out of the type that reaches IL emission.
15
//
16
// An unsettled placeholder is preserved: it is still
17
// accumulating constraints, and substituting a provisional
18
// answer would freeze the wrong type. The body-retry loop runs
19
// the enclosing walk again once more is known, so the composite
20
// is rebuilt with the settled type on a later iteration. Only
21
// substituting settled resolutions is also what makes the
22
// recursion safe: a settled type contains no placeholders to
23
// recurse back into, so a self-referential provisional origin
24
// cannot send resolution into a cycle.
25
class SETTLED_PLACEHOLDER_RESOLVER is
26
_instance: SETTLED_PLACEHOLDER_RESOLVER static;
27
28
instance: SETTLED_PLACEHOLDER_RESOLVER static is
29
if !_instance? then
30
_instance = SETTLED_PLACEHOLDER_RESOLVER();
31
fi
32
33
return _instance;
34
si
35
36
init() is
37
super.init();
38
si
39
40
resolve(type: Type) -> Type is
41
if isa Types.INFERRED_VARIABLE_TYPE(type) then
42
let resolved = type.origin.try_get_inferred_type();
43
44
if resolved? /\ resolved.is_settled then
45
return resolved;
46
fi
47
48
return type;
49
fi
50
51
if !isa Types.GENERIC(type) \/ !type.contains_inferred then
52
return type;
53
fi
54
55
let generic = cast Types.GENERIC(type);
56
let generic_symbol = cast Symbols.GENERIC?(generic.symbol);
57
58
if !generic_symbol? then
59
return type;
60
fi
61
62
let new_arguments = Collections.LIST[Type](generic.arguments.count);
63
let seen_any_new mut = false;
64
65
for argument in generic.arguments do
66
let resolved_argument = resolve(argument);
67
68
new_arguments.add(resolved_argument);
69
70
if resolved_argument != argument then
71
seen_any_new = true;
72
fi
73
od
74
75
if !seen_any_new then
76
return type;
77
fi
78
79
return generic.create(generic.symbol.location, generic_symbol.symbol, new_arguments);
80
si
81
82
resolve_all(types: Collections.List[Type]) -> Collections.List[Type] is
83
let result = Collections.LIST[Type](types.count);
84
85
for type in types do
86
result.add(resolve(type));
87
od
88
89
return result;
90
si
91
si
92
si