diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-03-31 18:38:26 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-03-31 18:39:34 -0700 |
| commit | e8143f6cbe3d1bdaeda5cd5af13447f6639b80ad (patch) | |
| tree | 954e032848a0abb638e1e0af45dc4ec3114e8f3e | |
| parent | cec766f73c298d287c20d1bd830c159958fe177d (diff) | |
| download | zig-e8143f6cbe3d1bdaeda5cd5af13447f6639b80ad.tar.gz zig-e8143f6cbe3d1bdaeda5cd5af13447f6639b80ad.zip | |
stage2: compile error for duplicate switch value on sparse
| -rw-r--r-- | BRANCH_TODO | 13 | ||||
| -rw-r--r-- | src/Sema.zig | 17 | ||||
| -rw-r--r-- | test/stage2/cbe.zig | 16 |
3 files changed, 27 insertions, 19 deletions
diff --git a/BRANCH_TODO b/BRANCH_TODO index 72b1ed6719..a80a7dca34 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -36,16 +36,3 @@ Performance optimizations to look into: * look into not emitting redundant dbg stmts to TZIR * make decl references in ZIR be u32 indexes to the Decl dependencies array hash map instead of duplicating *Decl entries in zir.Code. - - - for (inst.positionals.items) |item| { - const resolved = try sema.resolveInst(item); - const casted = try sema.coerce(block, operand.ty, resolved); - const val = try sema.resolveConstValue(block, item_src, casted); - - if (try seen_values.fetchPut(val, item.src)) |prev| { - return sema.mod.fail(&block.base, item.src, "duplicate switch value", .{}); - // TODO notes "previous value here" prev.value - } - } - diff --git a/src/Sema.zig b/src/Sema.zig index f53bc295f3..4d97506e3c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -62,8 +62,6 @@ const LazySrcLoc = Module.LazySrcLoc; const RangeSet = @import("RangeSet.zig"); const AstGen = @import("AstGen.zig"); -const ValueSrcMap = std.HashMap(Value, LazySrcLoc, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage); - pub fn root(sema: *Sema, root_block: *Scope.Block) !zir.Inst.Index { const inst_data = sema.code.instructions.items(.data)[0].pl_node; const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index); @@ -2557,7 +2555,7 @@ fn analyzeSwitch( var extra_index: usize = special.end; { - var scalar_i: usize = 0; + var scalar_i: u32 = 0; while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; @@ -2571,11 +2569,12 @@ fn analyzeSwitch( &seen_values, item_ref, src_node_offset, + .{ .scalar = scalar_i }, ); } } { - var multi_i: usize = 0; + var multi_i: u32 = 0; while (multi_i < multi_cases_len) : (multi_i += 1) { const items_len = sema.code.extra[extra_index]; extra_index += 1; @@ -2586,12 +2585,13 @@ fn analyzeSwitch( const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len + body_len; - for (items) |item_ref| { + for (items) |item_ref, item_i| { try sema.validateSwitchItemSparse( block, &seen_values, item_ref, src_node_offset, + .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, ); } @@ -2981,14 +2981,19 @@ fn validateSwitchItemBool( } } +const ValueSrcMap = std.HashMap(Value, AstGen.SwitchProngSrc, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage); + fn validateSwitchItemSparse( sema: *Sema, block: *Scope.Block, seen_values: *ValueSrcMap, item_ref: zir.Inst.Ref, src_node_offset: i32, + switch_prong_src: AstGen.SwitchProngSrc, ) InnerError!void { - @panic("TODO"); + const item_val = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); + const entry = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return; + return sema.validateSwitchDupe(block, entry.value, switch_prong_src, src_node_offset); } fn validateSwitchNoRange( diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index fa8195f48a..2b0976c9f8 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -359,6 +359,22 @@ pub fn addCases(ctx: *TestContext) !void { , &.{ ":6:9: error: duplicate switch value", }); + + // Sparse (no range capable) switch expression has duplicate case value. + case.addError( + \\export fn main() c_int { + \\ const A: type = i32; + \\ const b: c_int = switch (A) { + \\ i32 => 1, + \\ bool => 2, + \\ f64, i32 => 3, + \\ else => 4, + \\ }; + \\} + , &.{ + ":6:14: error: duplicate switch value", + ":4:9: note: previous value here", + }); } //{ // var case = ctx.exeFromCompiledC("optionals", .{}); |
