diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 90680b4156e7a..546ce34fe12ae 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -25,7 +25,8 @@ use util::nodemap::FxHashSet; use syntax::ast; use syntax::util::lev_distance::find_best_match_for_name; use errors::DiagnosticBuilder; -use syntax_pos::Span; +use syntax_pos::{Span, FileName}; + use rustc::hir::def_id::LOCAL_CRATE; use rustc::hir; @@ -187,7 +188,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { out_of_scope_traits, lev_candidate, mode, - .. }) => { let tcx = self.tcx; @@ -264,13 +264,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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)); + let filename = tcx.sess.codemap().span_to_filename(span); + + let parent_node = self.tcx.hir.get( + self.tcx.hir.get_parent_node(node_id), + ); + let msg = format!( + "you must specify a type for this binding, like `{}`", + concrete_type, + ); + + match (filename, parent_node) { + (FileName::Real(_), hir_map::NodeLocal(hir::Local { + source: hir::LocalSource::Normal, + ty, + .. + })) => { + err.span_suggestion( + // account for `let x: _ = 42;` + // ^^^^ + span.to(ty.as_ref().map(|ty| ty.span) + .unwrap_or(span)), + &msg, + format!("{}: {}", snippet, concrete_type), + ); + } + _ => { + err.span_label(span, msg); + } + } } } } diff --git a/src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs b/src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs new file mode 100644 index 0000000000000..01282f2ad24b2 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_export] +macro_rules! mac { + ($ident:ident) => { let $ident = 42; } +} 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 9bf74c3875fed..2b6e830ec5962 100644 --- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs +++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs @@ -8,11 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// aux-build:macro-in-other-crate.rs + +#[macro_use] extern crate macro_in_other_crate; + +macro_rules! local_mac { + ($ident:ident) => { let $ident = 42; } +} + fn main() { let x = 2.0.neg(); //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}` + let y = 2.0; let x = y.neg(); //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}` println!("{:?}", x); + + for i in 0..100 { + println!("{}", i.pow(2)); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` + } + + local_mac!(local_bar); + local_bar.pow(2); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` +} + +fn qux() { + mac!(bar); + bar.pow(2); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` } 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 68c8be7dff8c9..796520e0ec71b 100644 --- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr +++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr @@ -1,5 +1,5 @@ error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` - --> $DIR/method-on-ambiguous-numeric-type.rs:12:17 + --> $DIR/method-on-ambiguous-numeric-type.rs:20:17 | LL | let x = 2.0.neg(); | ^^^ @@ -9,7 +9,7 @@ LL | let x = 2.0_f32.neg(); | ^^^^^^^ error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` - --> $DIR/method-on-ambiguous-numeric-type.rs:15:15 + --> $DIR/method-on-ambiguous-numeric-type.rs:24:15 | LL | let x = y.neg(); | ^^^ @@ -18,6 +18,34 @@ help: you must specify a type for this binding, like `f32` LL | let y: f32 = 2.0; | ^^^^^^ -error: aborting due to 2 previous errors +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/method-on-ambiguous-numeric-type.rs:29:26 + | +LL | for i in 0..100 { + | - you must specify a type for this binding, like `i32` +LL | println!("{}", i.pow(2)); + | ^^^ + +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/method-on-ambiguous-numeric-type.rs:34:15 + | +LL | local_bar.pow(2); + | ^^^ +help: you must specify a type for this binding, like `i32` + | +LL | ($ident:ident) => { let $ident: i32 = 42; } + | ^^^^^^^^^^^ + +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/method-on-ambiguous-numeric-type.rs:40:9 + | +LL | mac!(bar); + | ---------- you must specify a type for this binding, like `i32` +LL | bar.pow(2); + | ^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0689`.