| author | |
| committer | |
| log | 5c68afef94b0b80823e033bd6965fcda74e19ebe |
| tree | e66fb82c14c731edce688b50150ccc38b585b729 |
| parent | 9a1d5001d4bf1f28bd0f23e8b936d677e0e5aac8 |
`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 | 2671 | return &sub_scope.base; |
| 2672 | 2672 | } |
| 2673 | 2673 | |
| 2674 | const is_comptime = gz.force_comptime or | |
| 2675 | tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime"; | |
| 2676 | ||
| 2674 | 2677 | // Detect whether the initialization expression actually uses the |
| 2675 | 2678 | // result location pointer. |
| 2676 | 2679 | var init_scope = gz.makeSubBlock(scope); |
| ... | ... | @@ -2692,7 +2695,7 @@ fn varDecl( |
| 2692 | 2695 | .type_inst = type_inst, |
| 2693 | 2696 | .align_inst = align_inst, |
| 2694 | 2697 | .is_const = true, |
| 2695 | .is_comptime = gz.force_comptime, | |
| 2698 | .is_comptime = is_comptime, | |
| 2696 | 2699 | }); |
| 2697 | 2700 | init_scope.instructions_top = gz.instructions.items.len; |
| 2698 | 2701 | } |
| ... | ... | @@ -2700,7 +2703,7 @@ fn varDecl( |
| 2700 | 2703 | } else { |
| 2701 | 2704 | const alloc = if (align_inst == .none) alloc: { |
| 2702 | 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 | 2707 | .alloc_inferred_comptime |
| 2705 | 2708 | else |
| 2706 | 2709 | .alloc_inferred; |
| ... | ... | @@ -2711,7 +2714,7 @@ fn varDecl( |
| 2711 | 2714 | .type_inst = .none, |
| 2712 | 2715 | .align_inst = align_inst, |
| 2713 | 2716 | .is_const = true, |
| 2714 | .is_comptime = gz.force_comptime, | |
| 2717 | .is_comptime = is_comptime, | |
| 2715 | 2718 | }); |
| 2716 | 2719 | init_scope.instructions_top = gz.instructions.items.len; |
| 2717 | 2720 | break :alloc ref; |
test/behavior/eval.zig+19| ... | ... | @@ -859,3 +859,22 @@ test "debug variable type resolved through indirect zero-bit types" { |
| 859 | 859 | const slice: []const T = &[_]T{}; |
| 860 | 860 | _ = slice; |
| 861 | 861 | } |
| 862 | ||
| 863 | test "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 | } |