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