| 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,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); |
| 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 | 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 @@ | ||
| 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,4 +9,5 @@ fn foo() !void { |
| 9 | // backend=stage2 | 9 | // backend=stage2 |
| 10 | // target=native | 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,4 +7,5 @@ fn bar() anyerror!i32 { return 0; } |
| 7 | // backend=stage2 | 7 | // backend=stage2 |
| 8 | // target=native | 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,6 +17,9 @@ fn bad() anyerror!void { |
| 17 | // backend=stage2 | 17 | // backend=stage2 |
| 18 | // target=native | 18 | // 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 @@ | ||
| 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' | ||