Appearance
| 1 | namespace Semantic is | |
| 2 | use Types.Type | |
| 3 | ||
| 4 | // Answers whether a type variable belongs to a declaration that | |
| 5 | // some context is written inside. | |
| 6 | // | |
| 7 | // Such a variable already stands for a definite type there: the | |
| 8 | // enclosing declaration will be given an argument for it, and | |
| 9 | // every use in the body means whatever that turns out to be. A | |
| 10 | // variable belonging to any other declaration - the callee an | |
| 11 | // overload resolver is trying, say - means nothing yet, because | |
| 12 | // what it stands for is the very thing being worked out. | |
| 13 | class ENCLOSING_TYPE_VARIABLE is | |
| 14 | init() is si | |
| 15 | ||
| 16 | is_fixed_in(type: Type, context: Symbols.Function?) -> bool is | |
| 17 | if !type.is_type_variable then | |
| 18 | return false | |
| 19 | fi | |
| 20 | ||
| 21 | let named = cast Types.NAMED?(type) | |
| 22 | ||
| 23 | if !named? then | |
| 24 | return false | |
| 25 | fi | |
| 26 | ||
| 27 | let declarer = _as_symbol(named.symbol.owner) | |
| 28 | ||
| 29 | if !declarer? then | |
| 30 | return false | |
| 31 | fi | |
| 32 | ||
| 33 | // The chain does not terminate on its own: a namespace | |
| 34 | // owns itself, having no symbol above it to own it, so a | |
| 35 | // walk reaching one would circle there forever. The walk | |
| 36 | // carries what it has already stood on and stops on its | |
| 37 | // own account, which also keeps any other ownership cycle | |
| 38 | // to a wrong answer rather than a hang - this runs inside | |
| 39 | // the inference retry loop, where a hang is much the | |
| 40 | // worse of the two. | |
| 41 | let seen = Collections.LIST[Symbols.Symbol]() | |
| 42 | let scope mut = _as_symbol(context) | |
| 43 | ||
| 44 | while scope? do | |
| 45 | if scope == declarer then | |
| 46 | return true | |
| 47 | fi | |
| 48 | ||
| 49 | if _contains(seen, scope) then | |
| 50 | return false | |
| 51 | fi | |
| 52 | ||
| 53 | seen.add(scope) | |
| 54 | ||
| 55 | scope = _as_symbol(scope.owner) | |
| 56 | od | |
| 57 | ||
| 58 | return false | |
| 59 | si | |
| 60 | ||
| 61 | _contains(seen: Collections.List[Symbols.Symbol], scope: Symbols.Symbol) -> bool is | |
| 62 | for s in seen do | |
| 63 | if s == scope then | |
| 64 | return true | |
| 65 | fi | |
| 66 | od | |
| 67 | ||
| 68 | return false | |
| 69 | si | |
| 70 | ||
| 71 | // A partial or impl block declares its members into a target | |
| 72 | // type while resolving names at its own site, so the walk has | |
| 73 | // to reach the target rather than stopping at the block, and a | |
| 74 | // specialization stands in for the declaration it specializes. | |
| 75 | // Both ends are normalised the same way so the comparison is | |
| 76 | // between declarations rather than between views of them. | |
| 77 | _as_symbol(scope: Scope?) -> Symbols.Symbol? is | |
| 78 | if !scope? then | |
| 79 | return null | |
| 80 | fi | |
| 81 | ||
| 82 | return scope.underlying_scope.unspecialized_symbol | |
| 83 | si | |
| 84 | si | |
| 85 | si |