Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Note numeric literals that can never fit in an expected type #73334

Merged
merged 5 commits into from
Jun 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand All @@ -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;
Expand Down
87 changes: 87 additions & 0 deletions src/test/ui/numeric/numeric-cast-no-fix.rs
Original file line number Diff line number Diff line change
@@ -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
Comment on lines +10 to +21
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this exhaustive by including the i* cases as well? A bunch of those should also suggest <type>::from like the u8 case does. I trust that they do (given the code above), but we also want to catch regressions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, let's add a check for f32/f64 as well, while we are at it (to make sure we don't suggest the wrong thing).


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
}
Loading