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(...@@ -2603,8 +2603,8 @@ fn zirArrayBasePtr(
2603 const start_ptr = sema.resolveInst(inst_data.operand);2603 const start_ptr = sema.resolveInst(inst_data.operand);
2604 var base_ptr = start_ptr;2604 var base_ptr = start_ptr;
2605 while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) {2605 while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) {
2606 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(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),2607 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
2608 else => break,2608 else => break,
2609 };2609 };
26102610
...@@ -2630,8 +2630,8 @@ fn zirFieldBasePtr(...@@ -2630,8 +2630,8 @@ fn zirFieldBasePtr(
2630 const start_ptr = sema.resolveInst(inst_data.operand);2630 const start_ptr = sema.resolveInst(inst_data.operand);
2631 var base_ptr = start_ptr;2631 var base_ptr = start_ptr;
2632 while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) {2632 while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) {
2633 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(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),2634 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
2635 else => break,2635 else => break,
2636 };2636 };
26372637
...@@ -5263,7 +5263,7 @@ fn zirOptionalPayloadPtr(...@@ -5263,7 +5263,7 @@ fn zirOptionalPayloadPtr(
5263 const optional_ptr = sema.resolveInst(inst_data.operand);5263 const optional_ptr = sema.resolveInst(inst_data.operand);
5264 const src = inst_data.src();5264 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);
5267}5267}
52685268
5269fn analyzeOptionalPayloadPtr(5269fn analyzeOptionalPayloadPtr(
...@@ -5272,6 +5272,7 @@ fn analyzeOptionalPayloadPtr(...@@ -5272,6 +5272,7 @@ fn analyzeOptionalPayloadPtr(
5272 src: LazySrcLoc,5272 src: LazySrcLoc,
5273 optional_ptr: Air.Inst.Ref,5273 optional_ptr: Air.Inst.Ref,
5274 safety_check: bool,5274 safety_check: bool,
5275 initializing: bool,
5275) CompileError!Air.Inst.Ref {5276) CompileError!Air.Inst.Ref {
5276 const optional_ptr_ty = sema.typeOf(optional_ptr);5277 const optional_ptr_ty = sema.typeOf(optional_ptr);
5277 assert(optional_ptr_ty.zigTypeTag() == .Pointer);5278 assert(optional_ptr_ty.zigTypeTag() == .Pointer);
...@@ -5290,7 +5291,7 @@ fn analyzeOptionalPayloadPtr(...@@ -5290,7 +5291,7 @@ fn analyzeOptionalPayloadPtr(
52905291
5291 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {5292 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {
5292 if (try sema.pointerDeref(block, src, pointer_val, optional_ptr_ty)) |val| {5293 if (try sema.pointerDeref(block, src, pointer_val, optional_ptr_ty)) |val| {
5293 if (safety_check) {5294 if (!initializing) {
5294 if (val.isNull()) {5295 if (val.isNull()) {
5295 return sema.fail(block, src, "unable to unwrap null", .{});5296 return sema.fail(block, src, "unable to unwrap null", .{});
5296 }5297 }
...@@ -5308,7 +5309,10 @@ fn analyzeOptionalPayloadPtr(...@@ -5308,7 +5309,10 @@ fn analyzeOptionalPayloadPtr(
5308 const is_non_null = try block.addUnOp(.is_non_null_ptr, optional_ptr);5309 const is_non_null = try block.addUnOp(.is_non_null_ptr, optional_ptr);
5309 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);5310 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
5310 }5311 }
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);
5312}5316}
53135317
5314/// Value in, value out.5318/// Value in, value out.
...@@ -5412,7 +5416,7 @@ fn zirErrUnionPayloadPtr(...@@ -5412,7 +5416,7 @@ fn zirErrUnionPayloadPtr(
5412 const operand = sema.resolveInst(inst_data.operand);5416 const operand = sema.resolveInst(inst_data.operand);
5413 const src = inst_data.src();5417 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);
5416}5420}
54175421
5418fn analyzeErrUnionPayloadPtr(5422fn analyzeErrUnionPayloadPtr(
...@@ -5421,6 +5425,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -5421,6 +5425,7 @@ fn analyzeErrUnionPayloadPtr(
5421 src: LazySrcLoc,5425 src: LazySrcLoc,
5422 operand: Air.Inst.Ref,5426 operand: Air.Inst.Ref,
5423 safety_check: bool,5427 safety_check: bool,
5428 initializing: bool,
5424) CompileError!Air.Inst.Ref {5429) CompileError!Air.Inst.Ref {
5425 const operand_ty = sema.typeOf(operand);5430 const operand_ty = sema.typeOf(operand);
5426 assert(operand_ty.zigTypeTag() == .Pointer);5431 assert(operand_ty.zigTypeTag() == .Pointer);
...@@ -5437,7 +5442,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -5437,7 +5442,7 @@ fn analyzeErrUnionPayloadPtr(
54375442
5438 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {5443 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
5439 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {5444 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {
5440 if (safety_check) {5445 if (!initializing) {
5441 if (val.getError()) |name| {5446 if (val.getError()) |name| {
5442 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});5447 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
5443 }5448 }
...@@ -5455,7 +5460,10 @@ fn analyzeErrUnionPayloadPtr(...@@ -5455,7 +5460,10 @@ fn analyzeErrUnionPayloadPtr(
5455 const is_non_err = try block.addUnOp(.is_err, operand);5460 const is_non_err = try block.addUnOp(.is_err, operand);
5456 try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion);5461 try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion);
5457 }5462 }
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);
5459}5467}
54605468
5461/// Value in, value out5469/// 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" {...@@ -1202,33 +1202,32 @@ test "for loop over pointers to struct, getting field from struct pointer" {
12021202
1203test "anon init through error unions and optionals" {1203test "anon init through error unions and optionals" {
1204 if (builtin.zig_backend == .stage1) return error.SkipZigTest;1204 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1205 if (true) return error.SkipZigTest; // TODO1205 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
12061206
1207 const S = struct {1207 const S = struct {
1208 a: u32,1208 a: u32,
12091209
1210 fn foo() anyerror!?anyerror!@This() {1210 fn foo() anyerror!?anyerror!@This() {
1211 return @This(){ .a = 1 };1211 return .{ .a = 1 };
1212 }1212 }
1213 fn bar() ?anyerror![2]u8 {1213 fn bar() ?anyerror![2]u8 {
1214 return [2]u8{ 1, 2 };1214 return .{ 1, 2 };
1215 }1215 }
12161216
1217 fn doTheTest() !void {1217 fn doTheTest() !void {
1218 var a = ((foo() catch unreachable).?) catch unreachable;1218 var a = try (try foo()).?;
1219 var b = (bar().?) catch unreachable;1219 var b = try bar().?;
1220 try expect(a.a + b[1] == 3);1220 try expect(a.a + b[1] == 3);
1221 }1221 }
1222 };1222 };
12231223
1224 try S.doTheTest();1224 try S.doTheTest();
1225 comptime try S.doTheTest();1225 // comptime try S.doTheTest(); // TODO
1226}1226}
12271227
1228test "anon init through optional" {1228test "anon init through optional" {
1229 if (builtin.zig_backend == .stage1) return error.SkipZigTest;1229 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1230 // not sure why this is needed, we only do the test at comptime1230 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
1231 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
12321231
1233 const S = struct {1232 const S = struct {
1234 a: u32,1233 a: u32,
...@@ -1239,14 +1238,14 @@ test "anon init through optional" {...@@ -1239,14 +1238,14 @@ test "anon init through optional" {
1239 try expect(s.?.a == 1);1238 try expect(s.?.a == 1);
1240 }1239 }
1241 };1240 };
1242 // try S.doTheTest(); // TODO1241
1242 try S.doTheTest();
1243 comptime try S.doTheTest();1243 comptime try S.doTheTest();
1244}1244}
12451245
1246test "anon init through error union" {1246test "anon init through error union" {
1247 if (builtin.zig_backend == .stage1) return error.SkipZigTest;1247 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1248 // not sure why this is needed, we only do the test at comptime1248 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
1249 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
12501249
1251 const S = struct {1250 const S = struct {
1252 a: u32,1251 a: u32,
...@@ -1257,6 +1256,7 @@ test "anon init through error union" {...@@ -1257,6 +1256,7 @@ test "anon init through error union" {
1257 try expect((try s).a == 1);1256 try expect((try s).a == 1);
1258 }1257 }
1259 };1258 };
1260 // try S.doTheTest(); // TODO1259
1260 try S.doTheTest();
1261 comptime try S.doTheTest();1261 comptime try S.doTheTest();
1262}1262}