commit a62c0875e2f3d5f42fa1d67936242ef8a9a5aee2
parent db9663f9b9e7868ab31614bbe27fb7d0a7de8198
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 2 Feb 2021 14:36:05 -0500
check: lower switch branches to type hint
Diffstat:
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -1331,7 +1331,7 @@ check_expr_switch(struct context *ctx,
struct expression *value = xcalloc(1, sizeof(struct expression));
check_expression(ctx, aexpr->_switch.value, value, NULL);
- const struct type *type = value->result;
+ const struct type *type = type_dealias(value->result);
expr->_switch.value = value;
struct type_tagged_union result_type = {0};
@@ -1357,7 +1357,7 @@ check_expr_switch(struct context *ctx,
check_expression(ctx, aopt->value, value, type);
// XXX: Should this be assignable instead?
expect(&aopt->value->loc,
- type == value->result,
+ type == type_dealias(value->result),
"Invalid type for switch case");
enum eval_result r = eval_expr(ctx, value, evaled);
@@ -1392,14 +1392,23 @@ check_expr_switch(struct context *ctx,
}
if (result_type.next) {
- expr->result = type_store_lookup_tagged(
- ctx->store, &result_type);
+ if (hint) {
+ expr->result = hint;
+ } else {
+ expr->result = type_store_lookup_tagged(
+ ctx->store, &result_type);
+ }
struct switch_case *_case = expr->_switch.cases;
+ struct ast_switch_case *acase = aexpr->_switch.cases;
while (_case) {
+ expect(&acase->value->loc,
+ type_is_assignable(expr->result, _case->value->result),
+ "Switch case is not assignable to result type");
_case->value = lower_implicit_cast(
expr->result, _case->value);
_case = _case->next;
+ acase = acase->next;
}
struct type_tagged_union *tu = result_type.next;
diff --git a/tests/18-match.ha b/tests/18-match.ha
@@ -86,7 +86,7 @@ fn implicit_cast() void = {
let x: foobar = foo;
let y: nullable *int = null;
let a: (int | foobar) = match (y) {
- null => foo: foobar,
+ null => foo,
z: *int => *z,
};
assert(a is foobar);