authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-24 17:45:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-24 17:47:39-07:00
log5c68afef94b0b80823e033bd6965fcda74e19ebe
treee66fb82c14c731edce688b50150ccc38b585b729
parent9a1d5001d4bf1f28bd0f23e8b936d677e0e5aac8

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.

2 files changed, 25 insertions(+), 3 deletions(-)

src/AstGen.zig+6-3
...@@ -2671,6 +2671,9 @@ fn varDecl(...@@ -2671,6 +2671,9 @@ fn varDecl(
2671 return &sub_scope.base;2671 return &sub_scope.base;
2672 }2672 }
26732673
2674 const is_comptime = gz.force_comptime or
2675 tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime";
2676
2674 // Detect whether the initialization expression actually uses the2677 // Detect whether the initialization expression actually uses the
2675 // result location pointer.2678 // result location pointer.
2676 var init_scope = gz.makeSubBlock(scope);2679 var init_scope = gz.makeSubBlock(scope);
...@@ -2692,7 +2695,7 @@ fn varDecl(...@@ -2692,7 +2695,7 @@ fn varDecl(
2692 .type_inst = type_inst,2695 .type_inst = type_inst,
2693 .align_inst = align_inst,2696 .align_inst = align_inst,
2694 .is_const = true,2697 .is_const = true,
2695 .is_comptime = gz.force_comptime,2698 .is_comptime = is_comptime,
2696 });2699 });
2697 init_scope.instructions_top = gz.instructions.items.len;2700 init_scope.instructions_top = gz.instructions.items.len;
2698 }2701 }
...@@ -2700,7 +2703,7 @@ fn varDecl(...@@ -2700,7 +2703,7 @@ fn varDecl(
2700 } else {2703 } else {
2701 const alloc = if (align_inst == .none) alloc: {2704 const alloc = if (align_inst == .none) alloc: {
2702 init_scope.instructions_top = gz.instructions.items.len;2705 init_scope.instructions_top = gz.instructions.items.len;
2703 const tag: Zir.Inst.Tag = if (gz.force_comptime)2706 const tag: Zir.Inst.Tag = if (is_comptime)
2704 .alloc_inferred_comptime2707 .alloc_inferred_comptime
2705 else2708 else
2706 .alloc_inferred;2709 .alloc_inferred;
...@@ -2711,7 +2714,7 @@ fn varDecl(...@@ -2711,7 +2714,7 @@ fn varDecl(
2711 .type_inst = .none,2714 .type_inst = .none,
2712 .align_inst = align_inst,2715 .align_inst = align_inst,
2713 .is_const = true,2716 .is_const = true,
2714 .is_comptime = gz.force_comptime,2717 .is_comptime = is_comptime,
2715 });2718 });
2716 init_scope.instructions_top = gz.instructions.items.len;2719 init_scope.instructions_top = gz.instructions.items.len;
2717 break :alloc ref;2720 break :alloc ref;
test/behavior/eval.zig+19
...@@ -859,3 +859,22 @@ test "debug variable type resolved through indirect zero-bit types" {...@@ -859,3 +859,22 @@ test "debug variable type resolved through indirect zero-bit types" {
859 const slice: []const T = &[_]T{};859 const slice: []const T = &[_]T{};
860 _ = slice;860 _ = slice;
861}861}
862
863test "const local with comptime init through array init" {
864 const E1 = enum {
865 A,
866 fn a() void {}
867 };
868
869 const S = struct {
870 fn declarations(comptime T: type) []const std.builtin.Type.Declaration {
871 return @typeInfo(T).Enum.decls;
872 }
873 };
874
875 const decls = comptime [_][]const std.builtin.Type.Declaration{
876 S.declarations(E1),
877 };
878
879 try comptime expect(decls[0][0].name[0] == 'a');
880}