authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-26 14:52:45-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-26 14:52:45-05:00
log8349a644d0b9d4b2d58d736a14cdcc567a9e9b89
tree419fe3dc7cab67d43f0cc5b85040340476ab42a1
parentb3aa1ab693ac160a07c44f07c7b90577039860a1
parentbf5c055562b88f1a686815c85d2a29c0889a97ee
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10986 from Vexu/stage2

stage2: actually coerce in coerce_result_ptr at comptime

8 files changed, 67 insertions(+), 39 deletions(-)

src/Sema.zig+12-17
...@@ -1593,27 +1593,16 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1593,27 +1593,16 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1593 }1593 }
1594 }1594 }
15951595
1596 // We would like to rely on the mechanism below even for comptime values.
1597 // However in the case that the pointer points to comptime-mutable value,
1598 // we cannot do it.
1599 if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {
1600 if (ptr_val.isComptimeMutablePtr()) {
1601 const ptr_ty = try Type.ptr(sema.arena, .{
1602 .pointee_type = pointee_ty,
1603 .@"addrspace" = addr_space,
1604 });
1605 return sema.addConstant(ptr_ty, ptr_val);
1606 }
1607 }
1608
1609 // Make a dummy store through the pointer to test the coercion.1596 // Make a dummy store through the pointer to test the coercion.
1610 // We will then use the generated instructions to decide what1597 // We will then use the generated instructions to decide what
1611 // kind of transformations to make on the result pointer.1598 // kind of transformations to make on the result pointer.
1612 var trash_block = block.makeSubBlock();1599 var trash_block = block.makeSubBlock();
1600 trash_block.is_comptime = false;
1613 defer trash_block.instructions.deinit(sema.gpa);1601 defer trash_block.instructions.deinit(sema.gpa);
16141602
1603 const dummy_ptr = try trash_block.addTy(.alloc, sema.typeOf(ptr));
1615 const dummy_operand = try trash_block.addBitCast(pointee_ty, .void_value);1604 const dummy_operand = try trash_block.addBitCast(pointee_ty, .void_value);
1616 try sema.storePtr(&trash_block, src, ptr, dummy_operand);1605 try sema.storePtr(&trash_block, src, dummy_ptr, dummy_operand);
16171606
1618 {1607 {
1619 const air_tags = sema.air_instructions.items(.tag);1608 const air_tags = sema.air_instructions.items(.tag);
...@@ -1644,6 +1633,9 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1644,6 +1633,9 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1644 switch (air_tags[trash_inst]) {1633 switch (air_tags[trash_inst]) {
1645 .bitcast => {1634 .bitcast => {
1646 if (Air.indexToRef(trash_inst) == dummy_operand) {1635 if (Air.indexToRef(trash_inst) == dummy_operand) {
1636 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
1637 return sema.addConstant(ptr_ty, ptr_val);
1638 }
1647 return sema.bitCast(block, ptr_ty, new_ptr, src);1639 return sema.bitCast(block, ptr_ty, new_ptr, src);
1648 }1640 }
1649 const ty_op = air_datas[trash_inst].ty_op;1641 const ty_op = air_datas[trash_inst].ty_op;
...@@ -1652,7 +1644,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1652,7 +1644,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1652 .pointee_type = operand_ty,1644 .pointee_type = operand_ty,
1653 .@"addrspace" = addr_space,1645 .@"addrspace" = addr_space,
1654 });1646 });
1655 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src);1647 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
1648 new_ptr = try sema.addConstant(ptr_operand_ty, ptr_val);
1649 } else {
1650 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src);
1651 }
1656 },1652 },
1657 .wrap_optional => {1653 .wrap_optional => {
1658 new_ptr = try sema.analyzeOptionalPayloadPtr(block, src, new_ptr, false, true);1654 new_ptr = try sema.analyzeOptionalPayloadPtr(block, src, new_ptr, false, true);
...@@ -1673,7 +1669,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1673,7 +1669,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1673 }1669 }
1674 },1670 },
1675 }1671 }
1676 } else unreachable; // TODO should not need else unreachable1672 }
1677}1673}
16781674
1679pub fn analyzeStructDecl(1675pub fn analyzeStructDecl(
...@@ -16937,7 +16933,6 @@ fn wrapErrorUnionPayload(...@@ -16937,7 +16933,6 @@ fn wrapErrorUnionPayload(
16937 const dest_payload_ty = dest_ty.errorUnionPayload();16933 const dest_payload_ty = dest_ty.errorUnionPayload();
16938 const coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);16934 const coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);
16939 if (try sema.resolveMaybeUndefVal(block, inst_src, coerced)) |val| {16935 if (try sema.resolveMaybeUndefVal(block, inst_src, coerced)) |val| {
16940 if (val.isUndef()) return sema.addConstUndef(dest_ty);
16941 return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));16936 return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
16942 }16937 }
16943 try sema.requireRuntimeBlock(block, inst_src);16938 try sema.requireRuntimeBlock(block, inst_src);
src/type.zig+2-2
...@@ -3980,7 +3980,7 @@ pub const Type = extern union {...@@ -3980,7 +3980,7 @@ pub const Type = extern union {
39803980
3981 pub fn structFields(ty: Type) Module.Struct.Fields {3981 pub fn structFields(ty: Type) Module.Struct.Fields {
3982 switch (ty.tag()) {3982 switch (ty.tag()) {
3983 .empty_struct => return .{},3983 .empty_struct, .empty_struct_literal => return .{},
3984 .@"struct" => {3984 .@"struct" => {
3985 const struct_obj = ty.castTag(.@"struct").?.data;3985 const struct_obj = ty.castTag(.@"struct").?.data;
3986 assert(struct_obj.haveFieldTypes());3986 assert(struct_obj.haveFieldTypes());
...@@ -3996,7 +3996,7 @@ pub const Type = extern union {...@@ -3996,7 +3996,7 @@ pub const Type = extern union {
3996 const struct_obj = ty.castTag(.@"struct").?.data;3996 const struct_obj = ty.castTag(.@"struct").?.data;
3997 return struct_obj.fields.count();3997 return struct_obj.fields.count();
3998 },3998 },
3999 .empty_struct => return 0,3999 .empty_struct, .empty_struct_literal => return 0,
4000 .tuple => return ty.castTag(.tuple).?.data.types.len,4000 .tuple => return ty.castTag(.tuple).?.data.types.len,
4001 else => unreachable,4001 else => unreachable,
4002 }4002 }
src/value.zig+14-9
...@@ -791,19 +791,24 @@ pub const Value = extern union {...@@ -791,19 +791,24 @@ pub const Value = extern union {
791 return decl_val.toAllocatedBytes(decl.ty, allocator);791 return decl_val.toAllocatedBytes(decl.ty, allocator);
792 },792 },
793 .the_only_possible_value => return &[_]u8{},793 .the_only_possible_value => return &[_]u8{},
794 .slice => return toAllocatedBytes(val.castTag(.slice).?.data.ptr, ty, allocator),794 .slice => {
795 else => {795 const slice = val.castTag(.slice).?.data;
796 const result = try allocator.alloc(u8, @intCast(usize, ty.arrayLen()));796 return arrayToAllocatedBytes(slice.ptr, slice.len.toUnsignedInt(), allocator);
797 var elem_value_buf: ElemValueBuffer = undefined;
798 for (result) |*elem, i| {
799 const elem_val = val.elemValueBuffer(i, &elem_value_buf);
800 elem.* = @intCast(u8, elem_val.toUnsignedInt());
801 }
802 return result;
803 },797 },
798 else => return arrayToAllocatedBytes(val, ty.arrayLen(), allocator),
804 }799 }
805 }800 }
806801
802 fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator) ![]u8 {
803 const result = try allocator.alloc(u8, @intCast(usize, len));
804 var elem_value_buf: ElemValueBuffer = undefined;
805 for (result) |*elem, i| {
806 const elem_val = val.elemValueBuffer(i, &elem_value_buf);
807 elem.* = @intCast(u8, elem_val.toUnsignedInt());
808 }
809 return result;
810 }
811
807 pub const ToTypeBuffer = Type.Payload.Bits;812 pub const ToTypeBuffer = Type.Payload.Bits;
808813
809 /// Asserts that the value is representable as a type.814 /// Asserts that the value is representable as a type.
test/behavior.zig+3-3
...@@ -127,8 +127,11 @@ test {...@@ -127,8 +127,11 @@ test {
127 _ = @import("behavior/bugs/726.zig");127 _ = @import("behavior/bugs/726.zig");
128 _ = @import("behavior/bugs/1421.zig");128 _ = @import("behavior/bugs/1421.zig");
129 _ = @import("behavior/bugs/1442.zig");129 _ = @import("behavior/bugs/1442.zig");
130 _ = @import("behavior/bugs/1607.zig");
130 _ = @import("behavior/bugs/2114.zig");131 _ = @import("behavior/bugs/2114.zig");
132 _ = @import("behavior/bugs/3384.zig");
131 _ = @import("behavior/bugs/3742.zig");133 _ = @import("behavior/bugs/3742.zig");
134 _ = @import("behavior/bugs/5398.zig");
132 _ = @import("behavior/struct_contains_null_ptr_itself.zig");135 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
133 _ = @import("behavior/switch_prong_err_enum.zig");136 _ = @import("behavior/switch_prong_err_enum.zig");
134 _ = @import("behavior/switch_prong_implicit_cast.zig");137 _ = @import("behavior/switch_prong_implicit_cast.zig");
...@@ -147,11 +150,8 @@ test {...@@ -147,11 +150,8 @@ test {
147 _ = @import("behavior/bugs/828.zig");150 _ = @import("behavior/bugs/828.zig");
148 _ = @import("behavior/bugs/920.zig");151 _ = @import("behavior/bugs/920.zig");
149 _ = @import("behavior/bugs/1120.zig");152 _ = @import("behavior/bugs/1120.zig");
150 _ = @import("behavior/bugs/1607.zig");
151 _ = @import("behavior/bugs/1851.zig");153 _ = @import("behavior/bugs/1851.zig");
152 _ = @import("behavior/bugs/3384.zig");
153 _ = @import("behavior/bugs/3779.zig");154 _ = @import("behavior/bugs/3779.zig");
154 _ = @import("behavior/bugs/5398.zig");
155 _ = @import("behavior/bugs/5413.zig");155 _ = @import("behavior/bugs/5413.zig");
156 _ = @import("behavior/bugs/5487.zig");156 _ = @import("behavior/bugs/5487.zig");
157 _ = @import("behavior/bugs/6456.zig");157 _ = @import("behavior/bugs/6456.zig");
test/behavior/bugs/5398.zig+3-3
...@@ -25,7 +25,7 @@ test "assignment of field with padding" {...@@ -25,7 +25,7 @@ test "assignment of field with padding" {
25 .emits_shadows = false,25 .emits_shadows = false,
26 },26 },
27 };27 };
28 try testing.expectEqual(false, renderable.material.transparent);28 try testing.expect(false == renderable.material.transparent);
29 try testing.expectEqual(false, renderable.material.emits_shadows);29 try testing.expect(false == renderable.material.emits_shadows);
30 try testing.expectEqual(true, renderable.material.render_color);30 try testing.expect(true == renderable.material.render_color);
31}31}
test/behavior/cast.zig+4-2
...@@ -371,7 +371,9 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {...@@ -371,7 +371,9 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {
371}371}
372372
373test "implicitly cast from T to anyerror!?T" {373test "implicitly cast from T to anyerror!?T" {
374 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
375 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
376 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
375377
376 try castToOptionalTypeError(1);378 try castToOptionalTypeError(1);
377 comptime try castToOptionalTypeError(1);379 comptime try castToOptionalTypeError(1);
...@@ -387,7 +389,7 @@ fn castToOptionalTypeError(z: i32) !void {...@@ -387,7 +389,7 @@ fn castToOptionalTypeError(z: i32) !void {
387389
388 const f = z;390 const f = z;
389 const g: anyerror!?i32 = f;391 const g: anyerror!?i32 = f;
390 _ = g catch {};392 _ = try g;
391393
392 const a = A{ .a = z };394 const a = A{ .a = z };
393 const b: anyerror!?A = a;395 const b: anyerror!?A = a;
test/behavior/error.zig+4-3
...@@ -294,10 +294,11 @@ fn quux_1() !i32 {...@@ -294,10 +294,11 @@ fn quux_1() !i32 {
294}294}
295295
296test "error: Zero sized error set returned with value payload crash" {296test "error: Zero sized error set returned with value payload crash" {
297 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO297 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
298 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
298299
299 _ = foo3(0) catch {};300 _ = try foo3(0);
300 _ = comptime foo3(0) catch {};301 _ = comptime try foo3(0);
301}302}
302303
303const Error = error{};304const Error = error{};
test/behavior/struct.zig+25
...@@ -1237,3 +1237,28 @@ test "anon init through error union" {...@@ -1237,3 +1237,28 @@ test "anon init through error union" {
1237 try S.doTheTest();1237 try S.doTheTest();
1238 comptime try S.doTheTest();1238 comptime try S.doTheTest();
1239}1239}
1240
1241test "typed init through error unions and optionals" {
1242 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1243 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
1244
1245 const S = struct {
1246 a: u32,
1247
1248 fn foo() anyerror!?anyerror!@This() {
1249 return @This(){ .a = 1 };
1250 }
1251 fn bar() ?anyerror![2]u8 {
1252 return [2]u8{ 1, 2 };
1253 }
1254
1255 fn doTheTest() !void {
1256 var a = try (try foo()).?;
1257 var b = try bar().?;
1258 try expect(a.a + b[1] == 3);
1259 }
1260 };
1261
1262 try S.doTheTest();
1263 comptime try S.doTheTest();
1264}