zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 5765755fcd6bd8570494057255e7d92d489ef35e (tree)
parent 13321c8070b52afb24f3c1b57eecbb2aa77fc4ec
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Fri, 18 Mar 2022 14:50:40 -0400

Merge pull request #11218 from mitchellh/labeled-break

AstGen: labeled blocks should always complete with a normal break
Diffstat:
Msrc/AstGen.zig | 9+++------
Mtest/behavior.zig | 1+
Atest/behavior/bugs/11213.zig | 37+++++++++++++++++++++++++++++++++++++
3 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/src/AstGen.zig b/src/AstGen.zig @@ -1939,7 +1939,7 @@ fn blockExpr( if (token_tags[lbrace - 1] == .colon and token_tags[lbrace - 2] == .identifier) { - return labeledBlockExpr(gz, scope, rl, block_node, statements, .block); + return labeledBlockExpr(gz, scope, rl, block_node, statements); } try blockExprStmts(gz, scope, statements); @@ -1984,13 +1984,10 @@ fn labeledBlockExpr( rl: ResultLoc, block_node: Ast.Node.Index, statements: []const Ast.Node.Index, - zir_tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); - assert(zir_tag == .block); - const astgen = gz.astgen; const tree = astgen.tree; const main_tokens = tree.nodes.items(.main_token); @@ -2004,7 +2001,7 @@ fn labeledBlockExpr( // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct // so that break statements can reference it. - const block_inst = try gz.makeBlockInst(zir_tag, block_node); + const block_inst = try gz.makeBlockInst(.block, block_node); try gz.instructions.append(astgen.gpa, block_inst); var block_scope = gz.makeSubBlock(parent_scope); @@ -2018,7 +2015,7 @@ fn labeledBlockExpr( try blockExprStmts(&block_scope, &block_scope.base, statements); if (!block_scope.endsWithNoReturn()) { - _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); + _ = try block_scope.addBreak(.@"break", block_inst, .void_value); } if (!block_scope.label.?.used) { diff --git a/test/behavior.zig b/test/behavior.zig @@ -70,6 +70,7 @@ test { _ = @import("behavior/bugs/11165.zig"); _ = @import("behavior/bugs/11181.zig"); _ = @import("behavior/bugs/11182.zig"); + _ = @import("behavior/bugs/11213.zig"); _ = @import("behavior/call.zig"); _ = @import("behavior/cast.zig"); _ = @import("behavior/comptime_memory.zig"); diff --git a/test/behavior/bugs/11213.zig b/test/behavior/bugs/11213.zig @@ -0,0 +1,37 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const testing = std.testing; + +test { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const g: error{Test}!void = error.Test; + + var v: u32 = 0; + hash(&v, g); + try testing.expect(v == 1); +} + +fn hash(v: *u32, key: anytype) void { + const Key = @TypeOf(key); + + if (@typeInfo(Key) == .ErrorSet) { + v.* += 1; + return; + } + + switch (@typeInfo(Key)) { + .ErrorUnion => blk: { + const payload = key catch |err| { + hash(v, err); + break :blk; + }; + + hash(v, payload); + }, + + else => unreachable, + } +}