1
Fork 0

Rollup merge of #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 https://github.com/rust-lang/rust/pull/38927#discussion_r95336667 https://github.com/rust-lang/rust/pull/38890#issuecomment-271731008

r? @nrc @eddyb
This commit is contained in:
Corey Farwell 2017-03-12 12:48:46 -04:00 committed by GitHub
commit 8d1c5700f0
14 changed files with 124 additions and 88 deletions

View file

@ -407,7 +407,7 @@ enum PathSource<'a> {
// Trait paths in bounds or impls. // Trait paths in bounds or impls.
Trait, Trait,
// Expression paths `path`, with optional parent context. // Expression paths `path`, with optional parent context.
Expr(Option<&'a ExprKind>), Expr(Option<&'a Expr>),
// Paths in path patterns `Path`. // Paths in path patterns `Path`.
Pat, Pat,
// Paths in struct expressions and patterns `Path { .. }`. // Paths in struct expressions and patterns `Path { .. }`.
@ -464,7 +464,7 @@ impl<'a> PathSource<'a> {
ValueNS => "method or associated constant", ValueNS => "method or associated constant",
MacroNS => bug!("associated macro"), 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`, // "function" here means "anything callable" rather than `Def::Fn`,
// this is not precise but usually more helpful than just "value". // this is not precise but usually more helpful than just "value".
Some(&ExprKind::Call(..)) => "function", Some(&ExprKind::Call(..)) => "function",
@ -2200,7 +2200,8 @@ impl<'a> Resolver<'a> {
source: PathSource) source: PathSource)
-> PathResolution { -> PathResolution {
let segments = &path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>(); 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, fn smart_resolve_path_fragment(&mut self,
@ -2208,6 +2209,7 @@ impl<'a> Resolver<'a> {
qself: Option<&QSelf>, qself: Option<&QSelf>,
path: &[Ident], path: &[Ident],
span: Span, span: Span,
ident_span: Span,
source: PathSource) source: PathSource)
-> PathResolution { -> PathResolution {
let ns = source.namespace(); let ns = source.namespace();
@ -2219,9 +2221,9 @@ impl<'a> Resolver<'a> {
let expected = source.descr_expected(); let expected = source.descr_expected();
let path_str = names_to_string(path); let path_str = names_to_string(path);
let code = source.error_code(def.is_some()); 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!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
format!("not a {}", expected)) format!("not a {}", expected), span)
} else { } else {
let item_str = path[path.len() - 1]; let item_str = path[path.len() - 1];
let (mod_prefix, mod_str) = if path.len() == 1 { let (mod_prefix, mod_str) = if path.len() == 1 {
@ -2237,9 +2239,9 @@ impl<'a> Resolver<'a> {
(mod_prefix, format!("`{}`", names_to_string(mod_path))) (mod_prefix, format!("`{}`", names_to_string(mod_path)))
}; };
(format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), (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`. // Emit special messages for unresolved `Self` and `self`.
if is_self_type(path, ns) { if is_self_type(path, ns) {
@ -2297,14 +2299,14 @@ impl<'a> Resolver<'a> {
err.span_label(span, &format!("type aliases cannot be used for traits")); err.span_label(span, &format!("type aliases cannot be used for traits"));
return err; return err;
} }
(Def::Mod(..), PathSource::Expr(Some(parent))) => match *parent { (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
ExprKind::Field(_, ident) => { ExprKind::Field(_, ident) => {
err.span_label(span, &format!("did you mean `{}::{}`?", err.span_label(parent.span, &format!("did you mean `{}::{}`?",
path_str, ident.node)); path_str, ident.node));
return err; return err;
} }
ExprKind::MethodCall(ident, ..) => { ExprKind::MethodCall(ident, ..) => {
err.span_label(span, &format!("did you mean `{}::{}(...)`?", err.span_label(parent.span, &format!("did you mean `{}::{}(...)`?",
path_str, ident.node)); path_str, ident.node));
return err; return err;
} }
@ -2330,12 +2332,12 @@ impl<'a> Resolver<'a> {
// Try Levenshtein if nothing else worked. // Try Levenshtein if nothing else worked.
if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) { 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; return err;
} }
// Fallback label. // Fallback label.
err.span_label(span, &fallback_label); err.span_label(base_span, &fallback_label);
err err
}; };
let report_errors = |this: &mut Self, def: Option<Def>| { let report_errors = |this: &mut Self, def: Option<Def>| {
@ -2455,7 +2457,7 @@ impl<'a> Resolver<'a> {
// Make sure `A::B` in `<T as A>::B::C` is a trait item. // 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 ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1], 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( return Some(PathResolution::with_unresolved_segments(
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1 res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
)); ));
@ -2813,7 +2815,7 @@ impl<'a> Resolver<'a> {
path: &[Ident], path: &[Ident],
ns: Namespace, ns: Namespace,
filter_fn: FilterFn) filter_fn: FilterFn)
-> Option<String> -> Option<Symbol>
where FilterFn: Fn(Def) -> bool where FilterFn: Fn(Def) -> bool
{ {
let add_module_candidates = |module: Module, names: &mut Vec<Name>| { let add_module_candidates = |module: Module, names: &mut Vec<Name>| {
@ -2827,7 +2829,7 @@ impl<'a> Resolver<'a> {
}; };
let mut names = Vec::new(); let mut names = Vec::new();
let prefix_str = if path.len() == 1 { if path.len() == 1 {
// Search in lexical scope. // Search in lexical scope.
// Walk backwards up the ribs in scope and collect candidates. // Walk backwards up the ribs in scope and collect candidates.
for rib in self.ribs[ns].iter().rev() { for rib in self.ribs[ns].iter().rev() {
@ -2861,21 +2863,19 @@ impl<'a> Resolver<'a> {
names.push(*name); names.push(*name);
} }
} }
String::new()
} else { } else {
// Search in module. // Search in module.
let mod_path = &path[..path.len() - 1]; let mod_path = &path[..path.len() - 1];
if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) { if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) {
add_module_candidates(module, &mut names); add_module_candidates(module, &mut names);
} }
names_to_string(mod_path) + "::" }
};
let name = path[path.len() - 1].name; let name = path[path.len() - 1].name;
// Make sure error reporting is deterministic. // Make sure error reporting is deterministic.
names.sort_by_key(|name| name.as_str()); names.sort_by_key(|name| name.as_str());
match find_best_match_for_name(names.iter(), &name.as_str(), None) { 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, _ => None,
} }
} }
@ -2898,7 +2898,7 @@ impl<'a> Resolver<'a> {
self.with_resolved_label(label, id, |this| this.visit_block(block)); 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 // First, record candidate traits for this expression if it could
// result in the invocation of a method call. // result in the invocation of a method call.
@ -2979,11 +2979,11 @@ impl<'a> Resolver<'a> {
// Equivalent to `visit::walk_expr` + passing some context to children. // Equivalent to `visit::walk_expr` + passing some context to children.
ExprKind::Field(ref subexpression, _) => { ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(&expr.node)); self.resolve_expr(subexpression, Some(expr));
} }
ExprKind::MethodCall(_, ref types, ref arguments) => { ExprKind::MethodCall(_, ref types, ref arguments) => {
let mut arguments = arguments.iter(); 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 { for argument in arguments {
self.resolve_expr(argument, None); self.resolve_expr(argument, None);
} }
@ -2999,7 +2999,7 @@ impl<'a> Resolver<'a> {
}); });
} }
ExprKind::Call(ref callee, ref arguments) => { ExprKind::Call(ref callee, ref arguments) => {
self.resolve_expr(callee, Some(&expr.node)); self.resolve_expr(callee, Some(expr));
for argument in arguments { for argument in arguments {
self.resolve_expr(argument, None); self.resolve_expr(argument, None);
} }
@ -3130,11 +3130,10 @@ impl<'a> Resolver<'a> {
if ident.name == lookup_name && ns == namespace { if ident.name == lookup_name && ns == namespace {
if filter_fn(name_binding.def()) { if filter_fn(name_binding.def()) {
// create the path // create the path
let span = name_binding.span;
let mut segms = path_segments.clone(); let mut segms = path_segments.clone();
segms.push(ident.into()); segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
let path = Path { let path = Path {
span: span, span: name_binding.span,
segments: segms, segments: segms,
}; };
// the entity is accessible in the following cases: // the entity is accessible in the following cases:
@ -3154,7 +3153,7 @@ impl<'a> Resolver<'a> {
if let Some(module) = name_binding.module() { if let Some(module) = name_binding.module() {
// form the path // form the path
let mut path_segments = path_segments.clone(); let mut path_segments = path_segments.clone();
path_segments.push(ident.into()); path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
// add the module to the lookup // add the module to the lookup

View file

@ -111,8 +111,11 @@ impl<'a> base::Resolver for Resolver<'a> {
path.segments[0].identifier.name = keywords::CrateRoot.name(); path.segments[0].identifier.name = keywords::CrateRoot.name();
let module = self.0.resolve_crate_var(ident.ctxt); let module = self.0.resolve_crate_var(ident.ctxt);
if !module.is_local() { if !module.is_local() {
let span = path.segments[0].span;
path.segments.insert(1, match module.kind { path.segments.insert(1, match module.kind {
ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name).into(), ModuleKind::Def(_, name) => ast::PathSegment::from_ident(
ast::Ident::with_empty_ctxt(name), span
),
_ => unreachable!(), _ => unreachable!(),
}) })
} }
@ -569,7 +572,6 @@ impl<'a> Resolver<'a> {
}; };
let ident = Ident::from_str(name); let ident = Ident::from_str(name);
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro) self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
.as_ref().map(|s| Symbol::intern(s))
}); });
if let Some(suggestion) = suggestion { if let Some(suggestion) = suggestion {

View file

@ -134,7 +134,7 @@ impl Path {
pub fn from_ident(s: Span, identifier: Ident) -> Path { pub fn from_ident(s: Span, identifier: Ident) -> Path {
Path { Path {
span: s, span: s,
segments: vec![identifier.into()], segments: vec![PathSegment::from_ident(identifier, s)],
} }
} }
@ -159,6 +159,8 @@ impl Path {
pub struct PathSegment { pub struct PathSegment {
/// The identifier portion of this path segment. /// The identifier portion of this path segment.
pub identifier: Ident, pub identifier: Ident,
/// Span of the segment identifier.
pub span: Span,
/// Type/lifetime parameters attached to this path. They come in /// Type/lifetime parameters attached to this path. They come in
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
@ -170,16 +172,14 @@ pub struct PathSegment {
pub parameters: Option<P<PathParameters>>, pub parameters: Option<P<PathParameters>>,
} }
impl From<Ident> for PathSegment {
fn from(id: Ident) -> Self {
PathSegment { identifier: id, parameters: None }
}
}
impl PathSegment { impl PathSegment {
pub fn from_ident(ident: Ident, span: Span) -> Self {
PathSegment { identifier: ident, span: span, parameters: None }
}
pub fn crate_root() -> Self { pub fn crate_root() -> Self {
PathSegment { PathSegment {
identifier: keywords::CrateRoot.ident(), identifier: keywords::CrateRoot.ident(),
span: DUMMY_SP,
parameters: None, parameters: None,
} }
} }

View file

@ -38,11 +38,11 @@ pub trait AstBuilder {
fn qpath(&self, self_type: P<ast::Ty>, fn qpath(&self, self_type: P<ast::Ty>,
trait_path: ast::Path, trait_path: ast::Path,
ident: ast::Ident) ident: ast::SpannedIdent)
-> (ast::QSelf, ast::Path); -> (ast::QSelf, ast::Path);
fn qpath_all(&self, self_type: P<ast::Ty>, fn qpath_all(&self, self_type: P<ast::Ty>,
trait_path: ast::Path, trait_path: ast::Path,
ident: ast::Ident, ident: ast::SpannedIdent,
lifetimes: Vec<ast::Lifetime>, lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>, types: Vec<P<ast::Ty>>,
bindings: Vec<ast::TypeBinding>) bindings: Vec<ast::TypeBinding>)
@ -323,7 +323,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
segments.push(ast::PathSegment::crate_root()); segments.push(ast::PathSegment::crate_root());
} }
segments.extend(idents.into_iter().map(Into::into)); segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, sp)));
let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() { let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
None None
} else { } else {
@ -333,7 +333,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
bindings: bindings, bindings: bindings,
}))) })))
}; };
segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters }); segments.push(ast::PathSegment {
identifier: last_identifier,
span: sp,
parameters: parameters
});
ast::Path { ast::Path {
span: sp, span: sp,
segments: segments, segments: segments,
@ -346,7 +350,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn qpath(&self, fn qpath(&self,
self_type: P<ast::Ty>, self_type: P<ast::Ty>,
trait_path: ast::Path, trait_path: ast::Path,
ident: ast::Ident) ident: ast::SpannedIdent)
-> (ast::QSelf, ast::Path) { -> (ast::QSelf, ast::Path) {
self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
} }
@ -357,7 +361,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn qpath_all(&self, fn qpath_all(&self,
self_type: P<ast::Ty>, self_type: P<ast::Ty>,
trait_path: ast::Path, trait_path: ast::Path,
ident: ast::Ident, ident: ast::SpannedIdent,
lifetimes: Vec<ast::Lifetime>, lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>, types: Vec<P<ast::Ty>>,
bindings: Vec<ast::TypeBinding>) bindings: Vec<ast::TypeBinding>)
@ -369,7 +373,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
bindings: bindings, bindings: bindings,
}; };
path.segments.push(ast::PathSegment { path.segments.push(ast::PathSegment {
identifier: ident, identifier: ident.node,
span: ident.span,
parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))), parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
}); });

