From f7aed3eb27888af72703da15a6b93e51e020f5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 4 Jan 2018 12:23:14 -0800 Subject: [PATCH] Do not use casting for suggestion to add type to numeric literal --- src/librustc/hir/mod.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 43 ++++++++++++++----- src/librustc_typeck/diagnostics.rs | 3 +- src/test/ui/issue-41652/issue_41652.stderr | 6 +-- .../macro-backtrace-invalid-internals.stderr | 8 ++-- .../method-on-ambiguous-numeric-type.rs | 3 ++ .../method-on-ambiguous-numeric-type.stderr | 16 +++++-- 7 files changed, 59 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 9ab3b5ca15e..63b7f806bba 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -241,7 +241,7 @@ pub struct LifetimeDef { } /// A "Path" is essentially Rust's notion of a name; for instance: -/// std::cmp::PartialEq . It's represented as a sequence of identifiers, +/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct Path { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 60ebe3c2c7b..15e16e59dd2 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -215,20 +215,43 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { item_name, ty_string ); - let snippet = tcx.sess.codemap().span_to_snippet(expr.span) - .unwrap_or("4".to_string()); let concrete_type = if actual.is_integral() { - "u32" + "i32" } else { "f32" }; - err.span_suggestion(expr.span, - &format!("you must specify a concrete type for \ - this numeric value, like `{}`", - concrete_type), - format!("({} as {})", - snippet, - concrete_type)); + match expr.node { + hir::ExprLit(_) => { // numeric literal + let snippet = tcx.sess.codemap().span_to_snippet(expr.span) + .unwrap_or("".to_string()); + // FIXME: use the literal for missing snippet + + err.span_suggestion(expr.span, + &format!("you must specify a concrete type for \ + this numeric value, like `{}`", + concrete_type), + format!("{}_{}", + snippet, + concrete_type)); + } + hir::ExprPath(ref qpath) => { // local binding + if let &hir::QPath::Resolved(_, ref path) = &qpath { + if let hir::def::Def::Local(node_id) = path.def { + let span = tcx.hir.span(node_id); + let snippet = tcx.sess.codemap().span_to_snippet(span) + .unwrap(); + err.span_suggestion(span, + &format!("you must specify a type for \ + this binding, like `{}`", + concrete_type), + format!("{}: {}", + snippet, + concrete_type)); + } + } + } + _ => {} + } err.emit(); return; } else { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 204e57f12aa..defcbdfe03d 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4661,9 +4661,10 @@ x.powi(2); // same error as above Because of this, you must give the numeric literal or binding a type: ``` -let _ = (2.0 as f32).powi(2); +let _ = 2.0_f32.powi(2); let x: f32 = 2.0; let _ = x.powi(2); +let _ = (2.0 as f32).powi(2); ``` "##, } diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr index 2b12efc5fad..373dff27f2e 100644 --- a/src/test/ui/issue-41652/issue_41652.stderr +++ b/src/test/ui/issue-41652/issue_41652.stderr @@ -3,10 +3,10 @@ error[E0689]: can't call method `f` on ambiguous numeric type `{integer}` | 19 | 3.f() | ^ -help: you must specify a concrete type for this numeric value, like `u32` +help: you must specify a concrete type for this numeric value, like `i32` | -19 | (3 as u32).f() - | ^^^^^^^^^^ +19 | 3_i32.f() + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 1600bb4fd54..b9cad7e113d 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -35,8 +35,8 @@ error[E0689]: can't call method `powi` on ambiguous numeric type `{float}` | -------------------- in this macro invocation help: you must specify a concrete type for this numeric value, like `f32` | -51 | (2.0 as f32).powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` - | ^^^^^^^^^^^^ +51 | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` + | ^^^^^^^ error[E0599]: no method named `fake` found for type `{integer}` in the current scope --> $DIR/macro-backtrace-invalid-internals.rs:33:13 @@ -75,8 +75,8 @@ error[E0689]: can't call method `powi` on ambiguous numeric type `{float}` | ------------------- in this macro invocation help: you must specify a concrete type for this numeric value, like `f32` | -57 | (2.0 as f32).powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` - | ^^^^^^^^^^^^ +57 | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}` + | ^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs index d0ae520f57b..fa5bafab871 100644 --- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs +++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs @@ -11,5 +11,8 @@ fn main() { let x = 2.0.powi(2); //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}` + let y = 2.0; + let x = y.powi(2); + //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}` println!("{:?}", x); } diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr index f315517d940..c2b292c642c 100644 --- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr +++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr @@ -5,8 +5,18 @@ error[E0689]: can't call method `powi` on ambiguous numeric type `{float}` | ^^^^ help: you must specify a concrete type for this numeric value, like `f32` | -12 | let x = (2.0 as f32).powi(2); - | ^^^^^^^^^^^^ +12 | let x = 2.0_f32.powi(2); + | ^^^^^^^ -error: aborting due to previous error +error[E0689]: can't call method `powi` on ambiguous numeric type `{float}` + --> $DIR/method-on-ambiguous-numeric-type.rs:15:15 + | +15 | let x = y.powi(2); + | ^^^^ +help: you must specify a type for this binding, like `f32` + | +14 | let y: f32 = 2.0; + | ^^^^^^ + +error: aborting due to 2 previous errors