harec

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

commit b315aba134db251d9df47c75392ecf2e12531e80
parent 2a6711b038d44577cd1aca66ea666260cbecc34b
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 31 Jan 2021 11:06:37 -0500

check: fix issue with type assertions

Diffstat:
Msrc/check.c | 10+++++++---
Mtests/18-match.ha | 11+++++++++++
2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -544,15 +544,15 @@ check_expr_cast(struct context *ctx, const struct type *secondary = expr->cast.secondary = type_store_lookup_atype(ctx->store, aexpr->cast.type); check_expression(ctx, aexpr->cast.value, value, secondary); - expect(&aexpr->cast.type->loc, - type_is_castable(secondary, value->result), - "Invalid cast"); if (aexpr->cast.kind == C_ASSERTION || aexpr->cast.kind == C_TEST) { const struct type *primary = type_dealias(expr->cast.value->result); expect(&aexpr->cast.value->loc, primary->storage == TYPE_STORAGE_TAGGED, "Expected a tagged union type"); + expect(&aexpr->cast.type->loc, + type_is_castable(value->result, secondary), + "Invalid cast"); bool found = false; for (const struct type_tagged_union *t = &primary->tagged; t; t = t->next) { @@ -567,6 +567,10 @@ check_expr_cast(struct context *ctx, switch (aexpr->cast.kind) { case C_CAST: + expect(&aexpr->cast.type->loc, + type_is_castable(secondary, value->result), + "Invalid cast"); + // Fallthrough case C_ASSERTION: expr->result = secondary; break; diff --git a/tests/18-match.ha b/tests/18-match.ha @@ -79,6 +79,16 @@ fn tagged_result() void = { assert(y is uint); }; +fn implicit_cast() void = { + let x: foobar = foo; + let y: nullable *int = null; + let a: (int | foobar) = match (y) { + null => foo: foobar, + z: *int => *z, + }; + assert(a is foobar); +}; + export fn main() void = { tagged(); termination(); @@ -86,5 +96,6 @@ export fn main() void = { pointer(); alias(); tagged_result(); + implicit_cast(); // TODO: Test exhaustiveness and dupe detection };