diff options
| author | Corey Farwell <coreyf@rwell.org> | 2017-03-12 12:48:46 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-03-12 12:48:46 -0400 |
| commit | 8d1c5700f08a657a15c317084f8807c82a6d8fd8 (patch) | |
| tree | abdbc4d3f992133c106c1ad7dbc13f5d44f9c44a /src/libsyntax | |
| parent | f88b24b34c6d17ebe4014bec5a0f7c2a57c529c7 (diff) | |
| parent | ffdcf7486656119328c3c6c1efef408abba3139f (diff) | |
| download | rust-8d1c5700f08a657a15c317084f8807c82a6d8fd8.tar.gz rust-8d1c5700f08a657a15c317084f8807c82a6d8fd8.zip | |
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
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 18 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 29 | ||||
| -rw-r--r-- | src/libsyntax/std_inject.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 2 |
7 files changed, 52 insertions, 35 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 981667337d5..fa320d2ca8b 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<A,B,C>` and `Path(A,B) -> C`. Note that @@ -170,16 +172,14 @@ pub struct PathSegment { pub parameters: Option<P<PathParameters>>, } -impl From<Ident> 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<ast::Ty>, trait_path: ast::Path, - ident: ast::Ident) + ident: ast::SpannedIdent) -> (ast::QSelf, ast::Path); fn qpath_all(&self, self_type: P<ast::Ty>, trait_path: ast::Path, - ident: ast::Ident, + ident: ast::SpannedIdent, lifetimes: Vec<ast::Lifetime>, types: Vec<P<ast::Ty>>, bindings: Vec<ast::TypeBinding>) @@ -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<ast::Ty>, 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<ast::Ty>, trait_path: ast::Path, - ident: ast::Ident, + ident: ast::SpannedIdent, lifetimes: Vec<ast::Lifetime>, types: Vec<P<ast::Ty>>, bindings: Vec<ast::TypeBinding>) @@ -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 fb4eb19be2b..aa968f03d68 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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 { 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 4164932e90e..ff7918cc278 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<T,U>::c<V,W>` /// - `a::b<T,U>::c(V) -> W` /// - `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(); 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::<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(); 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<ast::PathSegment>> { + -> PResult<'a, Vec<PathSegment>> { 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() { @@ -5950,7 +5957,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: T) -> codemap::Spanned<T> { fn path_node(ids: Vec<Ident>) -> 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(), } } |
