Skip to content
← Back

src/semantic/expected_arm_join.ghul

1
namespace Semantic is
2
use Semantic.Types.Type
3
4
// The type an if expression takes from its own arms when the type
5
// pushed down to it still holds placeholders. Such a type comes from a
6
// call whose type arguments the expression is meant to pin, so it
7
// cannot also be the expression's type. The arms' join stands in for
8
// it only when every arm that yields a value has contributed a type
9
// that is neither null nor an error, and the join itself is settled.
10
class EXPECTED_ARM_JOIN is
11
_lub: LEAST_UPPER_BOUND_MAP
12
_usable: bool
13
14
init(expected_type: Type?) is
15
super.init()
16
17
_lub = LEAST_UPPER_BOUND_MAP()
18
_usable = expected_type? /\ expected_type.contains_inferred
19
si
20
21
// An arm that yields a value but contributes no type to join: its
22
// type is not known yet, or it cannot be consumed. A join over the
23
// remaining arms would not describe the whole expression.
24
add_untyped_arm() is
25
_usable = false
26
si
27
28
add(arm_type: Type) is
29
if arm_type.is_null \/ arm_type.is_error then
30
_usable = false
31
else
32
_lub.add(arm_type)
33
fi
34
si
35
36
// An expression that yields absence on fall-through is typed by
37
// the optional join elsewhere, so it takes nothing from here.
38
result(yields_absence: bool) -> Type? is
39
if !_usable \/ yields_absence then
40
return null
41
fi
42
43
if let joined = _lub.get_result() /\ joined.is_settled then
44
return joined
45
fi
46
47
return null
48
si
49
si
50
si