From e02749224357a33cffcaf9970d14c199adc3d892 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 19 Feb 2022 11:35:49 +0200 Subject: stage2: support anon init through error unions and optionals --- test/behavior/struct.zig | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'test/behavior/struct.zig') diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 3e92b4374b..7428aed62a 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1199,3 +1199,64 @@ test "for loop over pointers to struct, getting field from struct pointer" { }; try S.doTheTest(); } + +test "anon init through error unions and optionals" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + if (true) return error.SkipZigTest; // TODO + + const S = struct { + a: u32, + + fn foo() anyerror!?anyerror!@This() { + return @This(){ .a = 1 }; + } + fn bar() ?anyerror![2]u8 { + return [2]u8{ 1, 2 }; + } + + fn doTheTest() !void { + var a = ((foo() catch unreachable).?) catch unreachable; + var b = (bar().?) catch unreachable; + try expect(a.a + b[1] == 3); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "anon init through optional" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + // not sure why this is needed, we only do the test at comptime + if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; + + const S = struct { + a: u32, + + fn doTheTest() !void { + var s: ?@This() = null; + s = .{ .a = 1 }; + try expect(s.?.a == 1); + } + }; + // try S.doTheTest(); // TODO + comptime try S.doTheTest(); +} + +test "anon init through error union" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + // not sure why this is needed, we only do the test at comptime + if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; + + const S = struct { + a: u32, + + fn doTheTest() !void { + var s: anyerror!@This() = error.Foo; + s = .{ .a = 1 }; + try expect((try s).a == 1); + } + }; + // try S.doTheTest(); // TODO + comptime try S.doTheTest(); +} -- cgit v1.2.3 From 6f0601c79336d688c80a3b8592cf758f3c94a636 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 19 Feb 2022 21:49:30 +0200 Subject: stage2: support anon init through error unions and optionals at runtime --- src/Sema.zig | 28 ++++++++++++++++++---------- test/behavior/struct.zig | 24 ++++++++++++------------ 2 files changed, 30 insertions(+), 22 deletions(-) (limited to 'test/behavior/struct.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 2d9381493a..5dadb94922 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2603,8 +2603,8 @@ fn zirArrayBasePtr( const start_ptr = sema.resolveInst(inst_data.operand); var base_ptr = start_ptr; while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) { - .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false), - .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false), + .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), + .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), else => break, }; @@ -2630,8 +2630,8 @@ fn zirFieldBasePtr( const start_ptr = sema.resolveInst(inst_data.operand); var base_ptr = start_ptr; while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) { - .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false), - .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false), + .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), + .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), else => break, }; @@ -5263,7 +5263,7 @@ fn zirOptionalPayloadPtr( const optional_ptr = sema.resolveInst(inst_data.operand); const src = inst_data.src(); - return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check); + return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false); } fn analyzeOptionalPayloadPtr( @@ -5272,6 +5272,7 @@ fn analyzeOptionalPayloadPtr( src: LazySrcLoc, optional_ptr: Air.Inst.Ref, safety_check: bool, + initializing: bool, ) CompileError!Air.Inst.Ref { const optional_ptr_ty = sema.typeOf(optional_ptr); assert(optional_ptr_ty.zigTypeTag() == .Pointer); @@ -5290,7 +5291,7 @@ fn analyzeOptionalPayloadPtr( if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| { if (try sema.pointerDeref(block, src, pointer_val, optional_ptr_ty)) |val| { - if (safety_check) { + if (!initializing) { if (val.isNull()) { return sema.fail(block, src, "unable to unwrap null", .{}); } @@ -5308,7 +5309,10 @@ fn analyzeOptionalPayloadPtr( const is_non_null = try block.addUnOp(.is_non_null_ptr, optional_ptr); try sema.addSafetyCheck(block, is_non_null, .unwrap_null); } - return block.addTyOp(.optional_payload_ptr, child_pointer, optional_ptr); + return block.addTyOp(if (initializing) + .optional_payload_ptr_set + else + .optional_payload_ptr, child_pointer, optional_ptr); } /// Value in, value out. @@ -5412,7 +5416,7 @@ fn zirErrUnionPayloadPtr( const operand = sema.resolveInst(inst_data.operand); const src = inst_data.src(); - return sema.analyzeErrUnionPayloadPtr(block, src, operand, safety_check); + return sema.analyzeErrUnionPayloadPtr(block, src, operand, safety_check, false); } fn analyzeErrUnionPayloadPtr( @@ -5421,6 +5425,7 @@ fn analyzeErrUnionPayloadPtr( src: LazySrcLoc, operand: Air.Inst.Ref, safety_check: bool, + initializing: bool, ) CompileError!Air.Inst.Ref { const operand_ty = sema.typeOf(operand); assert(operand_ty.zigTypeTag() == .Pointer); @@ -5437,7 +5442,7 @@ fn analyzeErrUnionPayloadPtr( if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| { - if (safety_check) { + if (!initializing) { if (val.getError()) |name| { return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); } @@ -5455,7 +5460,10 @@ fn analyzeErrUnionPayloadPtr( const is_non_err = try block.addUnOp(.is_err, operand); try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion); } - return block.addTyOp(.unwrap_errunion_payload_ptr, operand_pointer_ty, operand); + return block.addTyOp(if (initializing) + .errunion_payload_ptr_set + else + .unwrap_errunion_payload_ptr, operand_pointer_ty, operand); } /// Value in, value out diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 7428aed62a..a3e8bbdab3 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1202,33 +1202,32 @@ test "for loop over pointers to struct, getting field from struct pointer" { test "anon init through error unions and optionals" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (true) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO const S = struct { a: u32, fn foo() anyerror!?anyerror!@This() { - return @This(){ .a = 1 }; + return .{ .a = 1 }; } fn bar() ?anyerror![2]u8 { - return [2]u8{ 1, 2 }; + return .{ 1, 2 }; } fn doTheTest() !void { - var a = ((foo() catch unreachable).?) catch unreachable; - var b = (bar().?) catch unreachable; + var a = try (try foo()).?; + var b = try bar().?; try expect(a.a + b[1] == 3); } }; try S.doTheTest(); - comptime try S.doTheTest(); + // comptime try S.doTheTest(); // TODO } test "anon init through optional" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - // not sure why this is needed, we only do the test at comptime - if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; + if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO const S = struct { a: u32, @@ -1239,14 +1238,14 @@ test "anon init through optional" { try expect(s.?.a == 1); } }; - // try S.doTheTest(); // TODO + + try S.doTheTest(); comptime try S.doTheTest(); } test "anon init through error union" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - // not sure why this is needed, we only do the test at comptime - if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; + if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO const S = struct { a: u32, @@ -1257,6 +1256,7 @@ test "anon init through error union" { try expect((try s).a == 1); } }; - // try S.doTheTest(); // TODO + + try S.doTheTest(); comptime try S.doTheTest(); } -- cgit v1.2.3 From a5ac06268972bd7279a1bb928a40d70cc7d515ed Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 20 Feb 2022 11:25:19 +0200 Subject: stage2: make field/array base ptr work at comptime --- src/Sema.zig | 24 ++++++++++++++++-------- test/behavior/struct.zig | 2 +- 2 files changed, 17 insertions(+), 9 deletions(-) (limited to 'test/behavior/struct.zig') diff --git a/src/Sema.zig b/src/Sema.zig index e7220640a0..b196746c84 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5337,11 +5337,15 @@ fn analyzeOptionalPayloadPtr( }); if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| { + if (initializing) { + return sema.addConstant( + child_pointer, + try Value.Tag.opt_payload_ptr.create(sema.arena, pointer_val), + ); + } if (try sema.pointerDeref(block, src, pointer_val, optional_ptr_ty)) |val| { - if (!initializing) { - if (val.isNull()) { - return sema.fail(block, src, "unable to unwrap null", .{}); - } + if (val.isNull()) { + return sema.fail(block, src, "unable to unwrap null", .{}); } // The same Value represents the pointer to the optional and the payload. return sema.addConstant( @@ -5488,11 +5492,15 @@ fn analyzeErrUnionPayloadPtr( }); if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { + if (initializing) { + return sema.addConstant( + operand_pointer_ty, + try Value.Tag.eu_payload_ptr.create(sema.arena, pointer_val), + ); + } if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| { - if (!initializing) { - if (val.getError()) |name| { - return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); - } + if (val.getError()) |name| { + return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); } return sema.addConstant( diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index a3e8bbdab3..d059cccb60 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1222,7 +1222,7 @@ test "anon init through error unions and optionals" { }; try S.doTheTest(); - // comptime try S.doTheTest(); // TODO + comptime try S.doTheTest(); } test "anon init through optional" { -- cgit v1.2.3