mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
Add new error message for unreachable else prongs
* Adds error message for types: enum, int and bool * Adds compile error tests
This commit is contained in:
parent
e60be30824
commit
dcc406deff
20
src/ir.cpp
20
src/ir.cpp
@ -28700,6 +28700,10 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
|
||||
buf_ptr(enum_field->name)));
|
||||
}
|
||||
}
|
||||
} else if(!switch_type->data.enumeration.non_exhaustive && switch_type->data.enumeration.src_field_count == instruction->range_count) {
|
||||
ir_add_error_node(ira, instruction->else_prong,
|
||||
buf_sprintf("unreachable else prong, all cases already handled"));
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
} else if (switch_type->id == ZigTypeIdErrorSet) {
|
||||
if (!resolve_inferred_error_set(ira->codegen, switch_type, target_value->base.source_node)) {
|
||||
@ -28808,16 +28812,20 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
}
|
||||
if (instruction->else_prong == nullptr) {
|
||||
|
||||
BigInt min_val;
|
||||
eval_min_max_value_int(ira->codegen, switch_type, &min_val, false);
|
||||
BigInt max_val;
|
||||
eval_min_max_value_int(ira->codegen, switch_type, &max_val, true);
|
||||
if (!rangeset_spans(&rs, &min_val, &max_val)) {
|
||||
bool handles_all_cases = rangeset_spans(&rs, &min_val, &max_val);
|
||||
if (!handles_all_cases && instruction->else_prong == nullptr) {
|
||||
ir_add_error(ira, &instruction->base.base, buf_sprintf("switch must handle all possibilities"));
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
} else if(handles_all_cases && instruction->else_prong != nullptr) {
|
||||
ir_add_error_node(ira, instruction->else_prong,
|
||||
buf_sprintf("unreachable else prong, all cases already handled"));
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
}
|
||||
} else if (switch_type->id == ZigTypeIdBool) {
|
||||
int seenTrue = 0;
|
||||
int seenFalse = 0;
|
||||
@ -28851,6 +28859,12 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
|
||||
ir_add_error(ira, &instruction->base.base, buf_sprintf("switch must handle all possibilities"));
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
|
||||
if(seenTrue == 1 && seenFalse == 1 && instruction->else_prong != nullptr) {
|
||||
ir_add_error_node(ira, instruction->else_prong,
|
||||
buf_sprintf("unreachable else prong, all cases already handled"));
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
} else if (instruction->else_prong == nullptr) {
|
||||
ir_add_error(ira, &instruction->base.base,
|
||||
buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
|
||||
|
||||
@ -468,6 +468,102 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
"tmp.zig:12:5: error: switch on non-exhaustive enum must include `else` or `_` prong",
|
||||
});
|
||||
|
||||
cases.add("switch expression - unreachable else prong (bool)",
|
||||
\\fn foo(x: bool) void {
|
||||
\\ switch (x) {
|
||||
\\ true => {},
|
||||
\\ false => {},
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\}
|
||||
\\export fn entry() usize { return @sizeOf(@TypeOf(foo)); }
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:5:9: error: unreachable else prong, all cases already handled",
|
||||
});
|
||||
|
||||
cases.add("switch expression - unreachable else prong (u1)",
|
||||
\\fn foo(x: u1) void {
|
||||
\\ switch (x) {
|
||||
\\ 0 => {},
|
||||
\\ 1 => {},
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\}
|
||||
\\export fn entry() usize { return @sizeOf(@TypeOf(foo)); }
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:5:9: error: unreachable else prong, all cases already handled",
|
||||
});
|
||||
|
||||
cases.add("switch expression - unreachable else prong (u2)",
|
||||
\\fn foo(x: u2) void {
|
||||
\\ switch (x) {
|
||||
\\ 0 => {},
|
||||
\\ 1 => {},
|
||||
\\ 2 => {},
|
||||
\\ 3 => {},
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\}
|
||||
\\export fn entry() usize { return @sizeOf(@TypeOf(foo)); }
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:7:9: error: unreachable else prong, all cases already handled",
|
||||
});
|
||||
|
||||
cases.add("switch expression - unreachable else prong (range u8)",
|
||||
\\fn foo(x: u8) void {
|
||||
\\ switch (x) {
|
||||
\\ 0 => {},
|
||||
\\ 1 => {},
|
||||
\\ 2 => {},
|
||||
\\ 3 => {},
|
||||
\\ 4...255 => {},
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\}
|
||||
\\export fn entry() usize { return @sizeOf(@TypeOf(foo)); }
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:8:9: error: unreachable else prong, all cases already handled",
|
||||
});
|
||||
|
||||
cases.add("switch expression - unreachable else prong (range i8)",
|
||||
\\fn foo(x: i8) void {
|
||||
\\ switch (x) {
|
||||
\\ -128...0 => {},
|
||||
\\ 1 => {},
|
||||
\\ 2 => {},
|
||||
\\ 3 => {},
|
||||
\\ 4...127 => {},
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\}
|
||||
\\export fn entry() usize { return @sizeOf(@TypeOf(foo)); }
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:8:9: error: unreachable else prong, all cases already handled",
|
||||
});
|
||||
|
||||
cases.add("switch expression - unreachable else prong (enum)",
|
||||
\\const TestEnum = enum{ T1, T2 };
|
||||
\\
|
||||
\\fn err(x: u8) TestEnum {
|
||||
\\ switch (x) {
|
||||
\\ 0 => return TestEnum.T1,
|
||||
\\ else => return TestEnum.T2,
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
\\fn foo(x: u8) void {
|
||||
\\ switch (err(x)) {
|
||||
\\ TestEnum.T1 => {},
|
||||
\\ TestEnum.T2 => {},
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
\\export fn entry() usize { return @sizeOf(@TypeOf(foo)); }
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:14:9: error: unreachable else prong, all cases already handled",
|
||||
});
|
||||
|
||||
cases.addTest("@export with empty name string",
|
||||
\\pub export fn entry() void { }
|
||||
\\comptime {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user