authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-19 21:49:30+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-20 02:11:02+02:00
log6f0601c79336d688c80a3b8592cf758f3c94a636
tree9e1e5587e83cc7f1d89b3b338d236ec75ff0663a
parent27c63bf433f27b06bed92111cbc96e8574de8d11

stage2: support anon init through error unions and optionals at runtime


2 files changed, 30 insertions(+), 22 deletions(-)

src/Sema.zig+18-10
......@@ -2603,8 +2603,8 @@ fn zirArrayBasePtr(
26032603 const start_ptr = sema.resolveInst(inst_data.operand);
26042604 var base_ptr = start_ptr;
26052605 while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) {
2606 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false),
2607 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false),
2606 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
2607 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
26082608 else => break,
26092609 };
26102610
......@@ -2630,8 +2630,8 @@ fn zirFieldBasePtr(
26302630 const start_ptr = sema.resolveInst(inst_data.operand);
26312631 var base_ptr = start_ptr;
26322632 while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) {
2633 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false),
2634 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false),
2633 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
2634 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
26352635 else => break,
26362636 };
26372637
......@@ -5263,7 +5263,7 @@ fn zirOptionalPayloadPtr(
52635263 const optional_ptr = sema.resolveInst(inst_data.operand);
52645264 const src = inst_data.src();
52655265
5266 return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check);
5266 return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false);
52675267}
52685268
52695269fn analyzeOptionalPayloadPtr(
......@@ -5272,6 +5272,7 @@ fn analyzeOptionalPayloadPtr(
52725272 src: LazySrcLoc,
52735273 optional_ptr: Air.Inst.Ref,
52745274 safety_check: bool,
5275 initializing: bool,
52755276) CompileError!Air.Inst.Ref {
52765277 const optional_ptr_ty = sema.typeOf(optional_ptr);
52775278 assert(optional_ptr_ty.zigTypeTag() == .Pointer);
......@@ -5290,7 +5291,7 @@ fn analyzeOptionalPayloadPtr(
52905291
52915292 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {
52925293 if (try sema.pointerDeref(block, src, pointer_val, optional_ptr_ty)) |val| {
5293 if (safety_check) {
5294 if (!initializing) {
52945295 if (val.isNull()) {
52955296 return sema.fail(block, src, "unable to unwrap null", .{});
52965297 }
......@@ -5308,7 +5309,10 @@ fn analyzeOptionalPayloadPtr(
53085309 const is_non_null = try block.addUnOp(.is_non_null_ptr, optional_ptr);
53095310 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
53105311 }
5311 return block.addTyOp(.optional_payload_ptr, child_pointer, optional_ptr);
5312 return block.addTyOp(if (initializing)
5313 .optional_payload_ptr_set
5314 else
5315 .optional_payload_ptr, child_pointer, optional_ptr);
53125316}
53135317
53145318/// Value in, value out.
......@@ -5412,7 +5416,7 @@ fn zirErrUnionPayloadPtr(
54125416 const operand = sema.resolveInst(inst_data.operand);
54135417 const src = inst_data.src();
54145418
5415 return sema.analyzeErrUnionPayloadPtr(block, src, operand, safety_check);
5419 return sema.analyzeErrUnionPayloadPtr(block, src, operand, safety_check, false);
54165420}
54175421
54185422fn analyzeErrUnionPayloadPtr(
......@@ -5421,6 +5425,7 @@ fn analyzeErrUnionPayloadPtr(
54215425 src: LazySrcLoc,
54225426 operand: Air.Inst.Ref,
54235427 safety_check: bool,
5428 initializing: bool,
54245429) CompileError!Air.Inst.Ref {
54255430 const operand_ty = sema.typeOf(operand);
54265431 assert(operand_ty.zigTypeTag() == .Pointer);
......@@ -5437,7 +5442,7 @@ fn analyzeErrUnionPayloadPtr(
54375442
54385443 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
54395444 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {
5440 if (safety_check) {
5445 if (!initializing) {
54415446 if (val.getError()) |name| {
54425447 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
54435448 }
......@@ -5455,7 +5460,10 @@ fn analyzeErrUnionPayloadPtr(
54555460 const is_non_err = try block.addUnOp(.is_err, operand);
54565461 try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion);
54575462 }
5458 return block.addTyOp(.unwrap_errunion_payload_ptr, operand_pointer_ty, operand);
5463 return block.addTyOp(if (initializing)
5464 .errunion_payload_ptr_set
5465 else
5466 .unwrap_errunion_payload_ptr, operand_pointer_ty, operand);
54595467}
54605468
54615469/// Value in, value out
test/behavior/struct.zig+12-12
......@@ -1202,33 +1202,32 @@ test "for loop over pointers to struct, getting field from struct pointer" {
12021202
12031203test "anon init through error unions and optionals" {
12041204 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1205 if (true) return error.SkipZigTest; // TODO
1205 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
12061206
12071207 const S = struct {
12081208 a: u32,
12091209
12101210 fn foo() anyerror!?anyerror!@This() {
1211 return @This(){ .a = 1 };
1211 return .{ .a = 1 };
12121212 }
12131213 fn bar() ?anyerror![2]u8 {
1214 return [2]u8{ 1, 2 };
1214 return .{ 1, 2 };
12151215 }
12161216
12171217 fn doTheTest() !void {
1218 var a = ((foo() catch unreachable).?) catch unreachable;
1219 var b = (bar().?) catch unreachable;
1218 var a = try (try foo()).?;
1219 var b = try bar().?;
12201220 try expect(a.a + b[1] == 3);
12211221 }
12221222 };
12231223
12241224 try S.doTheTest();
1225 comptime try S.doTheTest();
1225 // comptime try S.doTheTest(); // TODO
12261226}
12271227
12281228test "anon init through optional" {
12291229 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1230 // not sure why this is needed, we only do the test at comptime
1231 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
1230 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
12321231
12331232 const S = struct {
12341233 a: u32,
......@@ -1239,14 +1238,14 @@ test "anon init through optional" {
12391238 try expect(s.?.a == 1);
12401239 }
12411240 };
1242 // try S.doTheTest(); // TODO
1241
1242 try S.doTheTest();
12431243 comptime try S.doTheTest();
12441244}
12451245
12461246test "anon init through error union" {
12471247 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1248 // not sure why this is needed, we only do the test at comptime
1249 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
1248 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
12501249
12511250 const S = struct {
12521251 a: u32,
......@@ -1257,6 +1256,7 @@ test "anon init through error union" {
12571256 try expect((try s).a == 1);
12581257 }
12591258 };
1260 // try S.doTheTest(); // TODO
1259
1260 try S.doTheTest();
12611261 comptime try S.doTheTest();
12621262}