Skip to content

Commit 7cfe20c

Browse files
committed
resolve: Use path segment spans in smart_resolve_path
1 parent 2719b84 commit 7cfe20c

6 files changed

+64
-47
lines changed

src/librustc_resolve/lib.rs

+25-25
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ enum PathSource<'a> {
407407
// Trait paths in bounds or impls.
408408
Trait,
409409
// Expression paths `path`, with optional parent context.
410-
Expr(Option<&'a ExprKind>),
410+
Expr(Option<&'a Expr>),
411411
// Paths in path patterns `Path`.
412412
Pat,
413413
// Paths in struct expressions and patterns `Path { .. }`.
@@ -464,7 +464,7 @@ impl<'a> PathSource<'a> {
464464
ValueNS => "method or associated constant",
465465
MacroNS => bug!("associated macro"),
466466
},
467-
PathSource::Expr(parent) => match parent {
467+
PathSource::Expr(parent) => match parent.map(|p| &p.node) {
468468
// "function" here means "anything callable" rather than `Def::Fn`,
469469
// this is not precise but usually more helpful than just "value".
470470
Some(&ExprKind::Call(..)) => "function",
@@ -2194,14 +2194,16 @@ impl<'a> Resolver<'a> {
21942194
source: PathSource)
21952195
-> PathResolution {
21962196
let segments = &path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>();
2197-
self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
2197+
let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
2198+
self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
21982199
}
21992200

22002201
fn smart_resolve_path_fragment(&mut self,
22012202
id: NodeId,
22022203
qself: Option<&QSelf>,
22032204
path: &[Ident],
22042205
span: Span,
2206+
ident_span: Span,
22052207
source: PathSource)
22062208
-> PathResolution {
22072209
let ns = source.namespace();
@@ -2213,9 +2215,9 @@ impl<'a> Resolver<'a> {
22132215
let expected = source.descr_expected();
22142216
let path_str = names_to_string(path);
22152217
let code = source.error_code(def.is_some());
2216-
let (base_msg, fallback_label) = if let Some(def) = def {
2218+
let (base_msg, fallback_label, base_span) = if let Some(def) = def {
22172219
(format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
2218-
format!("not a {}", expected))
2220+
format!("not a {}", expected), span)
22192221
} else {
22202222
let item_str = path[path.len() - 1];
22212223
let (mod_prefix, mod_str) = if path.len() == 1 {
@@ -2231,9 +2233,9 @@ impl<'a> Resolver<'a> {
22312233
(mod_prefix, format!("`{}`", names_to_string(mod_path)))
22322234
};
22332235
(format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
2234-
format!("not found in {}", mod_str))
2236+
format!("not found in {}", mod_str), ident_span)
22352237
};
2236-
let mut err = this.session.struct_span_err_with_code(span, &base_msg, code);
2238+
let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
22372239

22382240
// Emit special messages for unresolved `Self` and `self`.
22392241
if is_self_type(path, ns) {
@@ -2291,15 +2293,15 @@ impl<'a> Resolver<'a> {
22912293
err.span_label(span, &format!("type aliases cannot be used for traits"));
22922294
return err;
22932295
}
2294-
(Def::Mod(..), PathSource::Expr(Some(parent))) => match *parent {
2296+
(Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
22952297
ExprKind::Field(_, ident) => {
2296-
err.span_label(span, &format!("did you mean `{}::{}`?",
2297-
path_str, ident.node));
2298+
err.span_label(parent.span, &format!("did you mean `{}::{}`?",
2299+
path_str, ident.node));
22982300
return err;
22992301
}
23002302
ExprKind::MethodCall(ident, ..) => {
2301-
err.span_label(span, &format!("did you mean `{}::{}(...)`?",
2302-
path_str, ident.node));
2303+
err.span_label(parent.span, &format!("did you mean `{}::{}(...)`?",
2304+
path_str, ident.node));
23032305
return err;
23042306
}
23052307
_ => {}
@@ -2324,12 +2326,12 @@ impl<'a> Resolver<'a> {
23242326

23252327
// Try Levenshtein if nothing else worked.
23262328
if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) {
2327-
err.span_label(span, &format!("did you mean `{}`?", candidate));
2329+
err.span_label(ident_span, &format!("did you mean `{}`?", candidate));
23282330
return err;
23292331
}
23302332

23312333
// Fallback label.
2332-
err.span_label(span, &fallback_label);
2334+
err.span_label(base_span, &fallback_label);
23332335
err
23342336
};
23352337
let report_errors = |this: &mut Self, def: Option<Def>| {
@@ -2449,7 +2451,7 @@ impl<'a> Resolver<'a> {
24492451
// Make sure `A::B` in `<T as A>::B::C` is a trait item.
24502452
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
24512453
let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
2452-
span, PathSource::TraitItem(ns));
2454+
span, span, PathSource::TraitItem(ns));
24532455
return Some(PathResolution::with_unresolved_segments(
24542456
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
24552457
));
@@ -2807,7 +2809,7 @@ impl<'a> Resolver<'a> {
28072809
path: &[Ident],
28082810
ns: Namespace,
28092811
filter_fn: FilterFn)
2810-
-> Option<String>
2812+
-> Option<Symbol>
28112813
where FilterFn: Fn(Def) -> bool
28122814
{
28132815
let add_module_candidates = |module: Module, names: &mut Vec<Name>| {
@@ -2821,7 +2823,7 @@ impl<'a> Resolver<'a> {
28212823
};
28222824

28232825
let mut names = Vec::new();
2824-
let prefix_str = if path.len() == 1 {
2826+
if path.len() == 1 {
28252827
// Search in lexical scope.
28262828
// Walk backwards up the ribs in scope and collect candidates.
28272829
for rib in self.ribs[ns].iter().rev() {
@@ -2855,21 +2857,19 @@ impl<'a> Resolver<'a> {
28552857
names.push(*name);
28562858
}
28572859
}
2858-
String::new()
28592860
} else {
28602861
// Search in module.
28612862
let mod_path = &path[..path.len() - 1];
28622863
if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) {
28632864
add_module_candidates(module, &mut names);
28642865
}
2865-
names_to_string(mod_path) + "::"
2866-
};
2866+
}
28672867

28682868
let name = path[path.len() - 1].name;
28692869
// Make sure error reporting is deterministic.
28702870
names.sort_by_key(|name| name.as_str());
28712871
match find_best_match_for_name(names.iter(), &name.as_str(), None) {
2872-
Some(found) if found != name => Some(format!("{}{}", prefix_str, found)),
2872+
Some(found) if found != name => Some(found),
28732873
_ => None,
28742874
}
28752875
}
@@ -2892,7 +2892,7 @@ impl<'a> Resolver<'a> {
28922892
self.with_resolved_label(label, id, |this| this.visit_block(block));
28932893
}
28942894

2895-
fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) {
2895+
fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
28962896
// First, record candidate traits for this expression if it could
28972897
// result in the invocation of a method call.
28982898

@@ -2973,11 +2973,11 @@ impl<'a> Resolver<'a> {
29732973

29742974
// Equivalent to `visit::walk_expr` + passing some context to children.
29752975
ExprKind::Field(ref subexpression, _) => {
2976-
self.resolve_expr(subexpression, Some(&expr.node));
2976+
self.resolve_expr(subexpression, Some(expr));
29772977
}
29782978
ExprKind::MethodCall(_, ref types, ref arguments) => {
29792979
let mut arguments = arguments.iter();
2980-
self.resolve_expr(arguments.next().unwrap(), Some(&expr.node));
2980+
self.resolve_expr(arguments.next().unwrap(), Some(expr));
29812981
for argument in arguments {
29822982
self.resolve_expr(argument, None);
29832983
}
@@ -2993,7 +2993,7 @@ impl<'a> Resolver<'a> {
29932993
});
29942994
}
29952995
ExprKind::Call(ref callee, ref arguments) => {
2996-
self.resolve_expr(callee, Some(&expr.node));
2996+
self.resolve_expr(callee, Some(expr));
29972997
for argument in arguments {
29982998
self.resolve_expr(argument, None);
29992999
}

src/librustc_resolve/macros.rs

-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,6 @@ impl<'a> Resolver<'a> {
502502
};
503503
let ident = Ident::from_str(name);
504504
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
505-
.as_ref().map(|s| Symbol::intern(s))
506505
});
507506

508507
if let Some(suggestion) = suggestion {

src/test/ui/resolve/enums-are-namespaced-xc.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
error[E0425]: cannot find value `A` in module `namespaced_enums`
2-
--> $DIR/enums-are-namespaced-xc.rs:15:13
2+
--> $DIR/enums-are-namespaced-xc.rs:15:31
33
|
44
15 | let _ = namespaced_enums::A;
5-
| ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
5+
| ^ not found in `namespaced_enums`
66
|
77
= help: possible candidate is found in another module, you can import it into scope:
88
`use namespaced_enums::Foo::A;`
99

1010
error[E0425]: cannot find function `B` in module `namespaced_enums`
11-
--> $DIR/enums-are-namespaced-xc.rs:18:13
11+
--> $DIR/enums-are-namespaced-xc.rs:18:31
1212
|
1313
18 | let _ = namespaced_enums::B(10);
14-
| ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
14+
| ^ not found in `namespaced_enums`
1515
|
1616
= help: possible candidate is found in another module, you can import it into scope:
1717
`use namespaced_enums::Foo::B;`
1818

1919
error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
20-
--> $DIR/enums-are-namespaced-xc.rs:21:13
20+
--> $DIR/enums-are-namespaced-xc.rs:21:31
2121
|
2222
21 | let _ = namespaced_enums::C { a: 10 };
23-
| ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
23+
| ^ not found in `namespaced_enums`
2424
|
2525
= help: possible candidate is found in another module, you can import it into scope:
2626
`use namespaced_enums::Foo::C;`

src/test/ui/resolve/levenshtein.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ error[E0412]: cannot find type `Opiton` in this scope
1414
--> $DIR/levenshtein.rs:20:10
1515
|
1616
20 | type B = Opiton<u8>; // Misspelled type name from the prelude.
17-
| ^^^^^^^^^^ did you mean `Option`?
17+
| ^^^^^^ did you mean `Option`?
1818

1919
error[E0412]: cannot find type `Baz` in this scope
2020
--> $DIR/levenshtein.rs:23:14
@@ -35,16 +35,16 @@ error[E0425]: cannot find function `foobar` in this scope
3535
| ^^^^^^ did you mean `foo_bar`?
3636

3737
error[E0412]: cannot find type `first` in module `m`
38-
--> $DIR/levenshtein.rs:32:12
38+
--> $DIR/levenshtein.rs:32:15
3939
|
4040
32 | let b: m::first = m::second; // Misspelled item in module.
41-
| ^^^^^^^^ did you mean `m::First`?
41+
| ^^^^^ did you mean `First`?
4242

4343
error[E0425]: cannot find value `second` in module `m`
44-
--> $DIR/levenshtein.rs:32:23
44+
--> $DIR/levenshtein.rs:32:26
4545
|
4646
32 | let b: m::first = m::second; // Misspelled item in module.
47-
| ^^^^^^^^^ did you mean `m::Second`?
47+
| ^^^^^^ did you mean `Second`?
4848

4949
error: aborting due to 8 previous errors
5050

src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr

+27-9
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,73 @@ error[E0423]: expected value, found module `a`
22
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
33
|
44
27 | a.I
5-
| ^ did you mean `a::I`?
5+
| ^--
6+
| |
7+
| did you mean `a::I`?
68

79
error[E0423]: expected value, found module `a`
810
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:33:5
911
|
1012
33 | a.g()
11-
| ^ did you mean `a::g(...)`?
13+
| ^----
14+
| |
15+
| did you mean `a::g(...)`?
1216

1317
error[E0423]: expected value, found module `a`
1418
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:39:5
1519
|
1620
39 | a.b.J
17-
| ^ did you mean `a::b`?
21+
| ^--
22+
| |
23+
| did you mean `a::b`?
1824

1925
error[E0423]: expected value, found module `a::b`
2026
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
2127
|
2228
45 | a::b.J
23-
| ^^^^ did you mean `a::b::J`?
29+
| ^^^^--
30+
| |
31+
| did you mean `a::b::J`?
2432

2533
error[E0423]: expected value, found module `a`
2634
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:51:5
2735
|
2836
51 | a.b.f();
29-
| ^ did you mean `a::b`?
37+
| ^--
38+
| |
39+
| did you mean `a::b`?
3040

3141
error[E0423]: expected value, found module `a::b`
3242
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:12
3343
|
3444
55 | v.push(a::b);
35-
| ^^^^ did you mean `a::I`?
45+
| ^^^-
46+
| |
47+
| did you mean `I`?
3648

3749
error[E0423]: expected value, found module `a::b`
3850
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:61:5
3951
|
4052
61 | a::b.f()
41-
| ^^^^ did you mean `a::b::f(...)`?
53+
| ^^^^----
54+
| |
55+
| did you mean `a::b::f(...)`?
4256

4357
error[E0423]: expected value, found module `a::b`
4458
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:67:5
4559
|
4660
67 | a::b
47-
| ^^^^ did you mean `a::I`?
61+
| ^^^-
62+
| |
63+
| did you mean `I`?
4864

4965
error[E0423]: expected function, found module `a::b`
5066
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:73:5
5167
|
5268
73 | a::b()
53-
| ^^^^ did you mean `a::I`?
69+
| ^^^-
70+
| |
71+
| did you mean `I`?
5472

5573
error: main function not found
5674

src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0405]: cannot find trait `Nonexist` in this scope
22
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:11:8
33
|
44
11 | fn f<F:Nonexist(isize) -> isize>(x: F) {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
5+
| ^^^^^^^^ not found in this scope
66

77
error[E0404]: expected trait, found type alias `Typedef`
88
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:17:8

0 commit comments

Comments
 (0)