| author | |
| committer | |
| log | c9e1360cdba2bc0c20dc04a3d22fbc0002bcd70b |
| tree | 38584014ebb7aa8bf3184fa5bc4d08f05c38d19e |
| parent | 2a41b1449b724aa10290b9ec735c89405b627960 |
14 files changed, 145 insertions(+), 96 deletions(-)
src/Sema.zig+35-2| ... | ... | @@ -2749,7 +2749,15 @@ fn ensureResultUsed( |
| 2749 | 2749 | const operand_ty = sema.typeOf(operand); |
| 2750 | 2750 | switch (operand_ty.zigTypeTag()) { |
| 2751 | 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 | 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 | 2771 | const src = inst_data.src(); |
| 2764 | 2772 | const operand_ty = sema.typeOf(operand); |
| 2765 | 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 | 2783 | else => return, |
| 2768 | 2784 | } |
| 2769 | 2785 | } |
| ... | ... | @@ -20402,6 +20418,23 @@ fn coerceExtra( |
| 20402 | 20418 | const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) }); |
| 20403 | 20419 | errdefer msg.destroy(sema.gpa); |
| 20404 | 20420 | |
| 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 | 20438 | try in_memory_result.report(sema, block, inst_src, msg); |
| 20406 | 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 @@ |
| 1 | fn maybe(is: bool) ?u8 { | |
| 2 | if (is) return @as(u8, 10) else return null; | |
| 3 | } | |
| 4 | const U = union { | |
| 5 | Ye: u8, | |
| 6 | }; | |
| 7 | const S = struct { | |
| 8 | num: u8, | |
| 9 | }; | |
| 10 | export 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 | 9 | // backend=stage2 |
| 10 | 10 | // 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 | 7 | // backend=stage2 |
| 8 | 8 | // 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 | 17 | // backend=stage2 |
| 18 | 18 | // target=native |
| 19 | 19 | // |
| 20 | // :2:24: error: error is ignored. consider using `try`, `catch`, or `if` | |
| 21 | // :6:25: error: error is ignored. consider using `try`, `catch`, or `if` | |
| 22 | // :10:25: error: error is ignored. consider using `try`, `catch`, or `if` | |
| 20 | // :2:24: error: error is ignored | |
| 21 | // :2:24: note: 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 @@ |
| 1 | export 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 @@ |
| 1 | const Foo = struct { | |
| 2 | ptr: ?*usize, | |
| 3 | uval: u32, | |
| 4 | }; | |
| 5 | fn get_uval(x: u32) !u32 { | |
| 6 | _ = x; | |
| 7 | return error.NotFound; | |
| 8 | } | |
| 9 | export 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 @@ |
| 1 | export fn entry() void { | |
| 2 | var damn = Container{ | |
| 3 | .not_optional = getOptional(), | |
| 4 | }; | |
| 5 | _ = damn; | |
| 6 | } | |
| 7 | pub fn getOptional() ?i32 { | |
| 8 | return 0; | |
| 9 | } | |
| 10 | pub 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 @@ |
| 1 | export fn entry() void { | |
| 2 | var damn = Container{ | |
| 3 | .not_optional = getOptional(i32), | |
| 4 | }; | |
| 5 | _ = damn; | |
| 6 | } | |
| 7 | pub fn getOptional(comptime T: type) ?T { | |
| 8 | return 0; | |
| 9 | } | |
| 10 | pub 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 @@ |
| 1 | fn maybe(is: bool) ?u8 { | |
| 2 | if (is) return @as(u8, 10) else return null; | |
| 3 | } | |
| 4 | const U = union { | |
| 5 | Ye: u8, | |
| 6 | }; | |
| 7 | const S = struct { | |
| 8 | num: u8, | |
| 9 | }; | |
| 10 | export 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 @@ |
| 1 | export 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 @@ |
| 1 | const Foo = struct { | |
| 2 | ptr: ?*usize, | |
| 3 | uval: u32, | |
| 4 | }; | |
| 5 | fn get_uval(x: u32) !u32 { | |
| 6 | _ = x; | |
| 7 | return error.NotFound; | |
| 8 | } | |
| 9 | export 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 @@ |
| 1 | export fn entry() void { | |
| 2 | var damn = Container{ | |
| 3 | .not_optional = getOptional(), | |
| 4 | }; | |
| 5 | _ = damn; | |
| 6 | } | |
| 7 | pub fn getOptional() ?i32 { | |
| 8 | return 0; | |
| 9 | } | |
| 10 | pub 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 @@ |
| 1 | export fn entry() void { | |
| 2 | var damn = Container{ | |
| 3 | .not_optional = getOptional(i32), | |
| 4 | }; | |
| 5 | _ = damn; | |
| 6 | } | |
| 7 | pub fn getOptional(comptime T: type) ?T { | |
| 8 | return 0; | |
| 9 | } | |
| 10 | pub 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' |