Assertion failure when never is used as match case

match (foo) { // foo is any tagged union
case never => void;
case => void;
Assertion failed: type_dealias(NULL, _case->type)->storage == STORAGE_TAGGED (src/gen.c: gen_match_with_tagged: 2536)

The issue is that never is assignable to all tagged unions, so it passes check, but gen expects that every match case is either a member or a subset.

This can also happen as a result of hare lowering an error propagation/assertion into a match:

type a = !void;
type b = !void;
fn f() void = (a: (a | b))!;
Assigned to
6 months ago
a month ago
bug design harec

~sebsite 2 months ago

A thought: what if we made case => equivalent to case never => when matching on a tagged union? This would also disallow using never in a type assertion or type test, since those are syntactic sugar over match, and would result in a duplicate default case. Not sure how well this fits into the current plans for the tagged union overhaul, cc ~ecs

~ecs 2 months ago

maybe we should just disallow types with undefined sizes in matches? not sure why making never be a default would ever be useful outside of trying to hack together a reason to disallow it

~turminal 2 months ago

Strictly theoretically, using never makes sense here, because all types are assign-compatible to never. I'm not sure that reads sensibly to a programmer that doesn't want to concern themself with programming language theory though.

I also don't think that's the right way to prevent never in type assertions, not in the least because we want that to produce a better error message than "duplicate default case"

~sebsite a month ago

Yeah, on second thought, probably not a good idea. Disallowing types with undefined size in matches is probably the best solution.

Register here or Log in to comment, or comment via email.