diff --git a/src/AstGen.zig b/src/AstGen.zig index eb724934c9..97ca9f0a12 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -1360,6 +1360,12 @@ fn arrayInitExpr( } }, .block_ptr => |block_gz| { + // This condition is here for the same reason as the above condition in `inferred_ptr`. + // See corresponding logic in structInitExpr. + if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) { + const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon); + return rvalue(gz, rl, result, node); + } return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array); }, } @@ -1604,7 +1610,16 @@ fn structInitExpr( return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst); } }, - .block_ptr => |block_gz| return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr), + .block_ptr => |block_gz| { + // This condition is here for the same reason as the above condition in `inferred_ptr`. + // See corresponding logic in arrayInitExpr. + if (struct_init.ast.type_expr == 0 and astgen.isInferred(block_gz.rl_ptr)) { + const result = try structInitExprRlNone(gz, scope, node, struct_init, .struct_init_anon); + return rvalue(gz, rl, result, node); + } + + return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr); + }, } } @@ -10938,3 +10953,17 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. } return decl_count; } + +fn isInferred(astgen: *AstGen, ref: Zir.Inst.Ref) bool { + const inst = refToIndex(ref) orelse return false; + const zir_tags = astgen.instructions.items(.tag); + return switch (zir_tags[inst]) { + .alloc_inferred, + .alloc_inferred_mut, + .alloc_inferred_comptime, + .alloc_inferred_comptime_mut, + => true, + + else => false, + }; +} diff --git a/src/Zir.zig b/src/Zir.zig index 6a3e88e4b7..acf259607f 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -516,7 +516,7 @@ pub const Inst = struct { /// Same as `store` except provides a source location. /// Uses the `pl_node` union field. Payload is `Bin`. store_node, - /// This instruction is not really supposed to be emitted from AstGen; nevetheless it + /// This instruction is not really supposed to be emitted from AstGen; nevertheless it /// is sometimes emitted due to deficiencies in AstGen. When Sema sees this instruction, /// it must clean up after AstGen's mess by looking at various context clues and /// then treating it as one of the following: diff --git a/test/behavior/bugs/5474.zig b/test/behavior/bugs/5474.zig index 47066aa017..e0384b244c 100644 --- a/test/behavior/bugs/5474.zig +++ b/test/behavior/bugs/5474.zig @@ -49,19 +49,17 @@ fn constant() !void { } test "pointer-to-array constness for zero-size elements, var" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try mutable(); comptime try mutable(); } test "pointer-to-array constness for zero-size elements, const" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try constant(); comptime try constant(); } diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index db2816831d..1c87bdd5b7 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -165,3 +165,35 @@ test "array-like initializer for tuple types" { try S.doTheTest(); comptime try S.doTheTest(); } + +test "anon struct as the result from a labeled block" { + const S = struct { + fn doTheTest() !void { + const precomputed = comptime blk: { + var x: i32 = 1234; + break :blk .{ + .x = x, + }; + }; + try expect(precomputed.x == 1234); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "tuple as the result from a labeled block" { + const S = struct { + fn doTheTest() !void { + const precomputed = comptime blk: { + var x: i32 = 1234; + break :blk .{x}; + }; + try expect(precomputed[0] == 1234); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +}