From 7cfe20c676e3f17a065a24cc7da8647c135cc70e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 8 Mar 2017 22:15:12 +0300 Subject: [PATCH] resolve: Use path segment spans in smart_resolve_path --- src/librustc_resolve/lib.rs | 50 +++++++++---------- src/librustc_resolve/macros.rs | 1 - .../ui/resolve/enums-are-namespaced-xc.stderr | 12 ++--- src/test/ui/resolve/levenshtein.stderr | 10 ++-- ...uggest-path-instead-of-mod-dot-item.stderr | 36 +++++++++---- ...xed-closure-sugar-nonexistent-trait.stderr | 2 +- 6 files changed, 64 insertions(+), 47 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 105af23d05c05..99061747832ec 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -407,7 +407,7 @@ enum PathSource<'a> { // Trait paths in bounds or impls. Trait, // Expression paths `path`, with optional parent context. - Expr(Option<&'a ExprKind>), + Expr(Option<&'a Expr>), // Paths in path patterns `Path`. Pat, // Paths in struct expressions and patterns `Path { .. }`. @@ -464,7 +464,7 @@ impl<'a> PathSource<'a> { ValueNS => "method or associated constant", MacroNS => bug!("associated macro"), }, - PathSource::Expr(parent) => match parent { + PathSource::Expr(parent) => match parent.map(|p| &p.node) { // "function" here means "anything callable" rather than `Def::Fn`, // this is not precise but usually more helpful than just "value". Some(&ExprKind::Call(..)) => "function", @@ -2194,7 +2194,8 @@ impl<'a> Resolver<'a> { source: PathSource) -> PathResolution { let segments = &path.segments.iter().map(|seg| seg.identifier).collect::>(); - self.smart_resolve_path_fragment(id, qself, segments, path.span, source) + let ident_span = path.segments.last().map_or(path.span, |seg| seg.span); + self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source) } fn smart_resolve_path_fragment(&mut self, @@ -2202,6 +2203,7 @@ impl<'a> Resolver<'a> { qself: Option<&QSelf>, path: &[Ident], span: Span, + ident_span: Span, source: PathSource) -> PathResolution { let ns = source.namespace(); @@ -2213,9 +2215,9 @@ impl<'a> Resolver<'a> { let expected = source.descr_expected(); let path_str = names_to_string(path); let code = source.error_code(def.is_some()); - let (base_msg, fallback_label) = if let Some(def) = def { + let (base_msg, fallback_label, base_span) = if let Some(def) = def { (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), - format!("not a {}", expected)) + format!("not a {}", expected), span) } else { let item_str = path[path.len() - 1]; let (mod_prefix, mod_str) = if path.len() == 1 { @@ -2231,9 +2233,9 @@ impl<'a> Resolver<'a> { (mod_prefix, format!("`{}`", names_to_string(mod_path))) }; (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), - format!("not found in {}", mod_str)) + format!("not found in {}", mod_str), ident_span) }; - let mut err = this.session.struct_span_err_with_code(span, &base_msg, code); + let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code); // Emit special messages for unresolved `Self` and `self`. if is_self_type(path, ns) { @@ -2291,15 +2293,15 @@ impl<'a> Resolver<'a> { err.span_label(span, &format!("type aliases cannot be used for traits")); return err; } - (Def::Mod(..), PathSource::Expr(Some(parent))) => match *parent { + (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { ExprKind::Field(_, ident) => { - err.span_label(span, &format!("did you mean `{}::{}`?", - path_str, ident.node)); + err.span_label(parent.span, &format!("did you mean `{}::{}`?", + path_str, ident.node)); return err; } ExprKind::MethodCall(ident, ..) => { - err.span_label(span, &format!("did you mean `{}::{}(...)`?", - path_str, ident.node)); + err.span_label(parent.span, &format!("did you mean `{}::{}(...)`?", + path_str, ident.node)); return err; } _ => {} @@ -2324,12 +2326,12 @@ impl<'a> Resolver<'a> { // Try Levenshtein if nothing else worked. if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) { - err.span_label(span, &format!("did you mean `{}`?", candidate)); + err.span_label(ident_span, &format!("did you mean `{}`?", candidate)); return err; } // Fallback label. - err.span_label(span, &fallback_label); + err.span_label(base_span, &fallback_label); err }; let report_errors = |this: &mut Self, def: Option| { @@ -2449,7 +2451,7 @@ impl<'a> Resolver<'a> { // Make sure `A::B` in `::B::C` is a trait item. let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1], - span, PathSource::TraitItem(ns)); + span, span, PathSource::TraitItem(ns)); return Some(PathResolution::with_unresolved_segments( res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1 )); @@ -2807,7 +2809,7 @@ impl<'a> Resolver<'a> { path: &[Ident], ns: Namespace, filter_fn: FilterFn) - -> Option + -> Option where FilterFn: Fn(Def) -> bool { let add_module_candidates = |module: Module, names: &mut Vec| { @@ -2821,7 +2823,7 @@ impl<'a> Resolver<'a> { }; let mut names = Vec::new(); - let prefix_str = if path.len() == 1 { + if path.len() == 1 { // Search in lexical scope. // Walk backwards up the ribs in scope and collect candidates. for rib in self.ribs[ns].iter().rev() { @@ -2855,21 +2857,19 @@ impl<'a> Resolver<'a> { names.push(*name); } } - String::new() } else { // Search in module. let mod_path = &path[..path.len() - 1]; if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) { add_module_candidates(module, &mut names); } - names_to_string(mod_path) + "::" - }; + } let name = path[path.len() - 1].name; // Make sure error reporting is deterministic. names.sort_by_key(|name| name.as_str()); match find_best_match_for_name(names.iter(), &name.as_str(), None) { - Some(found) if found != name => Some(format!("{}{}", prefix_str, found)), + Some(found) if found != name => Some(found), _ => None, } } @@ -2892,7 +2892,7 @@ impl<'a> Resolver<'a> { self.with_resolved_label(label, id, |this| this.visit_block(block)); } - fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) { + fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { // First, record candidate traits for this expression if it could // result in the invocation of a method call. @@ -2973,11 +2973,11 @@ impl<'a> Resolver<'a> { // Equivalent to `visit::walk_expr` + passing some context to children. ExprKind::Field(ref subexpression, _) => { - self.resolve_expr(subexpression, Some(&expr.node)); + self.resolve_expr(subexpression, Some(expr)); } ExprKind::MethodCall(_, ref types, ref arguments) => { let mut arguments = arguments.iter(); - self.resolve_expr(arguments.next().unwrap(), Some(&expr.node)); + self.resolve_expr(arguments.next().unwrap(), Some(expr)); for argument in arguments { self.resolve_expr(argument, None); } @@ -2993,7 +2993,7 @@ impl<'a> Resolver<'a> { }); } ExprKind::Call(ref callee, ref arguments) => { - self.resolve_expr(callee, Some(&expr.node)); + self.resolve_expr(callee, Some(expr)); for argument in arguments { self.resolve_expr(argument, None); } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index d81bdf17034e6..9d4779a06baf6 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -502,7 +502,6 @@ impl<'a> Resolver<'a> { }; let ident = Ident::from_str(name); self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro) - .as_ref().map(|s| Symbol::intern(s)) }); if let Some(suggestion) = suggestion { diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index d541aa599a48b..dd04c5ce356c6 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -1,26 +1,26 @@ error[E0425]: cannot find value `A` in module `namespaced_enums` - --> $DIR/enums-are-namespaced-xc.rs:15:13 + --> $DIR/enums-are-namespaced-xc.rs:15:31 | 15 | let _ = namespaced_enums::A; - | ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums` + | ^ not found in `namespaced_enums` | = help: possible candidate is found in another module, you can import it into scope: `use namespaced_enums::Foo::A;` error[E0425]: cannot find function `B` in module `namespaced_enums` - --> $DIR/enums-are-namespaced-xc.rs:18:13 + --> $DIR/enums-are-namespaced-xc.rs:18:31 | 18 | let _ = namespaced_enums::B(10); - | ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums` + | ^ not found in `namespaced_enums` | = help: possible candidate is found in another module, you can import it into scope: `use namespaced_enums::Foo::B;` error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums` - --> $DIR/enums-are-namespaced-xc.rs:21:13 + --> $DIR/enums-are-namespaced-xc.rs:21:31 | 21 | let _ = namespaced_enums::C { a: 10 }; - | ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums` + | ^ not found in `namespaced_enums` | = help: possible candidate is found in another module, you can import it into scope: `use namespaced_enums::Foo::C;` diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index c7c42bcf23940..4dff2620319e4 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -14,7 +14,7 @@ error[E0412]: cannot find type `Opiton` in this scope --> $DIR/levenshtein.rs:20:10 | 20 | type B = Opiton; // Misspelled type name from the prelude. - | ^^^^^^^^^^ did you mean `Option`? + | ^^^^^^ did you mean `Option`? error[E0412]: cannot find type `Baz` in this scope --> $DIR/levenshtein.rs:23:14 @@ -35,16 +35,16 @@ error[E0425]: cannot find function `foobar` in this scope | ^^^^^^ did you mean `foo_bar`? error[E0412]: cannot find type `first` in module `m` - --> $DIR/levenshtein.rs:32:12 + --> $DIR/levenshtein.rs:32:15 | 32 | let b: m::first = m::second; // Misspelled item in module. - | ^^^^^^^^ did you mean `m::First`? + | ^^^^^ did you mean `First`? error[E0425]: cannot find value `second` in module `m` - --> $DIR/levenshtein.rs:32:23 + --> $DIR/levenshtein.rs:32:26 | 32 | let b: m::first = m::second; // Misspelled item in module. - | ^^^^^^^^^ did you mean `m::Second`? + | ^^^^^^ did you mean `Second`? error: aborting due to 8 previous errors diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index 57c0ecc813505..85fb1777dea23 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -2,55 +2,73 @@ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5 | 27 | a.I - | ^ did you mean `a::I`? + | ^-- + | | + | did you mean `a::I`? error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:33:5 | 33 | a.g() - | ^ did you mean `a::g(...)`? + | ^---- + | | + | did you mean `a::g(...)`? error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:39:5 | 39 | a.b.J - | ^ did you mean `a::b`? + | ^-- + | | + | did you mean `a::b`? error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5 | 45 | a::b.J - | ^^^^ did you mean `a::b::J`? + | ^^^^-- + | | + | did you mean `a::b::J`? error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:51:5 | 51 | a.b.f(); - | ^ did you mean `a::b`? + | ^-- + | | + | did you mean `a::b`? error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:12 | 55 | v.push(a::b); - | ^^^^ did you mean `a::I`? + | ^^^- + | | + | did you mean `I`? error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:61:5 | 61 | a::b.f() - | ^^^^ did you mean `a::b::f(...)`? + | ^^^^---- + | | + | did you mean `a::b::f(...)`? error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:67:5 | 67 | a::b - | ^^^^ did you mean `a::I`? + | ^^^- + | | + | did you mean `I`? error[E0423]: expected function, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:73:5 | 73 | a::b() - | ^^^^ did you mean `a::I`? + | ^^^- + | | + | did you mean `I`? error: main function not found diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr index f0d363f7335f7..015dbfc3dc775 100644 --- a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr +++ b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr @@ -2,7 +2,7 @@ error[E0405]: cannot find trait `Nonexist` in this scope --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:11:8 | 11 | fn f isize>(x: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^ not found in this scope error[E0404]: expected trait, found type alias `Typedef` --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:17:8