Skip to content

Commit 8d1c570

Browse files
authored
Rollup merge of rust-lang#40369 - petrochenkov:segspan, r=eddyb
Give spans to individual path segments in AST And use these spans in path resolution diagnostics. The spans are spans of identifiers in segments, not whole segments. I'm not sure what spans are more useful in general, but identifier spans are a better fit for resolve errors. HIR still doesn't have spans. Fixes rust-lang#38927 (comment) rust-lang#38890 (comment) r? @nrc @eddyb
2 parents f88b24b + ffdcf74 commit 8d1c570

14 files changed

+124
-88
lines changed

src/librustc_resolve/lib.rs

+28-29
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",
@@ -2200,14 +2200,16 @@ impl<'a> Resolver<'a> {
22002200
source: PathSource)
22012201
-> PathResolution {
22022202
let segments = &path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>();
2203-
self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
2203+
let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
2204+
self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
22042205
}
22052206

22062207
fn smart_resolve_path_fragment(&mut self,
22072208
id: NodeId,
22082209
qself: Option<&QSelf>,
22092210
path: &[Ident],
22102211
span: Span,
2212+
ident_span: Span,
22112213
source: PathSource)
22122214
-> PathResolution {
22132215
let ns = source.namespace();
@@ -2219,9 +2221,9 @@ impl<'a> Resolver<'a> {
22192221
let expected = source.descr_expected();
22202222
let path_str = names_to_string(path);
22212223
let code = source.error_code(def.is_some());
2222-
let (base_msg, fallback_label) = if let Some(def) = def {
2224+
let (base_msg, fallback_label, base_span) = if let Some(def) = def {
22232225
(format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
2224-
format!("not a {}", expected))
2226+
format!("not a {}", expected), span)
22252227
} else {
22262228
let item_str = path[path.len() - 1];
22272229
let (mod_prefix, mod_str) = if path.len() == 1 {
@@ -2237,9 +2239,9 @@ impl<'a> Resolver<'a> {
22372239
(mod_prefix, format!("`{}`", names_to_string(mod_path)))
22382240
};
22392241
(format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
2240-
format!("not found in {}", mod_str))
2242+
format!("not found in {}", mod_str), ident_span)
22412243
};
2242-
let mut err = this.session.struct_span_err_with_code(span, &base_msg, code);
2244+
let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
22432245

22442246
// Emit special messages for unresolved `Self` and `self`.
22452247
if is_self_type(path, ns) {
@@ -2297,15 +2299,15 @@ impl<'a> Resolver<'a> {
22972299
err.span_label(span, &format!("type aliases cannot be used for traits"));
22982300
return err;
22992301
}
2300-
(Def::Mod(..), PathSource::Expr(Some(parent))) => match *parent {
2302+
(Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
23012303
ExprKind::Field(_, ident) => {
2302-
err.span_label(span, &format!("did you mean `{}::{}`?",
2303-
path_str, ident.node));
2304+
err.span_label(parent.span, &format!("did you mean `{}::{}`?",
2305+
path_str, ident.node));
23042306
return err;
23052307
}
23062308
ExprKind::MethodCall(ident, ..) => {
2307-
err.span_label(span, &format!("did you mean `{}::{}(...)`?",
2308-
path_str, ident.node));
2309+
err.span_label(parent.span, &format!("did you mean `{}::{}(...)`?",
2310+
path_str, ident.node));
23092311
return err;
23102312
}
23112313
_ => {}
@@ -2330,12 +2332,12 @@ impl<'a> Resolver<'a> {
23302332

23312333
// Try Levenshtein if nothing else worked.
23322334
if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) {
2333-
err.span_label(span, &format!("did you mean `{}`?", candidate));
2335+
err.span_label(ident_span, &format!("did you mean `{}`?", candidate));
23342336
return err;
23352337
}
23362338

23372339
// Fallback label.
2338-
err.span_label(span, &fallback_label);
2340+
err.span_label(base_span, &fallback_label);
23392341
err
23402342
};
23412343
let report_errors = |this: &mut Self, def: Option<Def>| {
@@ -2455,7 +2457,7 @@ impl<'a> Resolver<'a> {
24552457
// Make sure `A::B` in `<T as A>::B::C` is a trait item.
24562458
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
24572459
let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
2458-
span, PathSource::TraitItem(ns));
2460+
span, span, PathSource::TraitItem(ns));
24592461
return Some(PathResolution::with_unresolved_segments(
24602462
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
24612463
));
@@ -2813,7 +2815,7 @@ impl<'a> Resolver<'a> {
28132815
path: &[Ident],
28142816
ns: Namespace,
28152817
filter_fn: FilterFn)
2816-
-> Option<String>
2818+
-> Option<Symbol>
28172819
where FilterFn: Fn(Def) -> bool
28182820
{
28192821
let add_module_candidates = |module: Module, names: &mut Vec<Name>| {
@@ -2827,7 +2829,7 @@ impl<'a> Resolver<'a> {
28272829
};
28282830

28292831
let mut names = Vec::new();
2830-
let prefix_str = if path.len() == 1 {
2832+
if path.len() == 1 {
28312833
// Search in lexical scope.
28322834
// Walk backwards up the ribs in scope and collect candidates.
28332835
for rib in self.ribs[ns].iter().rev() {
@@ -2861,21 +2863,19 @@ impl<'a> Resolver<'a> {
28612863
names.push(*name);
28622864
}
28632865
}
2864-
String::new()
28652866
} else {
28662867
// Search in module.
28672868
let mod_path = &path[..path.len() - 1];
28682869
if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) {
28692870
add_module_candidates(module, &mut names);
28702871
}
2871-
names_to_string(mod_path) + "::"
2872-
};
2872+
}
28732873

28742874
let name = path[path.len() - 1].name;
28752875
// Make sure error reporting is deterministic.
28762876
names.sort_by_key(|name| name.as_str());
28772877
match find_best_match_for_name(names.iter(), &name.as_str(), None) {
2878-
Some(found) if found != name => Some(format!("{}{}", prefix_str, found)),
2878+
Some(found) if found != name => Some(found),
28792879
_ => None,
28802880
}
28812881
}
@@ -2898,7 +2898,7 @@ impl<'a> Resolver<'a> {
28982898
self.with_resolved_label(label, id, |this| this.visit_block(block));
28992899
}
29002900

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

@@ -2979,11 +2979,11 @@ impl<'a> Resolver<'a> {
29792979

29802980
// Equivalent to `visit::walk_expr` + passing some context to children.
29812981
ExprKind::Field(ref subexpression, _) => {
2982-
self.resolve_expr(subexpression, Some(&expr.node));
2982+
self.resolve_expr(subexpression, Some(expr));
29832983
}
29842984
ExprKind::MethodCall(_, ref types, ref arguments) => {
29852985
let mut arguments = arguments.iter();
2986-
self.resolve_expr(arguments.next().unwrap(), Some(&expr.node));
2986+
self.resolve_expr(arguments.next().unwrap(), Some(expr));
29872987
for argument in arguments {
29882988
self.resolve_expr(argument, None);
29892989
}
@@ -2999,7 +2999,7 @@ impl<'a> Resolver<'a> {
29992999
});
30003000
}
30013001
ExprKind::Call(ref callee, ref arguments) => {
3002-
self.resolve_expr(callee, Some(&expr.node));
3002+
self.resolve_expr(callee, Some(expr));
30033003
for argument in arguments {
30043004
self.resolve_expr(argument, None);
30053005
}
@@ -3130,11 +3130,10 @@ impl<'a> Resolver<'a> {
31303130
if ident.name == lookup_name && ns == namespace {
31313131
if filter_fn(name_binding.def()) {
31323132
// create the path
3133-
let span = name_binding.span;
31343133
let mut segms = path_segments.clone();
3135-
segms.push(ident.into());
3134+
segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
31363135
let path = Path {
3137-
span: span,
3136+
span: name_binding.span,
31383137
segments: segms,
31393138
};
31403139
// the entity is accessible in the following cases:
@@ -3154,7 +3153,7 @@ impl<'a> Resolver<'a> {
31543153
if let Some(module) = name_binding.module() {
31553154
// form the path
31563155
let mut path_segments = path_segments.clone();
3157-
path_segments.push(ident.into());
3156+
path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
31583157

31593158
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
31603159
// add the module to the lookup

src/librustc_resolve/macros.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,11 @@ impl<'a> base::Resolver for Resolver<'a> {
111111
path.segments[0].identifier.name = keywords::CrateRoot.name();
112112
let module = self.0.resolve_crate_var(ident.ctxt);
113113
if !module.is_local() {
114+
let span = path.segments[0].span;
114115
path.segments.insert(1, match module.kind {
115-
ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name).into(),
116+
ModuleKind::Def(_, name) => ast::PathSegment::from_ident(
117+
ast::Ident::with_empty_ctxt(name), span
118+
),
116119
_ => unreachable!(),
117120
})
118121
}
@@ -569,7 +572,6 @@ impl<'a> Resolver<'a> {
569572
};
570573
let ident = Ident::from_str(name);
571574
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
572-
.as_ref().map(|s| Symbol::intern(s))
573575
});
574576

575577
if let Some(suggestion) = suggestion {

src/libsyntax/ast.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl Path {
134134
pub fn from_ident(s: Span, identifier: Ident) -> Path {
135135
Path {
136136
span: s,
137-
segments: vec![identifier.into()],
137+
segments: vec![PathSegment::from_ident(identifier, s)],
138138
}
139139
}
140140

@@ -159,6 +159,8 @@ impl Path {
159159
pub struct PathSegment {
160160
/// The identifier portion of this path segment.
161161
pub identifier: Ident,
162+
/// Span of the segment identifier.
163+
pub span: Span,
162164

163165
/// Type/lifetime parameters attached to this path. They come in
164166
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
@@ -170,16 +172,14 @@ pub struct PathSegment {
170172
pub parameters: Option<P<PathParameters>>,
171173
}
172174

173-
impl From<Ident> for PathSegment {
174-
fn from(id: Ident) -> Self {
175-
PathSegment { identifier: id, parameters: None }
176-
}
177-
}
178-
179175
impl PathSegment {
176+
pub fn from_ident(ident: Ident, span: Span) -> Self {
177+
PathSegment { identifier: ident, span: span, parameters: None }
178+
}
180179
pub fn crate_root() -> Self {
181180
PathSegment {
182181
identifier: keywords::CrateRoot.ident(),
182+
span: DUMMY_SP,
183183
parameters: None,
184184
}
185185
}

src/libsyntax/ext/build.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ pub trait AstBuilder {
3838

3939
fn qpath(&self, self_type: P<ast::Ty>,
4040
trait_path: ast::Path,
41-
ident: ast::Ident)
41+
ident: ast::SpannedIdent)
4242
-> (ast::QSelf, ast::Path);
4343
fn qpath_all(&self, self_type: P<ast::Ty>,
4444
trait_path: ast::Path,
45-
ident: ast::Ident,
45+
ident: ast::SpannedIdent,
4646
lifetimes: Vec<ast::Lifetime>,
4747
types: Vec<P<ast::Ty>>,
4848
bindings: Vec<ast::TypeBinding>)
@@ -323,7 +323,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
323323
segments.push(ast::PathSegment::crate_root());
324324
}
325325

326-
segments.extend(idents.into_iter().map(Into::into));
326+
segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, sp)));
327327
let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
328328
None
329329
} else {
@@ -333,7 +333,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
333333
bindings: bindings,
334334
})))
335335
};
336-
segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
336+
segments.push(ast::PathSegment {
337+
identifier: last_identifier,
338+
span: sp,
339+
parameters: parameters
340+
});
337341
ast::Path {
338342
span: sp,
339343
segments: segments,
@@ -346,7 +350,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
346350
fn qpath(&self,
347351
self_type: P<ast::Ty>,
348352
trait_path: ast::Path,
349-
ident: ast::Ident)
353+
ident: ast::SpannedIdent)
350354
-> (ast::QSelf, ast::Path) {
351355
self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
352356
}
@@ -357,7 +361,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
357361
fn qpath_all(&self,
358362
self_type: P<ast::Ty>,
359363
trait_path: ast::Path,
360-
ident: ast::Ident,
364+
ident: ast::SpannedIdent,
361365
lifetimes: Vec<ast::Lifetime>,
362366
types: Vec<P<ast::Ty>>,
363367
bindings: Vec<ast::TypeBinding>)
@@ -369,7 +373,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
369373
bindings: bindings,
370374
};
371375
path.segments.push(ast::PathSegment {
372-
identifier: ident,
376+
identifier: ident.node,
377+
span: ident.span,
373378
parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
374379
});
375380

src/libsyntax/fold.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,9 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
434434

435435
pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
436436
Path {
437-
segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
437+
segments: segments.move_map(|PathSegment {identifier, span, parameters}| PathSegment {
438438
identifier: fld.fold_ident(identifier),
439+
span: fld.new_span(span),
439440
parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
440441
}),
441442
span: fld.new_span(span)

0 commit comments

Comments
 (0)