authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-25 12:54:40+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-26 12:51:23-07:00
logee149aaa03e586e48c32cce09bf488ae0e88d053
tree786f7b54e7e47027ee66e3fd2c412bed4a31b7bf
parentb3aa1ab693ac160a07c44f07c7b90577039860a1

stage2: actually coerce in coerce_result_ptr at comptime


5 files changed, 63 insertions(+), 10 deletions(-)

src/Sema.zig+28-3
...@@ -1598,11 +1598,37 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1598,11 +1598,37 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1598 // we cannot do it.1598 // we cannot do it.
1599 if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {1599 if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {
1600 if (ptr_val.isComptimeMutablePtr()) {1600 if (ptr_val.isComptimeMutablePtr()) {
1601 const sentinel_val = try sema.addConstant(pointee_ty, Value.initTag(.unreachable_value));
1602 const coerced = try sema.coerce(block, sema.typeOf(ptr).childType(), sentinel_val, src);
1603
1604 var res_ptr = ptr_val;
1605 var cur_val = (try sema.resolveMaybeUndefVal(block, .unneeded, coerced)).?;
1606 while (true) switch (cur_val.tag()) {
1607 .unreachable_value => break,
1608 .opt_payload => {
1609 res_ptr = try Value.Tag.opt_payload_ptr.create(sema.arena, res_ptr);
1610 cur_val = cur_val.castTag(.opt_payload).?.data;
1611 },
1612 .eu_payload => {
1613 res_ptr = try Value.Tag.eu_payload_ptr.create(sema.arena, res_ptr);
1614 cur_val = cur_val.castTag(.eu_payload).?.data;
1615 },
1616 else => {
1617 if (std.debug.runtime_safety) {
1618 std.debug.panic("unexpected Value tag for coerce_result_ptr: {s}", .{
1619 cur_val.tag(),
1620 });
1621 } else {
1622 unreachable;
1623 }
1624 },
1625 };
1626
1601 const ptr_ty = try Type.ptr(sema.arena, .{1627 const ptr_ty = try Type.ptr(sema.arena, .{
1602 .pointee_type = pointee_ty,1628 .pointee_type = pointee_ty,
1603 .@"addrspace" = addr_space,1629 .@"addrspace" = addr_space,
1604 });1630 });
1605 return sema.addConstant(ptr_ty, ptr_val);1631 return sema.addConstant(ptr_ty, res_ptr);
1606 }1632 }
1607 }1633 }
16081634
...@@ -1673,7 +1699,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1673,7 +1699,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1673 }1699 }
1674 },1700 },
1675 }1701 }
1676 } else unreachable; // TODO should not need else unreachable1702 }
1677}1703}
16781704
1679pub fn analyzeStructDecl(1705pub fn analyzeStructDecl(
...@@ -16937,7 +16963,6 @@ fn wrapErrorUnionPayload(...@@ -16937,7 +16963,6 @@ fn wrapErrorUnionPayload(
16937 const dest_payload_ty = dest_ty.errorUnionPayload();16963 const dest_payload_ty = dest_ty.errorUnionPayload();
16938 const coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);16964 const coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);
16939 if (try sema.resolveMaybeUndefVal(block, inst_src, coerced)) |val| {16965 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));16966 return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
16942 }16967 }
16943 try sema.requireRuntimeBlock(block, inst_src);16968 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 }
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}