diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 4e22ead8db987..e78cd4891a5ea 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -415,10 +415,55 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { src, if needs_paren { ")" } else { "" }, expected_ty); - let into_suggestion = format!("{}{}{}.into()", - if needs_paren { "(" } else { "" }, - src, - if needs_paren { ")" } else { "" }); + let into_suggestion = format!( + "{}{}{}.into()", + if needs_paren { "(" } else { "" }, + src, + if needs_paren { ")" } else { "" }, + ); + let literal_is_ty_suffixed = |expr: &hir::Expr| { + if let hir::ExprKind::Lit(lit) = &expr.node { + lit.node.is_suffixed() + } else { + false + } + }; + + let into_sugg = into_suggestion.clone(); + let suggest_to_change_suffix_or_into = |err: &mut DiagnosticBuilder, + note: Option<&str>| { + let suggest_msg = if literal_is_ty_suffixed(expr) { + format!( + "change the type of the numeric literal from `{}` to `{}`", + checked_ty, + expected_ty, + ) + } else { + match note { + Some(note) => format!("{}, which {}", msg, note), + _ => format!("{} in a lossless way", msg), + } + }; + + let suffix_suggestion = format!( + "{}{}{}{}", + if needs_paren { "(" } else { "" }, + src.trim_right_matches(&checked_ty.to_string()), + expected_ty, + if needs_paren { ")" } else { "" }, + ); + + err.span_suggestion_with_applicability( + expr.span, + &suggest_msg, + if literal_is_ty_suffixed(expr) { + suffix_suggestion + } else { + into_sugg + }, + Applicability::MachineApplicable, + ); + }; match (&expected_ty.sty, &checked_ty.sty) { (&ty::Int(ref exp), &ty::Int(ref found)) => { @@ -444,11 +489,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } _ => { - err.span_suggestion_with_applicability( - expr.span, - &format!("{}, which {}", msg, will_sign_extend), - into_suggestion, - Applicability::MachineApplicable + suggest_to_change_suffix_or_into( + err, + Some(will_sign_extend), ); } } @@ -477,12 +520,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } _ => { - err.span_suggestion_with_applicability( - expr.span, - &format!("{}, which {}", msg, will_zero_extend), - into_suggestion, - Applicability::MachineApplicable - ); + suggest_to_change_suffix_or_into( + err, + Some(will_zero_extend), + ); } } true @@ -583,12 +624,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } (&ty::Float(ref exp), &ty::Float(ref found)) => { if found.bit_width() < exp.bit_width() { - err.span_suggestion_with_applicability( - expr.span, - &format!("{} in a lossless way", msg), - into_suggestion, - Applicability::MachineApplicable - ); + suggest_to_change_suffix_or_into( + err, + None, + ); } else if can_cast { err.span_suggestion_with_applicability( expr.span, diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.rs b/src/test/ui/mismatched_types/numeric-literal-cast.rs new file mode 100644 index 0000000000000..516b2e8dd30bf --- /dev/null +++ b/src/test/ui/mismatched_types/numeric-literal-cast.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo(_: u16) {} +fn foo1(_: f64) {} +fn foo2(_: i32) {} + +fn main() { + foo(1u8); + foo1(2f32); + foo2(3i16); +} + diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.stderr b/src/test/ui/mismatched_types/numeric-literal-cast.stderr new file mode 100644 index 0000000000000..e2fe1a0914d4f --- /dev/null +++ b/src/test/ui/mismatched_types/numeric-literal-cast.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:16:9 + | +LL | foo(1u8); + | ^^^ expected u16, found u8 +help: change the type of the numeric literal from `u8` to `u16` + | +LL | foo(1u16); + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:17:10 + | +LL | foo1(2f32); + | ^^^^ expected f64, found f32 +help: change the type of the numeric literal from `f32` to `f64` + | +LL | foo1(2f64); + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:18:10 + | +LL | foo2(3i16); + | ^^^^ expected i32, found i16 +help: change the type of the numeric literal from `i16` to `i32` + | +LL | foo2(3i32); + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`.