| author | |
| committer | |
| log | 5765755fcd6bd8570494057255e7d92d489ef35e |
| tree | 9b53e9f1ad4d391e318e71a08b1bfafb7fe4024c |
| parent | 13321c8070b52afb24f3c1b57eecbb2aa77fc4ec |
| parent | de8f3bc885c7bfd1a084478c1302f0814d98bb62 |
| signature |
AstGen: labeled blocks should always complete with a normal break3 files changed, 41 insertions(+), 6 deletions(-)
src/AstGen.zig+3-6| ... | ... | @@ -1939,7 +1939,7 @@ fn blockExpr( |
| 1939 | 1939 | if (token_tags[lbrace - 1] == .colon and |
| 1940 | 1940 | token_tags[lbrace - 2] == .identifier) |
| 1941 | 1941 | { |
| 1942 | return labeledBlockExpr(gz, scope, rl, block_node, statements, .block); | |
| 1942 | return labeledBlockExpr(gz, scope, rl, block_node, statements); | |
| 1943 | 1943 | } |
| 1944 | 1944 | |
| 1945 | 1945 | try blockExprStmts(gz, scope, statements); |
| ... | ... | @@ -1984,13 +1984,10 @@ fn labeledBlockExpr( |
| 1984 | 1984 | rl: ResultLoc, |
| 1985 | 1985 | block_node: Ast.Node.Index, |
| 1986 | 1986 | statements: []const Ast.Node.Index, |
| 1987 | zir_tag: Zir.Inst.Tag, | |
| 1988 | 1987 | ) InnerError!Zir.Inst.Ref { |
| 1989 | 1988 | const tracy = trace(@src()); |
| 1990 | 1989 | defer tracy.end(); |
| 1991 | 1990 | |
| 1992 | assert(zir_tag == .block); | |
| 1993 | ||
| 1994 | 1991 | const astgen = gz.astgen; |
| 1995 | 1992 | const tree = astgen.tree; |
| 1996 | 1993 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2004,7 +2001,7 @@ fn labeledBlockExpr( |
| 2004 | 2001 | |
| 2005 | 2002 | // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct |
| 2006 | 2003 | // so that break statements can reference it. |
| 2007 | const block_inst = try gz.makeBlockInst(zir_tag, block_node); | |
| 2004 | const block_inst = try gz.makeBlockInst(.block, block_node); | |
| 2008 | 2005 | try gz.instructions.append(astgen.gpa, block_inst); |
| 2009 | 2006 | |
| 2010 | 2007 | var block_scope = gz.makeSubBlock(parent_scope); |
| ... | ... | @@ -2018,7 +2015,7 @@ fn labeledBlockExpr( |
| 2018 | 2015 | |
| 2019 | 2016 | try blockExprStmts(&block_scope, &block_scope.base, statements); |
| 2020 | 2017 | if (!block_scope.endsWithNoReturn()) { |
| 2021 | _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); | |
| 2018 | _ = try block_scope.addBreak(.@"break", block_inst, .void_value); | |
| 2022 | 2019 | } |
| 2023 | 2020 | |
| 2024 | 2021 | if (!block_scope.label.?.used) { |
test/behavior.zig+1| ... | ... | @@ -70,6 +70,7 @@ test { |
| 70 | 70 | _ = @import("behavior/bugs/11165.zig"); |
| 71 | 71 | _ = @import("behavior/bugs/11181.zig"); |
| 72 | 72 | _ = @import("behavior/bugs/11182.zig"); |
| 73 | _ = @import("behavior/bugs/11213.zig"); | |
| 73 | 74 | _ = @import("behavior/call.zig"); |
| 74 | 75 | _ = @import("behavior/cast.zig"); |
| 75 | 76 | _ = @import("behavior/comptime_memory.zig"); |
test/behavior/bugs/11213.zig created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const testing = std.testing; | |
| 4 | ||
| 5 | test { | |
| 6 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 7 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 9 | ||
| 10 | const g: error{Test}!void = error.Test; | |
| 11 | ||
| 12 | var v: u32 = 0; | |
| 13 | hash(&v, g); | |
| 14 | try testing.expect(v == 1); | |
| 15 | } | |
| 16 | ||
| 17 | fn hash(v: *u32, key: anytype) void { | |
| 18 | const Key = @TypeOf(key); | |
| 19 | ||
| 20 | if (@typeInfo(Key) == .ErrorSet) { | |
| 21 | v.* += 1; | |
| 22 | return; | |
| 23 | } | |
| 24 | ||
| 25 | switch (@typeInfo(Key)) { | |
| 26 | .ErrorUnion => blk: { | |
| 27 | const payload = key catch |err| { | |
| 28 | hash(v, err); | |
| 29 | break :blk; | |
| 30 | }; | |
| 31 | ||
| 32 | hash(v, payload); | |
| 33 | }, | |
| 34 | ||
| 35 | else => unreachable, | |
| 36 | } | |
| 37 | } |