Exhaustive switch on enums. This addresses #838

This commit is contained in:
Christoffer Lerno
2023-07-09 01:00:39 +02:00
committed by Christoffer Lerno
parent 8b605d9183
commit 9543fbbf1c
9 changed files with 45 additions and 8 deletions

View File

@@ -79,7 +79,6 @@ fn void*! arena_allocator_function(Allocator* data, usz size, usz alignment, usz
arena.used = size;
return null;
}
unreachable();
}
/**

View File

@@ -237,5 +237,4 @@ fn void*! dynamic_arena_allocator_function(Allocator* data, usz size, usz alignm
allocator.reset();
return null;
}
unreachable();
}

View File

@@ -97,7 +97,6 @@ fn void*! on_stack_allocator_function(Allocator* data, usz size, usz alignment,
case RESET:
unreachable("Reset unsupported");
}
unreachable();
}
fn bool allocation_in_stack_mem(OnStackAllocator* a, void* ptr) @local

View File

@@ -83,7 +83,6 @@ fn void*! temp_allocator_function(Allocator* data, usz size, usz alignment, usz
arena._reset(size)!;
return null;
}
unreachable();
}
fn void! TempAllocator._free(&self, void* old_pointer) @local

View File

@@ -104,5 +104,4 @@ fn void*! tracking_allocator_fn(Allocator* data, usz size, usz alignment, usz of
this.map.clear();
return null;
}
unreachable();
}

View File

@@ -69,7 +69,6 @@ fn Object*! JsonParser.parse_from_token(&self, JsonTokenType token)
case NULL: return object::new_null();
case EOF: return JsonParsingError.EOF?;
}
unreachable();
}
fn Object*! JsonParser.parse_any(&self)
{

View File

@@ -3,6 +3,7 @@
## 0.5.0 Change List
### Changes / improvements
- Exhaustive switches with enums has better analysis.
- Globals may now be initialized with optional values.
- New generic syntax.
- Added `$embed` to embed binary data.

View File

@@ -2110,8 +2110,10 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc
return false;
}
// We need an if-chain if this isn't an enum/integer type.
TypeKind flat_switch_type_kind = type_flatten(switch_type)->type_kind;
bool if_chain = flat_switch_type_kind != TYPE_ENUM && !type_kind_is_any_integer(flat_switch_type_kind);
Type *flat = type_flatten(switch_type);
TypeKind flat_switch_type_kind = flat->type_kind;
bool is_enum_switch = flat_switch_type_kind == TYPE_ENUM;
bool if_chain = !is_enum_switch && !type_kind_is_any_integer(flat_switch_type_kind);
Ast *default_case = NULL;
assert(context->active_scope.defer_start == context->active_scope.defer_last);
@@ -2163,6 +2165,7 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc
POP_NEXT();
}
if (!exhaustive && is_enum_switch && case_count == vec_size(flat->decl->enums.values)) exhaustive = true;
bool all_jump_end = exhaustive;
for (unsigned i = 0; i < case_count; i++)
{

View File

@@ -0,0 +1,39 @@
// #target: macos-x64
module test;
import std::io;
enum Foo
{
ABC,
DEF
}
fn int hello(Foo a)
{
switch (a)
{
case ABC: return 1;
case DEF: return 0;
}
}
/* #expect: test.ll
define i32 @test.hello(i32 %0) #0 {
entry:
%switch = alloca i32, align 4
store i32 %0, ptr %switch, align 4
br label %switch.entry
switch.entry: ; preds = %entry
%1 = load i32, ptr %switch, align 4
switch i32 %1, label %switch.exit [
i32 0, label %switch.case
i32 1, label %switch.case1
]
switch.case: ; preds = %switch.entry
ret i32 1
switch.case1: ; preds = %switch.entry
ret i32 0
switch.exit: ; preds = %switch.entry
unreachable
}