Skip to content

Commit 4b3de6f

Browse files
Ariel Ben-Yehudaalexcrichton
Ariel Ben-Yehuda
authored andcommitted
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 5030922 + 7cfe20c commit 4b3de6f

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",
@@ -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
}
@@ -3124,11 +3124,10 @@ impl<'a> Resolver<'a> {
31243124
if ident.name == lookup_name && ns == namespace {
31253125
if filter_fn(name_binding.def()) {
31263126
// create the path
3127-
let span = name_binding.span;
31283127
let mut segms = path_segments.clone();
3129-
segms.push(ident.into());
3128+
segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
31303129
let path = Path {
3131-
span: span,
3130+
span: name_binding.span,
31323131
segments: segms,
31333132
};
31343133
// the entity is accessible in the following cases:
@@ -3148,7 +3147,7 @@ impl<'a> Resolver<'a> {
31483147
if let Some(module) = name_binding.module() {
31493148
// form the path
31503149
let mut path_segments = path_segments.clone();
3151-
path_segments.push(ident.into());
3150+
path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
31523151

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

src/librustc_resolve/macros.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,11 @@ impl<'a> base::Resolver for Resolver<'a> {
110110
path.segments[0].identifier.name = keywords::CrateRoot.name();
111111
let module = self.0.resolve_crate_var(ident.ctxt);
112112
if !module.is_local() {
113+
let span = path.segments[0].span;
113114
path.segments.insert(1, match module.kind {
114-
ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name).into(),
115+
ModuleKind::Def(_, name) => ast::PathSegment::from_ident(
116+
ast::Ident::with_empty_ctxt(name), span
117+
),
115118
_ => unreachable!(),
116119
})
117120
}
@@ -499,7 +502,6 @@ impl<'a> Resolver<'a> {
499502
};
500503
let ident = Ident::from_str(name);
501504
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
502-
.as_ref().map(|s| Symbol::intern(s))
503505
});
504506

505507
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)