View file

@ -434,8 +434,9 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path { pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
Path { Path {
segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment { segments: segments.move_map(|PathSegment {identifier, span, parameters}| PathSegment {
identifier: fld.fold_ident(identifier), identifier: fld.fold_ident(identifier),
span: fld.new_span(span),
parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))), parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
}), }),
span: fld.new_span(span) span: fld.new_span(span)

View file

@ -617,13 +617,17 @@ mod tests {
Span {lo: BytePos(a), hi: BytePos(b), expn_id: NO_EXPANSION} Span {lo: BytePos(a), hi: BytePos(b), expn_id: NO_EXPANSION}
} }
fn str2seg(s: &str, lo: u32, hi: u32) -> ast::PathSegment {
ast::PathSegment::from_ident(Ident::from_str(s), sp(lo, hi))
}
#[test] fn path_exprs_1() { #[test] fn path_exprs_1() {
assert!(string_to_expr("a".to_string()) == assert!(string_to_expr("a".to_string()) ==
P(ast::Expr{ P(ast::Expr{
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path { node: ast::ExprKind::Path(None, ast::Path {
span: sp(0, 1), span: sp(0, 1),
segments: vec![Ident::from_str("a").into()], segments: vec![str2seg("a", 0, 1)],
}), }),
span: sp(0, 1), span: sp(0, 1),
attrs: ThinVec::new(), attrs: ThinVec::new(),
@ -637,8 +641,8 @@ mod tests {
node: ast::ExprKind::Path(None, ast::Path { node: ast::ExprKind::Path(None, ast::Path {
span: sp(0, 6), span: sp(0, 6),
segments: vec![ast::PathSegment::crate_root(), segments: vec![ast::PathSegment::crate_root(),
Ident::from_str("a").into(), str2seg("a", 2, 3),
Ident::from_str("b").into()] str2seg("b", 5, 6)]
}), }),
span: sp(0, 6), span: sp(0, 6),
attrs: ThinVec::new(), attrs: ThinVec::new(),
@ -744,7 +748,7 @@ mod tests {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node:ast::ExprKind::Path(None, ast::Path{ node:ast::ExprKind::Path(None, ast::Path{
span: sp(7, 8), span: sp(7, 8),
segments: vec![Ident::from_str("d").into()], segments: vec![str2seg("d", 7, 8)],
}), }),
span:sp(7,8), span:sp(7,8),
attrs: ThinVec::new(), attrs: ThinVec::new(),
@ -761,7 +765,7 @@ mod tests {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path { node: ast::ExprKind::Path(None, ast::Path {
span:sp(0,1), span:sp(0,1),
segments: vec![Ident::from_str("b").into()], segments: vec![str2seg("b", 0, 1)],
}), }),
span: sp(0,1), span: sp(0,1),
attrs: ThinVec::new()})), attrs: ThinVec::new()})),
@ -802,7 +806,7 @@ mod tests {
ty: P(ast::Ty{id: ast::DUMMY_NODE_ID, ty: P(ast::Ty{id: ast::DUMMY_NODE_ID,
node: ast::TyKind::Path(None, ast::Path{ node: ast::TyKind::Path(None, ast::Path{
span:sp(10,13), span:sp(10,13),
segments: vec![Ident::from_str("i32").into()], segments: vec![str2seg("i32", 10, 13)],
}), }),
span:sp(10,13) span:sp(10,13)
}), }),
@ -844,7 +848,7 @@ mod tests {
node: ast::ExprKind::Path(None, node: ast::ExprKind::Path(None,
ast::Path{ ast::Path{
span:sp(17,18), span:sp(17,18),
segments: vec![Ident::from_str("b").into()], segments: vec![str2seg("b", 17, 18)],
}), }),
span: sp(17,18), span: sp(17,18),
attrs: ThinVec::new()})), attrs: ThinVec::new()})),

