Skip to content

Commit

Permalink
resolve: Use path segment spans in smart_resolve_path
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Mar 8, 2017
1 parent 2719b84 commit 7cfe20c
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 47 deletions.
50 changes: 25 additions & 25 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 { .. }`.
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -2194,14 +2194,16 @@ impl<'a> Resolver<'a> {
source: PathSource)
-> PathResolution {
let segments = &path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>();
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,
id: NodeId,
qself: Option<&QSelf>,
path: &[Ident],
span: Span,
ident_span: Span,
source: PathSource)
-> PathResolution {
let ns = source.namespace();
Expand All @@ -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 {
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}
_ => {}
Expand All @@ -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<Def>| {
Expand Down Expand Up @@ -2449,7 +2451,7 @@ impl<'a> Resolver<'a> {
// Make sure `A::B` in `<T as A>::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
));
Expand Down Expand Up @@ -2807,7 +2809,7 @@ impl<'a> Resolver<'a> {
path: &[Ident],
ns: Namespace,
filter_fn: FilterFn)
-> Option<String>
-> Option<Symbol>
where FilterFn: Fn(Def) -> bool
{
let add_module_candidates = |module: Module, names: &mut Vec<Name>| {
Expand All @@ -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() {
Expand Down Expand Up @@ -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,
}
}
Expand All @@ -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.

Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/resolve/enums-are-namespaced-xc.stderr
Original file line number Diff line number Diff line change
@@ -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;`
Expand Down
10 changes: 5 additions & 5 deletions src/test/ui/resolve/levenshtein.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ error[E0412]: cannot find type `Opiton` in this scope
--> $DIR/levenshtein.rs:20:10
|
20 | type B = Opiton<u8>; // 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
Expand All @@ -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

36 changes: 27 additions & 9 deletions src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<F:Nonexist(isize) -> 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
Expand Down

0 comments on commit 7cfe20c

Please sign in to comment.