Skip to content
← Back

src/semantic/null_return_join.ghul

1
namespace Semantic is
2
use Types.Type
3
4
// What a function's inferred return type settles at once one of its
5
// returns has produced null. A null says a value can be absent
6
// without saying what it holds when present, so it settles nothing
7
// itself: what it does is make whatever the other returns settled on
8
// able to be absent.
9
//
10
// The widening is the one ARM_NULL_JOIN already decides for an if or
11
// case arm, so a body's returns and an expression's arms answer
12
// alike.
13
class NULL_RETURN_JOIN is
14
of(
15
pinned: Type,
16
returned_genuine_null: bool,
17
innate_symbol_lookup: Lookups.InnateSymbolLookup
18
) -> Type static is
19
if !returned_genuine_null then
20
return pinned
21
fi
22
23
// Already able to be absent - the slot asked for an optional,
24
// or another return produced one - so the null adds nothing
25
// and wrapping again would make an optional of an optional.
26
if pinned.is_optional \/ pinned.is_maybe then
27
return pinned
28
fi
29
30
let decision = ARM_NULL_JOIN().decide(pinned, true, true)
31
32
if decision == ArmNullJoinDecision.WIDEN_VALUE_OPTIONAL then
33
return innate_symbol_lookup.get_optional_type(pinned)
34
fi
35
36
if decision == ArmNullJoinDecision.WIDEN_REFERENCE_OPTIONAL then
37
return pinned
38
.as_optional()
39
fi
40
41
// A type variable has no optional carrier to widen into, the
42
// same verdict an arm reaches: left as it is, and whatever
43
// the return is checked against reports it.
44
return pinned
45
si
46
si
47
si