View file

@ -27,7 +27,7 @@ use ast::Local;
use ast::MacStmtStyle; use ast::MacStmtStyle;
use ast::Mac_; use ast::Mac_;
use ast::{MutTy, Mutability}; use ast::{MutTy, Mutability};
use ast::{Pat, PatKind}; use ast::{Pat, PatKind, PathSegment};
use ast::{PolyTraitRef, QSelf}; use ast::{PolyTraitRef, QSelf};
use ast::{Stmt, StmtKind}; use ast::{Stmt, StmtKind};
use ast::{VariantData, StructField}; use ast::{VariantData, StructField};
@ -1811,7 +1811,7 @@ impl<'a> Parser<'a> {
}; };
if is_global { if is_global {
segments.insert(0, ast::PathSegment::crate_root()); segments.insert(0, PathSegment::crate_root());
} }
// Assemble the span. // Assemble the span.
@ -1829,11 +1829,12 @@ impl<'a> Parser<'a> {
/// - `a::b<T,U>::c<V,W>` /// - `a::b<T,U>::c<V,W>`
/// - `a::b<T,U>::c(V) -> W` /// - `a::b<T,U>::c(V) -> W`
/// - `a::b<T,U>::c(V)` /// - `a::b<T,U>::c(V)`
pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> { pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<PathSegment>> {
let mut segments = Vec::new(); let mut segments = Vec::new();
loop { loop {
// First, parse an identifier. // First, parse an identifier.
let identifier = self.parse_path_segment_ident()?; let identifier = self.parse_path_segment_ident()?;
let ident_span = self.prev_span;
if self.check(&token::ModSep) && self.look_ahead(1, |t| *t == token::Lt) { if self.check(&token::ModSep) && self.look_ahead(1, |t| *t == token::Lt) {
self.bump(); self.bump();
@ -1881,7 +1882,11 @@ impl<'a> Parser<'a> {
}; };
// Assemble and push the result. // Assemble and push the result.
segments.push(ast::PathSegment { identifier: identifier, parameters: parameters }); segments.push(PathSegment {
identifier: identifier,
span: ident_span,
parameters: parameters
});
// Continue only if we see a `::` // Continue only if we see a `::`
if !self.eat(&token::ModSep) { if !self.eat(&token::ModSep) {
@ -1892,15 +1897,16 @@ impl<'a> Parser<'a> {
/// Examples: /// Examples:
/// - `a::b::<T,U>::c` /// - `a::b::<T,U>::c`
pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> { pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<PathSegment>> {
let mut segments = Vec::new(); let mut segments = Vec::new();
loop { loop {
// First, parse an identifier. // First, parse an identifier.
let identifier = self.parse_path_segment_ident()?; let identifier = self.parse_path_segment_ident()?;
let ident_span = self.prev_span;
// If we do not see a `::`, stop. // If we do not see a `::`, stop.
if !self.eat(&token::ModSep) { if !self.eat(&token::ModSep) {
segments.push(identifier.into()); segments.push(PathSegment::from_ident(identifier, ident_span));
return Ok(segments); return Ok(segments);
} }
@ -1909,8 +1915,9 @@ impl<'a> Parser<'a> {
// Consumed `a::b::<`, go look for types // Consumed `a::b::<`, go look for types
let (lifetimes, types, bindings) = self.parse_generic_args()?; let (lifetimes, types, bindings) = self.parse_generic_args()?;
self.expect_gt()?; self.expect_gt()?;
segments.push(ast::PathSegment { segments.push(PathSegment {
identifier: identifier, identifier: identifier,
span: ident_span,
parameters: ast::AngleBracketedParameterData { parameters: ast::AngleBracketedParameterData {
lifetimes: lifetimes, lifetimes: lifetimes,
types: types, types: types,
@ -1924,7 +1931,7 @@ impl<'a> Parser<'a> {
} }
} else { } else {
// Consumed `a::`, go look for `b` // Consumed `a::`, go look for `b`
segments.push(identifier.into()); segments.push(PathSegment::from_ident(identifier, ident_span));
} }
} }
} }
@ -1932,14 +1939,14 @@ impl<'a> Parser<'a> {
/// Examples: /// Examples:
/// - `a::b::c` /// - `a::b::c`
pub fn parse_path_segments_without_types(&mut self) pub fn parse_path_segments_without_types(&mut self)
-> PResult<'a, Vec<ast::PathSegment>> { -> PResult<'a, Vec<PathSegment>> {
let mut segments = Vec::new(); let mut segments = Vec::new();
loop { loop {
// First, parse an identifier. // First, parse an identifier.
let identifier = self.parse_path_segment_ident()?; let identifier = self.parse_path_segment_ident()?;
// Assemble and push the result. // Assemble and push the result.
segments.push(identifier.into()); segments.push(PathSegment::from_ident(identifier, self.prev_span));
// If we do not see a `::` or see `::{`/`::*`, stop. // If we do not see a `::` or see `::{`/`::*`, stop.
if !self.check(&token::ModSep) || self.is_import_coupler() { if !self.check(&token::ModSep) || self.is_import_coupler() {
@ -5950,7 +5957,7 @@ impl<'a> Parser<'a> {
// `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`. // `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`.
self.eat(&token::ModSep); self.eat(&token::ModSep);
let prefix = ast::Path { let prefix = ast::Path {
segments: vec![ast::PathSegment::crate_root()], segments: vec![PathSegment::crate_root()],
span: mk_sp(lo, self.span.hi), span: mk_sp(lo, self.span.hi),
}; };
let view_path_kind = if self.eat(&token::BinOp(token::Star)) { let view_path_kind = if self.eat(&token::BinOp(token::Star)) {

View file

@ -82,7 +82,7 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess,
vis: ast::Visibility::Inherited, vis: ast::Visibility::Inherited,
node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path { node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| { segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
ast::Ident::from_str(name).into() ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP)
}).collect(), }).collect(),
span: span, span: span,
})))), })))),

View file

@ -580,7 +580,7 @@ fn nospan<T>(t: T) -> codemap::Spanned<T> {
fn path_node(ids: Vec<Ident>) -> ast::Path { fn path_node(ids: Vec<Ident>) -> ast::Path {
ast::Path { ast::Path {
span: DUMMY_SP, span: DUMMY_SP,
segments: ids.into_iter().map(Into::into).collect(), segments: ids.into_iter().map(|id| ast::PathSegment::from_ident(id, DUMMY_SP)).collect(),
} }
} }

View file

@ -61,7 +61,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
fn path(&self) -> ast::Path { fn path(&self) -> ast::Path {
ast::Path { ast::Path {
span: self.span, span: self.span,
segments: vec![self.ident.into()], segments: vec![ast::PathSegment::from_ident(self.ident, self.span)],
} }
} }
} }

View file

@ -1,26 +1,26 @@
error[E0425]: cannot find value `A` in module `namespaced_enums` 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; 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: = help: possible candidate is found in another module, you can import it into scope:
`use namespaced_enums::Foo::A;` `use namespaced_enums::Foo::A;`
error[E0425]: cannot find function `B` in module `namespaced_enums` 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); 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: = help: possible candidate is found in another module, you can import it into scope:
`use namespaced_enums::Foo::B;` `use namespaced_enums::Foo::B;`
error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums` 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 }; 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: = help: possible candidate is found in another module, you can import it into scope:
`use namespaced_enums::Foo::C;` `use namespaced_enums::Foo::C;`

View file

@ -14,7 +14,7 @@ error[E0412]: cannot find type `Opiton` in this scope
--> $DIR/levenshtein.rs:20:10 --> $DIR/levenshtein.rs:20:10
| |
20 | type B = Opiton<u8>; // Misspelled type name from the prelude. 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 error[E0412]: cannot find type `Baz` in this scope
--> $DIR/levenshtein.rs:23:14 --> $DIR/levenshtein.rs:23:14
@ -35,16 +35,16 @@ error[E0425]: cannot find function `foobar` in this scope
| ^^^^^^ did you mean `foo_bar`? | ^^^^^^ did you mean `foo_bar`?
error[E0412]: cannot find type `first` in module `m` 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. 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` 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. 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 error: aborting due to 8 previous errors

View file

@ -2,55 +2,73 @@ error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
| |
27 | a.I 27 | a.I
| ^ did you mean `a::I`? | ^--
| |
| did you mean `a::I`?
error[E0423]: expected value, found module `a` error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:33:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:33:5
| |
33 | a.g() 33 | a.g()
| ^ did you mean `a::g(...)`? | ^----
| |
| did you mean `a::g(...)`?
error[E0423]: expected value, found module `a` error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:39:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:39:5
| |
39 | a.b.J 39 | a.b.J
| ^ did you mean `a::b`? | ^--
| |
| did you mean `a::b`?
error[E0423]: expected value, found module `a::b` error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
| |
45 | a::b.J 45 | a::b.J
| ^^^^ did you mean `a::b::J`? | ^^^^--
| |
| did you mean `a::b::J`?
error[E0423]: expected value, found module `a` error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:51:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:51:5
| |
51 | a.b.f(); 51 | a.b.f();
| ^ did you mean `a::b`? | ^--
| |
| did you mean `a::b`?
error[E0423]: expected value, found module `a::b` error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:12 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:12
| |
55 | v.push(a::b); 55 | v.push(a::b);
| ^^^^ did you mean `a::I`? | ^^^-
| |
| did you mean `I`?
error[E0423]: expected value, found module `a::b` error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:61:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:61:5
| |
61 | a::b.f() 61 | a::b.f()
| ^^^^ did you mean `a::b::f(...)`? | ^^^^----
| |
| did you mean `a::b::f(...)`?
error[E0423]: expected value, found module `a::b` error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:67:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:67:5
| |
67 | a::b 67 | a::b
| ^^^^ did you mean `a::I`? | ^^^-
| |
| did you mean `I`?
error[E0423]: expected function, found module `a::b` error[E0423]: expected function, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:73:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:73:5
| |
73 | a::b() 73 | a::b()
| ^^^^ did you mean `a::I`? | ^^^-
| |
| did you mean `I`?
error: main function not found error: main function not found

View file

@ -2,7 +2,7 @@ error[E0405]: cannot find trait `Nonexist` in this scope
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:11:8 --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:11:8
| |
11 | fn f<F:Nonexist(isize) -> isize>(x: F) {} 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` error[E0404]: expected trait, found type alias `Typedef`
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:17:8 --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:17:8