authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-18 14:50:40-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-18 14:50:40-04:00
log5765755fcd6bd8570494057255e7d92d489ef35e
tree9b53e9f1ad4d391e318e71a08b1bfafb7fe4024c
parent13321c8070b52afb24f3c1b57eecbb2aa77fc4ec
parentde8f3bc885c7bfd1a084478c1302f0814d98bb62
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11218 from mitchellh/labeled-break

AstGen: labeled blocks should always complete with a normal break

3 files changed, 41 insertions(+), 6 deletions(-)

src/AstGen.zig+3-6
......@@ -1939,7 +1939,7 @@ fn blockExpr(
19391939 if (token_tags[lbrace - 1] == .colon and
19401940 token_tags[lbrace - 2] == .identifier)
19411941 {
1942 return labeledBlockExpr(gz, scope, rl, block_node, statements, .block);
1942 return labeledBlockExpr(gz, scope, rl, block_node, statements);
19431943 }
19441944
19451945 try blockExprStmts(gz, scope, statements);
......@@ -1984,13 +1984,10 @@ fn labeledBlockExpr(
19841984 rl: ResultLoc,
19851985 block_node: Ast.Node.Index,
19861986 statements: []const Ast.Node.Index,
1987 zir_tag: Zir.Inst.Tag,
19881987) InnerError!Zir.Inst.Ref {
19891988 const tracy = trace(@src());
19901989 defer tracy.end();
19911990
1992 assert(zir_tag == .block);
1993
19941991 const astgen = gz.astgen;
19951992 const tree = astgen.tree;
19961993 const main_tokens = tree.nodes.items(.main_token);
......@@ -2004,7 +2001,7 @@ fn labeledBlockExpr(
20042001
20052002 // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct
20062003 // 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);
20082005 try gz.instructions.append(astgen.gpa, block_inst);
20092006
20102007 var block_scope = gz.makeSubBlock(parent_scope);
......@@ -2018,7 +2015,7 @@ fn labeledBlockExpr(
20182015
20192016 try blockExprStmts(&block_scope, &block_scope.base, statements);
20202017 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);
20222019 }
20232020
20242021 if (!block_scope.label.?.used) {
test/behavior.zig+1
......@@ -70,6 +70,7 @@ test {
7070 _ = @import("behavior/bugs/11165.zig");
7171 _ = @import("behavior/bugs/11181.zig");
7272 _ = @import("behavior/bugs/11182.zig");
73 _ = @import("behavior/bugs/11213.zig");
7374 _ = @import("behavior/call.zig");
7475 _ = @import("behavior/cast.zig");
7576 _ = @import("behavior/comptime_memory.zig");
test/behavior/bugs/11213.zig created+37
......@@ -0,0 +1,37 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const testing = std.testing;
4
5test {
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
17fn 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}