Rollup merge of #73334 - ayazhafiz:err/num-type-cannot-fit, r=estebank
Note numeric literals that can never fit in an expected type re https://github.com/rust-lang/rust/pull/72380#discussion_r438289385 Given the toy code ```rust fn is_positive(n: usize) { n > -1_isize; } ``` We currently get a type mismatch error like the following: ``` error[E0308]: mismatched types --> src/main.rs:2:9 | 2 | n > -1_isize; | ^^^^^^^^ expected `usize`, found `isize` | help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit | 2 | n > (-1_isize).try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ``` But clearly, `-1` can never fit into a `usize`, so the suggestion will always panic. A more useful message would tell the user that the value can never fit in the expected type: ``` error[E0308]: mismatched types --> test.rs:2:9 | 2 | n > -1_isize; | ^^^^^^^^ expected `usize`, found `isize` | note: `-1_isize` can never fit into `usize` --> test.rs:2:9 | 2 | n > -1_isize; | ^^^^^^^^ ``` Which is what this commit implements. I only added this check for negative literals because - Currently we can only perform such a check for literals (constant value propagation is outside the scope of the typechecker at this point) - A lint error for out-of-range numeric literals is already emitted IMO it makes more sense to put this check in librustc_lint, but as far as I can tell the typecheck pass happens before the lint pass, so I've added it here. r? @estebank
This commit is contained in:
commit
b285d68f36
4 changed files with 428 additions and 1 deletions
|
@ -783,6 +783,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| {
|
||||
if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false }
|
||||
};
|
||||
let is_negative_int =
|
||||
|expr: &hir::Expr<'_>| matches!(expr.kind, hir::ExprKind::Unary(hir::UnOp::UnNeg, ..));
|
||||
let is_uint = |ty: Ty<'_>| matches!(ty.kind, ty::Uint(..));
|
||||
|
||||
let in_const_context = self.tcx.hir().is_inside_const_context(expr.hir_id);
|
||||
|
||||
|
@ -807,7 +810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
"you can convert `{}` from `{}` to `{}`, matching the type of `{}`",
|
||||
lhs_src, expected_ty, checked_ty, src
|
||||
);
|
||||
let suggestion = format!("{}::from({})", checked_ty, lhs_src,);
|
||||
let suggestion = format!("{}::from({})", checked_ty, lhs_src);
|
||||
(lhs_expr.span, msg, suggestion)
|
||||
} else {
|
||||
let msg = format!("{} and panic if the converted value wouldn't fit", msg);
|
||||
|
@ -822,8 +825,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|err: &mut DiagnosticBuilder<'_>,
|
||||
found_to_exp_is_fallible: bool,
|
||||
exp_to_found_is_fallible: bool| {
|
||||
let always_fallible = found_to_exp_is_fallible
|
||||
&& (exp_to_found_is_fallible || expected_ty_expr.is_none());
|
||||
let msg = if literal_is_ty_suffixed(expr) {
|
||||
&lit_msg
|
||||
} else if always_fallible && (is_negative_int(expr) && is_uint(expected_ty)) {
|
||||
// We now know that converting either the lhs or rhs is fallible. Before we
|
||||
// suggest a fallible conversion, check if the value can never fit in the
|
||||
// expected type.
|
||||
let msg = format!("`{}` cannot fit into type `{}`", src, expected_ty);
|
||||
err.note(&msg);
|
||||
return;
|
||||
} else if in_const_context {
|
||||
// Do not recommend `into` or `try_into` in const contexts.
|
||||
return;
|
||||
|
|
87
src/test/ui/numeric/numeric-cast-no-fix.rs
Normal file
87
src/test/ui/numeric/numeric-cast-no-fix.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
#[allow(unused_must_use)]
|
||||
fn main() {
|
||||
let x_usize: usize = 1;
|
||||
let x_u128: u128 = 2;
|
||||
let x_u64: u64 = 3;
|
||||
let x_u32: u32 = 4;
|
||||
let x_u16: u16 = 5;
|
||||
let x_u8: u8 = 6;
|
||||
|
||||
x_usize > -1_isize;
|
||||
//~^ ERROR mismatched types
|
||||
x_u128 > -1_isize;
|
||||
//~^ ERROR mismatched types
|
||||
x_u64 > -1_isize;
|
||||
//~^ ERROR mismatched types
|
||||
x_u32 > -1_isize;
|
||||
//~^ ERROR mismatched types
|
||||
x_u16 > -1_isize;
|
||||
//~^ ERROR mismatched types
|
||||
x_u8 > -1_isize;
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
x_usize > -1_i128;
|
||||
//~^ ERROR mismatched types
|
||||
x_u128 > -1_i128;
|
||||
//~^ ERROR mismatched types
|
||||
x_u64 > -1_i128;
|
||||
//~^ ERROR mismatched types
|
||||
x_u32 > -1_i128;
|
||||
//~^ ERROR mismatched types
|
||||
x_u16 > -1_i128;
|
||||
//~^ ERROR mismatched types
|
||||
x_u8 > -1_i128;
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
x_usize > -1_i64;
|
||||
//~^ ERROR mismatched types
|
||||
x_u128 > -1_i64;
|
||||
//~^ ERROR mismatched types
|
||||
x_u64 > -1_i64;
|
||||
//~^ ERROR mismatched types
|
||||
x_u32 > -1_i64;
|
||||
//~^ ERROR mismatched types
|
||||
x_u16 > -1_i64;
|
||||
//~^ ERROR mismatched types
|
||||
x_u8 > -1_i64;
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
x_usize > -1_i32;
|
||||
//~^ ERROR mismatched types
|
||||
x_u128 > -1_i32;
|
||||
//~^ ERROR mismatched types
|
||||
x_u64 > -1_i32;
|
||||
//~^ ERROR mismatched types
|
||||
x_u32 > -1_i32;
|
||||
//~^ ERROR mismatched types
|
||||
x_u16 > -1_i32;
|
||||
//~^ ERROR mismatched types
|
||||
x_u8 > -1_i32;
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
x_usize > -1_i16;
|
||||
//~^ ERROR mismatched types
|
||||
x_u128 > -1_i16;
|
||||
//~^ ERROR mismatched types
|
||||
x_u64 > -1_i16;
|
||||
//~^ ERROR mismatched types
|
||||
x_u32 > -1_i16;
|
||||
//~^ ERROR mismatched types
|
||||
x_u16 > -1_i16;
|
||||
//~^ ERROR mismatched types
|
||||
x_u8 > -1_i16;
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
x_usize > -1_i8;
|
||||
//~^ ERROR mismatched types
|
||||
x_u128 > -1_i8;
|
||||
//~^ ERROR mismatched types
|
||||
x_u64 > -1_i8;
|
||||
//~^ ERROR mismatched types
|
||||
x_u32 > -1_i8;
|
||||
//~^ ERROR mismatched types
|
||||
x_u16 > -1_i8;
|
||||
//~^ ERROR mismatched types
|
||||
x_u8 > -1_i8;
|
||||
//~^ ERROR mismatched types
|
||||
}
|
324
src/test/ui/numeric/numeric-cast-no-fix.stderr
Normal file
324
src/test/ui/numeric/numeric-cast-no-fix.stderr
Normal file
|
@ -0,0 +1,324 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:10:15
|
||||
|
|
||||
LL | x_usize > -1_isize;
|
||||
| ^^^^^^^^ expected `usize`, found `isize`
|
||||
|
|
||||
= note: `-1_isize` cannot fit into type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:12:14
|
||||
|
|
||||
LL | x_u128 > -1_isize;
|
||||
| ^^^^^^^^ expected `u128`, found `isize`
|
||||
|
|
||||
= note: `-1_isize` cannot fit into type `u128`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:14:13
|
||||
|
|
||||
LL | x_u64 > -1_isize;
|
||||
| ^^^^^^^^ expected `u64`, found `isize`
|
||||
|
|
||||
= note: `-1_isize` cannot fit into type `u64`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:16:13
|
||||
|
|
||||
LL | x_u32 > -1_isize;
|
||||
| ^^^^^^^^ expected `u32`, found `isize`
|
||||
|
|
||||
= note: `-1_isize` cannot fit into type `u32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:18:13
|
||||
|
|
||||
LL | x_u16 > -1_isize;
|
||||
| ^^^^^^^^ expected `u16`, found `isize`
|
||||
|
|
||||
= note: `-1_isize` cannot fit into type `u16`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:20:12
|
||||
|
|
||||
LL | x_u8 > -1_isize;
|
||||
| ^^^^^^^^ expected `u8`, found `isize`
|
||||
|
|
||||
help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize`
|
||||
|
|
||||
LL | isize::from(x_u8) > -1_isize;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:23:15
|
||||
|
|
||||
LL | x_usize > -1_i128;
|
||||
| ^^^^^^^ expected `usize`, found `i128`
|
||||
|
|
||||
= note: `-1_i128` cannot fit into type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:25:14
|
||||
|
|
||||
LL | x_u128 > -1_i128;
|
||||
| ^^^^^^^ expected `u128`, found `i128`
|
||||
|
|
||||
= note: `-1_i128` cannot fit into type `u128`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:27:13
|
||||
|
|
||||
LL | x_u64 > -1_i128;
|
||||
| ^^^^^^^ expected `u64`, found `i128`
|
||||
|
|
||||
help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128`
|
||||
|
|
||||
LL | i128::from(x_u64) > -1_i128;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:29:13
|
||||
|
|
||||
LL | x_u32 > -1_i128;
|
||||
| ^^^^^^^ expected `u32`, found `i128`
|
||||
|
|
||||
help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128`
|
||||
|
|
||||
LL | i128::from(x_u32) > -1_i128;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:31:13
|
||||
|
|
||||
LL | x_u16 > -1_i128;
|
||||
| ^^^^^^^ expected `u16`, found `i128`
|
||||
|
|
||||
help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128`
|
||||
|
|
||||
LL | i128::from(x_u16) > -1_i128;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:33:12
|
||||
|
|
||||
LL | x_u8 > -1_i128;
|
||||
| ^^^^^^^ expected `u8`, found `i128`
|
||||
|
|
||||
help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128`
|
||||
|
|
||||
LL | i128::from(x_u8) > -1_i128;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:36:15
|
||||
|
|
||||
LL | x_usize > -1_i64;
|
||||
| ^^^^^^ expected `usize`, found `i64`
|
||||
|
|
||||
= note: `-1_i64` cannot fit into type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:38:14
|
||||
|
|
||||
LL | x_u128 > -1_i64;
|
||||
| ^^^^^^ expected `u128`, found `i64`
|
||||
|
|
||||
= note: `-1_i64` cannot fit into type `u128`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:40:13
|
||||
|
|
||||
LL | x_u64 > -1_i64;
|
||||
| ^^^^^^ expected `u64`, found `i64`
|
||||
|
|
||||
= note: `-1_i64` cannot fit into type `u64`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:42:13
|
||||
|
|
||||
LL | x_u32 > -1_i64;
|
||||
| ^^^^^^ expected `u32`, found `i64`
|
||||
|
|
||||
help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64`
|
||||
|
|
||||
LL | i64::from(x_u32) > -1_i64;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:44:13
|
||||
|
|
||||
LL | x_u16 > -1_i64;
|
||||
| ^^^^^^ expected `u16`, found `i64`
|
||||
|
|
||||
help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64`
|
||||
|
|
||||
LL | i64::from(x_u16) > -1_i64;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:46:12
|
||||
|
|
||||
LL | x_u8 > -1_i64;
|
||||
| ^^^^^^ expected `u8`, found `i64`
|
||||
|
|
||||
help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64`
|
||||
|
|
||||
LL | i64::from(x_u8) > -1_i64;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:49:15
|
||||
|
|
||||
LL | x_usize > -1_i32;
|
||||
| ^^^^^^ expected `usize`, found `i32`
|
||||
|
|
||||
= note: `-1_i32` cannot fit into type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:51:14
|
||||
|
|
||||
LL | x_u128 > -1_i32;
|
||||
| ^^^^^^ expected `u128`, found `i32`
|
||||
|
|
||||
= note: `-1_i32` cannot fit into type `u128`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:53:13
|
||||
|
|
||||
LL | x_u64 > -1_i32;
|
||||
| ^^^^^^ expected `u64`, found `i32`
|
||||
|
|
||||
= note: `-1_i32` cannot fit into type `u64`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:55:13
|
||||
|
|
||||
LL | x_u32 > -1_i32;
|
||||
| ^^^^^^ expected `u32`, found `i32`
|
||||
|
|
||||
= note: `-1_i32` cannot fit into type `u32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:57:13
|
||||
|
|
||||
LL | x_u16 > -1_i32;
|
||||
| ^^^^^^ expected `u16`, found `i32`
|
||||
|
|
||||
help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32`
|
||||
|
|
||||
LL | i32::from(x_u16) > -1_i32;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:59:12
|
||||
|
|
||||
LL | x_u8 > -1_i32;
|
||||
| ^^^^^^ expected `u8`, found `i32`
|
||||
|
|
||||
help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32`
|
||||
|
|
||||
LL | i32::from(x_u8) > -1_i32;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:62:15
|
||||
|
|
||||
LL | x_usize > -1_i16;
|
||||
| ^^^^^^ expected `usize`, found `i16`
|
||||
|
|
||||
= note: `-1_i16` cannot fit into type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:64:14
|
||||
|
|
||||
LL | x_u128 > -1_i16;
|
||||
| ^^^^^^ expected `u128`, found `i16`
|
||||
|
|
||||
= note: `-1_i16` cannot fit into type `u128`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:66:13
|
||||
|
|
||||
LL | x_u64 > -1_i16;
|
||||
| ^^^^^^ expected `u64`, found `i16`
|
||||
|
|
||||
= note: `-1_i16` cannot fit into type `u64`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:68:13
|
||||
|
|
||||
LL | x_u32 > -1_i16;
|
||||
| ^^^^^^ expected `u32`, found `i16`
|
||||
|
|
||||
= note: `-1_i16` cannot fit into type `u32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:70:13
|
||||
|
|
||||
LL | x_u16 > -1_i16;
|
||||
| ^^^^^^ expected `u16`, found `i16`
|
||||
|
|
||||
= note: `-1_i16` cannot fit into type `u16`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:72:12
|
||||
|
|
||||
LL | x_u8 > -1_i16;
|
||||
| ^^^^^^ expected `u8`, found `i16`
|
||||
|
|
||||
help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16`
|
||||
|
|
||||
LL | i16::from(x_u8) > -1_i16;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:75:15
|
||||
|
|
||||
LL | x_usize > -1_i8;
|
||||
| ^^^^^ expected `usize`, found `i8`
|
||||
|
|
||||
= note: `-1_i8` cannot fit into type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:77:14
|
||||
|
|
||||
LL | x_u128 > -1_i8;
|
||||
| ^^^^^ expected `u128`, found `i8`
|
||||
|
|
||||
= note: `-1_i8` cannot fit into type `u128`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:79:13
|
||||
|
|
||||
LL | x_u64 > -1_i8;
|
||||
| ^^^^^ expected `u64`, found `i8`
|
||||
|
|
||||
= note: `-1_i8` cannot fit into type `u64`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:81:13
|
||||
|
|
||||
LL | x_u32 > -1_i8;
|
||||
| ^^^^^ expected `u32`, found `i8`
|
||||
|
|
||||
= note: `-1_i8` cannot fit into type `u32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:83:13
|
||||
|
|
||||
LL | x_u16 > -1_i8;
|
||||
| ^^^^^ expected `u16`, found `i8`
|
||||
|
|
||||
= note: `-1_i8` cannot fit into type `u16`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/numeric-cast-no-fix.rs:85:12
|
||||
|
|
||||
LL | x_u8 > -1_i8;
|
||||
| ^^^^^ expected `u8`, found `i8`
|
||||
|
|
||||
= note: `-1_i8` cannot fit into type `u8`
|
||||
|
||||
error: aborting due to 36 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -39,12 +39,16 @@ error[E0308]: mismatched types
|
|||
|
|
||||
LL | let f = [0; -4_isize];
|
||||
| ^^^^^^^^ expected `usize`, found `isize`
|
||||
|
|
||||
= note: `-4_isize` cannot fit into type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/repeat_count.rs:22:23
|
||||
|
|
||||
LL | let f = [0_usize; -1_isize];
|
||||
| ^^^^^^^^ expected `usize`, found `isize`
|
||||
|
|
||||
= note: `-1_isize` cannot fit into type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/repeat_count.rs:25:17
|
||||
|
|
Loading…
Reference in a new issue