diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d51ec268ec2..105af23d05c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3124,11 +3124,10 @@ impl<'a> Resolver<'a> { if ident.name == lookup_name && ns == namespace { if filter_fn(name_binding.def()) { // create the path - let span = name_binding.span; let mut segms = path_segments.clone(); - segms.push(ident.into()); + segms.push(ast::PathSegment::from_ident(ident, name_binding.span)); let path = Path { - span: span, + span: name_binding.span, segments: segms, }; // the entity is accessible in the following cases: @@ -3148,7 +3147,7 @@ impl<'a> Resolver<'a> { if let Some(module) = name_binding.module() { // form the path 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 { // add the module to the lookup diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 720d616e007..d81bdf17034 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -110,8 +110,11 @@ impl<'a> base::Resolver for Resolver<'a> { path.segments[0].identifier.name = keywords::CrateRoot.name(); let module = self.0.resolve_crate_var(ident.ctxt); if !module.is_local() { + let span = path.segments[0].span; 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!(), }) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9cc754cbf4d..adb7e8d101f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -134,7 +134,7 @@ impl Path { pub fn from_ident(s: Span, identifier: Ident) -> Path { Path { span: s, - segments: vec![identifier.into()], + segments: vec![PathSegment::from_ident(identifier, s)], } } @@ -159,6 +159,8 @@ impl Path { pub struct PathSegment { /// The identifier portion of this path segment. pub identifier: Ident, + /// Span of the segment identifier. + pub span: Span, /// Type/lifetime parameters attached to this path. They come in /// two flavors: `Path` and `Path(A,B) -> C`. Note that @@ -170,16 +172,14 @@ pub struct PathSegment { pub parameters: Option>, } -impl From for PathSegment { - fn from(id: Ident) -> Self { - PathSegment { identifier: id, parameters: None } - } -} - impl PathSegment { + pub fn from_ident(ident: Ident, span: Span) -> Self { + PathSegment { identifier: ident, span: span, parameters: None } + } pub fn crate_root() -> Self { PathSegment { identifier: keywords::CrateRoot.ident(), + span: DUMMY_SP, parameters: None, } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index f8d4eff80b2..e0fb46ff5eb 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -38,11 +38,11 @@ pub trait AstBuilder { fn qpath(&self, self_type: P, trait_path: ast::Path, - ident: ast::Ident) + ident: ast::SpannedIdent) -> (ast::QSelf, ast::Path); fn qpath_all(&self, self_type: P, trait_path: ast::Path, - ident: ast::Ident, + ident: ast::SpannedIdent, lifetimes: Vec, types: Vec>, bindings: Vec) @@ -323,7 +323,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { 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() { None } else { @@ -333,7 +333,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> { bindings: bindings, }))) }; - segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters }); + segments.push(ast::PathSegment { + identifier: last_identifier, + span: sp, + parameters: parameters + }); ast::Path { span: sp, segments: segments, @@ -346,7 +350,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn qpath(&self, self_type: P, trait_path: ast::Path, - ident: ast::Ident) + ident: ast::SpannedIdent) -> (ast::QSelf, ast::Path) { 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, self_type: P, trait_path: ast::Path, - ident: ast::Ident, + ident: ast::SpannedIdent, lifetimes: Vec, types: Vec>, bindings: Vec) @@ -369,7 +373,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { bindings: bindings, }; path.segments.push(ast::PathSegment { - identifier: ident, + identifier: ident.node, + span: ident.span, parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))), }); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 4242b0f8b98..665f48ab456 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -434,8 +434,9 @@ pub fn noop_fold_usize(i: usize, _: &mut T) -> usize { pub fn noop_fold_path(Path { segments, span }: Path, fld: &mut T) -> Path { Path { - segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment { + segments: segments.move_map(|PathSegment {identifier, span, parameters}| PathSegment { identifier: fld.fold_ident(identifier), + span: fld.new_span(span), parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))), }), span: fld.new_span(span) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index c00d2952b3b..88535f91379 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -617,13 +617,17 @@ mod tests { 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() { assert!(string_to_expr("a".to_string()) == P(ast::Expr{ id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Path(None, ast::Path { span: sp(0, 1), - segments: vec![Ident::from_str("a").into()], + segments: vec![str2seg("a", 0, 1)], }), span: sp(0, 1), attrs: ThinVec::new(), @@ -637,8 +641,8 @@ mod tests { node: ast::ExprKind::Path(None, ast::Path { span: sp(0, 6), segments: vec![ast::PathSegment::crate_root(), - Ident::from_str("a").into(), - Ident::from_str("b").into()] + str2seg("a", 2, 3), + str2seg("b", 5, 6)] }), span: sp(0, 6), attrs: ThinVec::new(), @@ -744,7 +748,7 @@ mod tests { id: ast::DUMMY_NODE_ID, node:ast::ExprKind::Path(None, ast::Path{ span: sp(7, 8), - segments: vec![Ident::from_str("d").into()], + segments: vec![str2seg("d", 7, 8)], }), span:sp(7,8), attrs: ThinVec::new(), @@ -761,7 +765,7 @@ mod tests { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Path(None, ast::Path { span:sp(0,1), - segments: vec![Ident::from_str("b").into()], + segments: vec![str2seg("b", 0, 1)], }), span: sp(0,1), attrs: ThinVec::new()})), @@ -802,7 +806,7 @@ mod tests { ty: P(ast::Ty{id: ast::DUMMY_NODE_ID, node: ast::TyKind::Path(None, ast::Path{ span:sp(10,13), - segments: vec![Ident::from_str("i32").into()], + segments: vec![str2seg("i32", 10, 13)], }), span:sp(10,13) }), @@ -844,7 +848,7 @@ mod tests { node: ast::ExprKind::Path(None, ast::Path{ span:sp(17,18), - segments: vec![Ident::from_str("b").into()], + segments: vec![str2seg("b", 17, 18)], }), span: sp(17,18), attrs: ThinVec::new()})), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6c566dab1d6..002f1359b6f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -27,7 +27,7 @@ use ast::Local; use ast::MacStmtStyle; use ast::Mac_; use ast::{MutTy, Mutability}; -use ast::{Pat, PatKind}; +use ast::{Pat, PatKind, PathSegment}; use ast::{PolyTraitRef, QSelf}; use ast::{Stmt, StmtKind}; use ast::{VariantData, StructField}; @@ -1811,7 +1811,7 @@ impl<'a> Parser<'a> { }; if is_global { - segments.insert(0, ast::PathSegment::crate_root()); + segments.insert(0, PathSegment::crate_root()); } // Assemble the span. @@ -1829,11 +1829,12 @@ impl<'a> Parser<'a> { /// - `a::b::c` /// - `a::b::c(V) -> W` /// - `a::b::c(V)` - pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec> { + pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec> { let mut segments = Vec::new(); loop { // First, parse an identifier. 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) { self.bump(); @@ -1881,7 +1882,11 @@ impl<'a> Parser<'a> { }; // 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 `::` if !self.eat(&token::ModSep) { @@ -1892,15 +1897,16 @@ impl<'a> Parser<'a> { /// Examples: /// - `a::b::::c` - pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec> { + pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec> { let mut segments = Vec::new(); loop { // First, parse an identifier. let identifier = self.parse_path_segment_ident()?; + let ident_span = self.prev_span; // If we do not see a `::`, stop. if !self.eat(&token::ModSep) { - segments.push(identifier.into()); + segments.push(PathSegment::from_ident(identifier, ident_span)); return Ok(segments); } @@ -1909,8 +1915,9 @@ impl<'a> Parser<'a> { // Consumed `a::b::<`, go look for types let (lifetimes, types, bindings) = self.parse_generic_args()?; self.expect_gt()?; - segments.push(ast::PathSegment { + segments.push(PathSegment { identifier: identifier, + span: ident_span, parameters: ast::AngleBracketedParameterData { lifetimes: lifetimes, types: types, @@ -1924,7 +1931,7 @@ impl<'a> Parser<'a> { } } else { // 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: /// - `a::b::c` pub fn parse_path_segments_without_types(&mut self) - -> PResult<'a, Vec> { + -> PResult<'a, Vec> { let mut segments = Vec::new(); loop { // First, parse an identifier. let identifier = self.parse_path_segment_ident()?; // 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 !self.check(&token::ModSep) || self.is_import_coupler() { @@ -5902,7 +5909,7 @@ impl<'a> Parser<'a> { // `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`. self.eat(&token::ModSep); let prefix = ast::Path { - segments: vec![ast::PathSegment::crate_root()], + segments: vec![PathSegment::crate_root()], span: mk_sp(lo, self.span.hi), }; let view_path_kind = if self.eat(&token::BinOp(token::Star)) { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 4a2dfaf6124..2192d203cdc 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -82,7 +82,7 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess, vis: ast::Visibility::Inherited, node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path { 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(), span: span, })))), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index dd2756cd2b2..e052d2cda3a 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -580,7 +580,7 @@ fn nospan(t: T) -> codemap::Spanned { fn path_node(ids: Vec) -> ast::Path { ast::Path { 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(), } } diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 1fc1bdff593..dc4b8eb24cd 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -61,7 +61,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, fn path(&self) -> ast::Path { ast::Path { span: self.span, - segments: vec![self.ident.into()], + segments: vec![ast::PathSegment::from_ident(self.ident, self.span)], } } }