harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Msrc/check.c | 17+++++++++++++----
Mtests/18-match.ha | 2+-
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);