| author | |
| committer | |
| log | ee149aaa03e586e48c32cce09bf488ae0e88d053 |
| tree | 786f7b54e7e47027ee66e3fd2c412bed4a31b7bf |
| parent | b3aa1ab693ac160a07c44f07c7b90577039860a1 |
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 | } |
| 1608 | 1634 | ||
| ... | @@ -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 unreachable | 1702 | } |
| 1677 | } | 1703 | } |
| 1678 | 1704 | ||
| 1679 | pub fn analyzeStructDecl( | 1705 | pub 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 { |
| 3980 | 3980 | ||
| 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 | } |
| 372 | 372 | ||
| 373 | test "implicitly cast from T to anyerror!?T" { | 373 | test "implicitly cast from T to anyerror!?T" { |
| 374 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 374 | 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; | ||
| 375 | 377 | ||
| 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 { |
| 387 | 389 | ||
| 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; |
| 391 | 393 | ||
| 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 | } |
| 295 | 295 | ||
| 296 | test "error: Zero sized error set returned with value payload crash" { | 296 | test "error: Zero sized error set returned with value payload crash" { |
| 297 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 297 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 298 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 298 | 299 | ||
| 299 | _ = foo3(0) catch {}; | 300 | _ = try foo3(0); |
| 300 | _ = comptime foo3(0) catch {}; | 301 | _ = comptime try foo3(0); |
| 301 | } | 302 | } |
| 302 | 303 | ||
| 303 | const Error = error{}; | 304 | const 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 | |||
| 1241 | test "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 | } |