Commit 7d9e3840bb

Andrew Kelley <andrew@ziglang.org>
2022-02-20 08:08:26
Sema: fix inline break from a non-comptime scope to outer one
Prior to this, the compiler would hit an assertion because the break_inline would not successfully move the compile-time control flow.
1 parent 01638c2
Changed files (3)
src
test
behavior
src/Sema.zig
@@ -964,7 +964,14 @@ fn analyzeBodyInner(
                     break sema.zirBreak(block, inst);
                 }
             },
-            .break_inline => break inst,
+            .break_inline => {
+                if (block.is_comptime) {
+                    break inst;
+                } else {
+                    sema.comptime_break_inst = inst;
+                    return error.ComptimeBreak;
+                }
+            },
             .repeat => {
                 if (block.is_comptime) {
                     // Send comptime control flow back to the beginning of this block.
@@ -3572,8 +3579,20 @@ fn resolveBlockBody(
     if (child_block.is_comptime) {
         return sema.resolveBody(child_block, body, body_inst);
     } else {
-        _ = try sema.analyzeBody(child_block, body);
-        return sema.analyzeBlockBody(parent_block, src, child_block, merges);
+        if (sema.analyzeBodyInner(child_block, body)) |_| {
+            return sema.analyzeBlockBody(parent_block, src, child_block, merges);
+        } else |err| switch (err) {
+            error.ComptimeBreak => {
+                const break_inst = sema.comptime_break_inst;
+                const break_data = sema.code.instructions.items(.data)[break_inst].@"break";
+                if (break_data.block_inst == body_inst) {
+                    return sema.resolveInst(break_data.operand);
+                } else {
+                    return error.ComptimeBreak;
+                }
+            },
+            else => |e| return e,
+        }
     }
 }
 
src/type.zig
@@ -2986,7 +2986,7 @@ pub const Type = extern union {
 
     pub fn containerLayout(ty: Type) std.builtin.TypeInfo.ContainerLayout {
         return switch (ty.tag()) {
-            .tuple => .Auto,
+            .tuple, .empty_struct_literal => .Auto,
             .@"struct" => ty.castTag(.@"struct").?.data.layout,
             .@"union" => ty.castTag(.@"union").?.data.layout,
             .union_tagged => ty.castTag(.union_tagged).?.data.layout,
test/behavior/eval.zig
@@ -763,8 +763,6 @@ fn scalar(x: u32) u32 {
 }
 
 test "comptime assign int to optional int" {
-    if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
     comptime {
         var x: ?i32 = null;
         x = 2;