authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-11 14:17:22+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-11 14:17:22+03:00
logc9e1360cdba2bc0c20dc04a3d22fbc0002bcd70b
tree38584014ebb7aa8bf3184fa5bc4d08f05c38d19e
parent2a41b1449b724aa10290b9ec735c89405b627960

Sema: add "cannot convert to payload type" error notes


14 files changed, 145 insertions(+), 96 deletions(-)

src/Sema.zig+35-2
...@@ -2749,7 +2749,15 @@ fn ensureResultUsed(...@@ -2749,7 +2749,15 @@ fn ensureResultUsed(
2749 const operand_ty = sema.typeOf(operand);2749 const operand_ty = sema.typeOf(operand);
2750 switch (operand_ty.zigTypeTag()) {2750 switch (operand_ty.zigTypeTag()) {
2751 .Void, .NoReturn => return,2751 .Void, .NoReturn => return,
2752 .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is ignored. consider using `try`, `catch`, or `if`", .{}),2752 .ErrorSet, .ErrorUnion => {
2753 const msg = msg: {
2754 const msg = try sema.errMsg(block, src, "error is ignored", .{});
2755 errdefer msg.destroy(sema.gpa);
2756 try sema.errNote(block, src, msg, "consider using `try`, `catch`, or `if`", .{});
2757 break :msg msg;
2758 };
2759 return sema.failWithOwnedErrorMsg(block, msg);
2760 },
2753 else => return sema.fail(block, src, "expression value is ignored", .{}),2761 else => return sema.fail(block, src, "expression value is ignored", .{}),
2754 }2762 }
2755}2763}
...@@ -2763,7 +2771,15 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -2763,7 +2771,15 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
2763 const src = inst_data.src();2771 const src = inst_data.src();
2764 const operand_ty = sema.typeOf(operand);2772 const operand_ty = sema.typeOf(operand);
2765 switch (operand_ty.zigTypeTag()) {2773 switch (operand_ty.zigTypeTag()) {
2766 .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is discarded. consider using `try`, `catch`, or `if`", .{}),2774 .ErrorSet, .ErrorUnion => {
2775 const msg = msg: {
2776 const msg = try sema.errMsg(block, src, "error is discarded", .{});
2777 errdefer msg.destroy(sema.gpa);
2778 try sema.errNote(block, src, msg, "consider using `try`, `catch`, or `if`", .{});
2779 break :msg msg;
2780 };
2781 return sema.failWithOwnedErrorMsg(block, msg);
2782 },
2767 else => return,2783 else => return,
2768 }2784 }
2769}2785}
...@@ -20402,6 +20418,23 @@ fn coerceExtra(...@@ -20402,6 +20418,23 @@ fn coerceExtra(
20402 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) });20418 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) });
20403 errdefer msg.destroy(sema.gpa);20419 errdefer msg.destroy(sema.gpa);
2040420420
20421 // E!T to T
20422 if (inst_ty.zigTypeTag() == .ErrorUnion and
20423 (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
20424 {
20425 try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{});
20426 try sema.errNote(block, inst_src, msg, "consider using `try`, `catch`, or `if`", .{});
20427 }
20428
20429 // ?T to T
20430 var buf: Type.Payload.ElemType = undefined;
20431 if (inst_ty.zigTypeTag() == .Optional and
20432 (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(&buf), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
20433 {
20434 try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{});
20435 try sema.errNote(block, inst_src, msg, "consider using `.?`, `orelse`, or `if`", .{});
20436 }
20437
20405 try in_memory_result.report(sema, block, inst_src, msg);20438 try in_memory_result.report(sema, block, inst_src, msg);
20406 break :msg msg;20439 break :msg msg;
20407 };20440 };
test/cases/compile_errors/assigning_to_struct_or_union_fields_that_are_not_optionals_with_a_function_that_returns_an_optional.zig created+23
...@@ -0,0 +1,23 @@
1fn maybe(is: bool) ?u8 {
2 if (is) return @as(u8, 10) else return null;
3}
4const U = union {
5 Ye: u8,
6};
7const S = struct {
8 num: u8,
9};
10export fn entry() void {
11 var u = U{ .Ye = maybe(false) };
12 var s = S{ .num = maybe(false) };
13 _ = u;
14 _ = s;
15}
16
17// error
18// backend=stage2
19// target=native
20//
21// :11:27: error: expected type 'u8', found '?u8'
22// :11:27: note: cannot convert optional to payload type
23// :11:27: note: consider using `.?`, `orelse`, or `if`
test/cases/compile_errors/discarding_error_value.zig+2-1
...@@ -9,4 +9,5 @@ fn foo() !void {...@@ -9,4 +9,5 @@ fn foo() !void {
9// backend=stage29// backend=stage2
10// target=native10// target=native
11//11//
12// :2:12: error: error is discarded. consider using `try`, `catch`, or `if`12// :2:12: error: error is discarded
13// :2:12: note: consider using `try`, `catch`, or `if`
test/cases/compile_errors/ignored_deferred_function_call.zig+2-1
...@@ -7,4 +7,5 @@ fn bar() anyerror!i32 { return 0; }...@@ -7,4 +7,5 @@ fn bar() anyerror!i32 { return 0; }
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:14: error: error is ignored. consider using `try`, `catch`, or `if`10// :2:14: error: error is ignored
11// :2:14: note: consider using `try`, `catch`, or `if`
test/cases/compile_errors/ignored_expression_in_while_continuation.zig+6-3
...@@ -17,6 +17,9 @@ fn bad() anyerror!void {...@@ -17,6 +17,9 @@ fn bad() anyerror!void {
17// backend=stage217// backend=stage2
18// target=native18// target=native
19//19//
20// :2:24: error: error is ignored. consider using `try`, `catch`, or `if`20// :2:24: error: error is ignored
21// :6:25: error: error is ignored. consider using `try`, `catch`, or `if`21// :2:24: note: consider using `try`, `catch`, or `if`
22// :10:25: error: error is ignored. consider using `try`, `catch`, or `if`22// :6:25: error: error is ignored
23// :6:25: note: consider using `try`, `catch`, or `if`
24// :10:25: error: error is ignored
25// :10:25: note: consider using `try`, `catch`, or `if`
test/cases/compile_errors/issue_5618_coercion_of_optional_anyopaque_to_anyopaque_must_fail.zig created+14
...@@ -0,0 +1,14 @@
1export fn foo() void {
2 var u: ?*anyopaque = null;
3 var v: *anyopaque = undefined;
4 v = u;
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :4:9: error: expected type '*anyopaque', found '?*anyopaque'
12// :4:9: note: cannot convert optional to payload type
13// :4:9: note: consider using `.?`, `orelse`, or `if`
14// :4:9: note: '?*anyopaque' could have null values which are illegal in type '*anyopaque'
test/cases/compile_errors/regression_test_2980_base_type_u32_is_not_type_checked_properly_when_assigning_a_value_within_a_struct.zig created+23
...@@ -0,0 +1,23 @@
1const Foo = struct {
2 ptr: ?*usize,
3 uval: u32,
4};
5fn get_uval(x: u32) !u32 {
6 _ = x;
7 return error.NotFound;
8}
9export fn entry() void {
10 const afoo = Foo{
11 .ptr = null,
12 .uval = get_uval(42),
13 };
14 _ = afoo;
15}
16
17// error
18// backend=stage2
19// target=native
20//
21// :12:25: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'
22// :12:25: note: cannot convert error union to payload type
23// :12:25: note: consider using `try`, `catch`, or `if`
test/cases/compile_errors/result_location_incompatibility_mismatching_handle_is_ptr.zig created+20
...@@ -0,0 +1,20 @@
1export fn entry() void {
2 var damn = Container{
3 .not_optional = getOptional(),
4 };
5 _ = damn;
6}
7pub fn getOptional() ?i32 {
8 return 0;
9}
10pub const Container = struct {
11 not_optional: i32,
12};
13
14// error
15// backend=stage2
16// target=native
17//
18// :3:36: error: expected type 'i32', found '?i32'
19// :3:36: note: cannot convert optional to payload type
20// :3:36: note: consider using `.?`, `orelse`, or `if`
test/cases/compile_errors/result_location_incompatibility_mismatching_handle_is_ptr_generic_call.zig created+20
...@@ -0,0 +1,20 @@
1export fn entry() void {
2 var damn = Container{
3 .not_optional = getOptional(i32),
4 };
5 _ = damn;
6}
7pub fn getOptional(comptime T: type) ?T {
8 return 0;
9}
10pub const Container = struct {
11 not_optional: i32,
12};
13
14// error
15// backend=stage2
16// target=native
17//
18// :3:36: error: expected type 'i32', found '?i32'
19// :3:36: note: cannot convert optional to payload type
20// :3:36: note: consider using `.?`, `orelse`, or `if`
test/cases/compile_errors/stage1/obj/assigning_to_struct_or_union_fields_that_are_not_optionals_with_a_function_that_returns_an_optional.zig deleted-21
...@@ -1,21 +0,0 @@
1fn maybe(is: bool) ?u8 {
2 if (is) return @as(u8, 10) else return null;
3}
4const U = union {
5 Ye: u8,
6};
7const S = struct {
8 num: u8,
9};
10export fn entry() void {
11 var u = U{ .Ye = maybe(false) };
12 var s = S{ .num = maybe(false) };
13 _ = u;
14 _ = s;
15}
16
17// error
18// backend=stage1
19// target=native
20//
21// tmp.zig:11:27: error: cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type 'u8', found '?u8'
test/cases/compile_errors/stage1/obj/issue_5618_coercion_of_optional_anyopaque_to_anyopaque_must_fail.zig deleted-11
...@@ -1,11 +0,0 @@
1export fn foo() void {
2 var u: ?*anyopaque = null;
3 var v: *anyopaque = undefined;
4 v = u;
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:4:9: error: cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type '*anyopaque', found '?*anyopaque'
test/cases/compile_errors/stage1/obj/regression_test_2980_base_type_u32_is_not_type_checked_properly_when_assigning_a_value_within_a_struct.zig deleted-21
...@@ -1,21 +0,0 @@
1const Foo = struct {
2 ptr: ?*usize,
3 uval: u32,
4};
5fn get_uval(x: u32) !u32 {
6 _ = x;
7 return error.NotFound;
8}
9export fn entry() void {
10 const afoo = Foo{
11 .ptr = null,
12 .uval = get_uval(42),
13 };
14 _ = afoo;
15}
16
17// error
18// backend=stage1
19// target=native
20//
21// tmp.zig:12:25: error: cannot convert error union to payload type. consider using `try`, `catch`, or `if`. expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'
test/cases/compile_errors/stage1/obj/result_location_incompatibility_mismatching_handle_is_ptr.zig deleted-18
...@@ -1,18 +0,0 @@
1export fn entry() void {
2 var damn = Container{
3 .not_optional = getOptional(),
4 };
5 _ = damn;
6}
7pub fn getOptional() ?i32 {
8 return 0;
9}
10pub const Container = struct {
11 not_optional: i32,
12};
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:3:36: error: cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type 'i32', found '?i32'
test/cases/compile_errors/stage1/obj/result_location_incompatibility_mismatching_handle_is_ptr_generic_call.zig deleted-18
...@@ -1,18 +0,0 @@
1export fn entry() void {
2 var damn = Container{
3 .not_optional = getOptional(i32),
4 };
5 _ = damn;
6}
7pub fn getOptional(comptime T: type) ?T {
8 return 0;
9}
10pub const Container = struct {
11 not_optional: i32,
12};
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:3:36: error: cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type 'i32', found '?i32'