Commit 5c68afef94

Andrew Kelley <andrew@ziglang.org>
2022-03-25 01:45:34
AstGen: fix const locals with comptime initializations
`const foo = comptime ...` generated invalid ZIR when the initialization expression contained an array literal because the validate_array_init_comptime instruction assumed that the corresponding alloc instruction was comptime. The solution is to look slightly ahead and notice that the initialization expression would be comptime-known and affect the alloc instruction tag accordingly.
1 parent 9a1d500
Changed files (2)
src
test
behavior
src/AstGen.zig
@@ -2671,6 +2671,9 @@ fn varDecl(
                 return &sub_scope.base;
             }
 
+            const is_comptime = gz.force_comptime or
+                tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime";
+
             // Detect whether the initialization expression actually uses the
             // result location pointer.
             var init_scope = gz.makeSubBlock(scope);
@@ -2692,7 +2695,7 @@ fn varDecl(
                         .type_inst = type_inst,
                         .align_inst = align_inst,
                         .is_const = true,
-                        .is_comptime = gz.force_comptime,
+                        .is_comptime = is_comptime,
                     });
                     init_scope.instructions_top = gz.instructions.items.len;
                 }
@@ -2700,7 +2703,7 @@ fn varDecl(
             } else {
                 const alloc = if (align_inst == .none) alloc: {
                     init_scope.instructions_top = gz.instructions.items.len;
-                    const tag: Zir.Inst.Tag = if (gz.force_comptime)
+                    const tag: Zir.Inst.Tag = if (is_comptime)
                         .alloc_inferred_comptime
                     else
                         .alloc_inferred;
@@ -2711,7 +2714,7 @@ fn varDecl(
                         .type_inst = .none,
                         .align_inst = align_inst,
                         .is_const = true,
-                        .is_comptime = gz.force_comptime,
+                        .is_comptime = is_comptime,
                     });
                     init_scope.instructions_top = gz.instructions.items.len;
                     break :alloc ref;
test/behavior/eval.zig
@@ -859,3 +859,22 @@ test "debug variable type resolved through indirect zero-bit types" {
     const slice: []const T = &[_]T{};
     _ = slice;
 }
+
+test "const local with comptime init through array init" {
+    const E1 = enum {
+        A,
+        fn a() void {}
+    };
+
+    const S = struct {
+        fn declarations(comptime T: type) []const std.builtin.Type.Declaration {
+            return @typeInfo(T).Enum.decls;
+        }
+    };
+
+    const decls = comptime [_][]const std.builtin.Type.Declaration{
+        S.declarations(E1),
+    };
+
+    try comptime expect(decls[0][0].name[0] == 'a');
+}