Appearance
| 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 |