Skip to content
← Back

src/semantic/enclosing_type_variable.ghul

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