| author | |
| committer | |
| log | 273da9efd9238e20da1299789537b00de2f0ebd8 |
| tree | 54905594f55be9fd19a179ab1bcaeb1900d02bc1 |
| parent | a30d283981ae31ed0212ef153f086e07daeffe65 |
when an inferred alloc is passed as the result pointer of a block.4 files changed, 69 insertions(+), 10 deletions(-)
src/AstGen.zig+30-1| ... | @@ -1360,6 +1360,12 @@ fn arrayInitExpr( | ... | @@ -1360,6 +1360,12 @@ fn arrayInitExpr( |
| 1360 | } | 1360 | } |
| 1361 | }, | 1361 | }, |
| 1362 | .block_ptr => |block_gz| { | 1362 | .block_ptr => |block_gz| { |
| 1363 | // This condition is here for the same reason as the above condition in `inferred_ptr`. | ||
| 1364 | // See corresponding logic in structInitExpr. | ||
| 1365 | if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) { | ||
| 1366 | const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon); | ||
| 1367 | return rvalue(gz, rl, result, node); | ||
| 1368 | } | ||
| 1363 | return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array); | 1369 | return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array); |
| 1364 | }, | 1370 | }, |
| 1365 | } | 1371 | } |
| ... | @@ -1604,7 +1610,16 @@ fn structInitExpr( | ... | @@ -1604,7 +1610,16 @@ fn structInitExpr( |
| 1604 | return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst); | 1610 | return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst); |
| 1605 | } | 1611 | } |
| 1606 | }, | 1612 | }, |
| 1607 | .block_ptr => |block_gz| return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr), | 1613 | .block_ptr => |block_gz| { |
| 1614 | // This condition is here for the same reason as the above condition in `inferred_ptr`. | ||
| 1615 | // See corresponding logic in arrayInitExpr. | ||
| 1616 | if (struct_init.ast.type_expr == 0 and astgen.isInferred(block_gz.rl_ptr)) { | ||
| 1617 | const result = try structInitExprRlNone(gz, scope, node, struct_init, .struct_init_anon); | ||
| 1618 | return rvalue(gz, rl, result, node); | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr); | ||
| 1622 | }, | ||
| 1608 | } | 1623 | } |
| 1609 | } | 1624 | } |
| 1610 | 1625 | ||
| ... | @@ -10938,3 +10953,17 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. | ... | @@ -10938,3 +10953,17 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 10938 | } | 10953 | } |
| 10939 | return decl_count; | 10954 | return decl_count; |
| 10940 | } | 10955 | } |
| 10956 | |||
| 10957 | fn isInferred(astgen: *AstGen, ref: Zir.Inst.Ref) bool { | ||
| 10958 | const inst = refToIndex(ref) orelse return false; | ||
| 10959 | const zir_tags = astgen.instructions.items(.tag); | ||
| 10960 | return switch (zir_tags[inst]) { | ||
| 10961 | .alloc_inferred, | ||
| 10962 | .alloc_inferred_mut, | ||
| 10963 | .alloc_inferred_comptime, | ||
| 10964 | .alloc_inferred_comptime_mut, | ||
| 10965 | => true, | ||
| 10966 | |||
| 10967 | else => false, | ||
| 10968 | }; | ||
| 10969 | } |
src/Zir.zig+1-1| ... | @@ -516,7 +516,7 @@ pub const Inst = struct { | ... | @@ -516,7 +516,7 @@ pub const Inst = struct { |
| 516 | /// Same as `store` except provides a source location. | 516 | /// Same as `store` except provides a source location. |
| 517 | /// Uses the `pl_node` union field. Payload is `Bin`. | 517 | /// Uses the `pl_node` union field. Payload is `Bin`. |
| 518 | store_node, | 518 | store_node, |
| 519 | /// This instruction is not really supposed to be emitted from AstGen; nevetheless it | 519 | /// This instruction is not really supposed to be emitted from AstGen; nevertheless it |
| 520 | /// is sometimes emitted due to deficiencies in AstGen. When Sema sees this instruction, | 520 | /// is sometimes emitted due to deficiencies in AstGen. When Sema sees this instruction, |
| 521 | /// it must clean up after AstGen's mess by looking at various context clues and | 521 | /// it must clean up after AstGen's mess by looking at various context clues and |
| 522 | /// then treating it as one of the following: | 522 | /// then treating it as one of the following: |
test/behavior/bugs/5474.zig+6-8| ... | @@ -49,19 +49,17 @@ fn constant() !void { | ... | @@ -49,19 +49,17 @@ fn constant() !void { |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | test "pointer-to-array constness for zero-size elements, var" { | 51 | test "pointer-to-array constness for zero-size elements, var" { |
| 52 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 52 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 53 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 53 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 54 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 54 | |
| 55 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 56 | try mutable(); | 55 | try mutable(); |
| 57 | comptime try mutable(); | 56 | comptime try mutable(); |
| 58 | } | 57 | } |
| 59 | 58 | ||
| 60 | test "pointer-to-array constness for zero-size elements, const" { | 59 | test "pointer-to-array constness for zero-size elements, const" { |
| 61 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 60 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 62 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 61 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 63 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 62 | |
| 64 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 65 | try constant(); | 63 | try constant(); |
| 66 | comptime try constant(); | 64 | comptime try constant(); |
| 67 | } | 65 | } |
test/behavior/tuple.zig+32| ... | @@ -165,3 +165,35 @@ test "array-like initializer for tuple types" { | ... | @@ -165,3 +165,35 @@ test "array-like initializer for tuple types" { |
| 165 | try S.doTheTest(); | 165 | try S.doTheTest(); |
| 166 | comptime try S.doTheTest(); | 166 | comptime try S.doTheTest(); |
| 167 | } | 167 | } |
| 168 | |||
| 169 | test "anon struct as the result from a labeled block" { | ||
| 170 | const S = struct { | ||
| 171 | fn doTheTest() !void { | ||
| 172 | const precomputed = comptime blk: { | ||
| 173 | var x: i32 = 1234; | ||
| 174 | break :blk .{ | ||
| 175 | .x = x, | ||
| 176 | }; | ||
| 177 | }; | ||
| 178 | try expect(precomputed.x == 1234); | ||
| 179 | } | ||
| 180 | }; | ||
| 181 | |||
| 182 | try S.doTheTest(); | ||
| 183 | comptime try S.doTheTest(); | ||
| 184 | } | ||
| 185 | |||
| 186 | test "tuple as the result from a labeled block" { | ||
| 187 | const S = struct { | ||
| 188 | fn doTheTest() !void { | ||
| 189 | const precomputed = comptime blk: { | ||
| 190 | var x: i32 = 1234; | ||
| 191 | break :blk .{x}; | ||
| 192 | }; | ||
| 193 | try expect(precomputed[0] == 1234); | ||
| 194 | } | ||
| 195 | }; | ||
| 196 | |||
| 197 | try S.doTheTest(); | ||
| 198 | comptime try S.doTheTest(); | ||
| 199 | } |