From e5fb13897d947e13a1322a055b71632e30357eff Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 10 Mar 2018 02:02:39 +0300 Subject: AST: Keep distinction between `path` and `::path` in imports and visibilities Add the root segment for name resolution purposes only --- src/libsyntax/ast.rs | 17 ++++++++--------- src/libsyntax/ext/build.rs | 10 +++++++--- src/libsyntax/parse/parser.rs | 15 +++++---------- src/libsyntax/parse/token.rs | 1 + src/libsyntax/print/pprust.rs | 43 +++++++++++++++++++------------------------ src/libsyntax/std_inject.rs | 2 +- 6 files changed, 41 insertions(+), 47 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index fdb32486b5d..4ce6c53d338 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -108,17 +108,16 @@ impl Path { } } - // Add starting "crate root" segment to all paths except those that - // already have it or start with `self`, `super`, `Self` or `$crate`. - pub fn default_to_global(mut self) -> Path { - if !self.is_global() { - let ident = self.segments[0].identifier; - if !::parse::token::Ident(ident).is_path_segment_keyword() || - ident.name == keywords::Crate.name() { - self.segments.insert(0, PathSegment::crate_root(self.span)); + // Make a "crate root" segment for this path unless it already has it + // or starts with something like `self`/`super`/`$crate`/etc. + pub fn make_root(&self) -> Option { + if let Some(ident) = self.segments.get(0).map(|seg| seg.identifier) { + if ::parse::token::Ident(ident).is_path_segment_keyword() && + ident.name != keywords::Crate.name() { + return None; } } - self + Some(PathSegment::crate_root(self.span.with_hi(self.span.lo()))) } pub fn is_global(&self) -> bool { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 97f784dd617..ee646dc9174 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -329,9 +329,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> { None }; segments.push(ast::PathSegment { identifier: last_identifier, span, parameters }); - let path = ast::Path { span, segments }; - - if global { path.default_to_global() } else { path } + let mut path = ast::Path { span, segments }; + if global { + if let Some(seg) = path.make_root() { + path.segments.insert(0, seg); + } + } + path } /// Constructs a qualified path. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7a432930490..ca879765b4e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5869,7 +5869,7 @@ impl<'a> Parser<'a> { // `pub(in path)` self.bump(); // `(` self.bump(); // `in` - let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path` + let path = self.parse_path(PathStyle::Mod)?; // `path` self.expect(&token::CloseDelim(token::Paren))?; // `)` let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { path: P(path), @@ -5882,7 +5882,7 @@ impl<'a> Parser<'a> { { // `pub(self)` or `pub(super)` self.bump(); // `(` - let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self` + let path = self.parse_path(PathStyle::Mod)?; // `super`/`self` self.expect(&token::CloseDelim(token::Paren))?; // `)` let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { path: P(path), @@ -6480,7 +6480,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::Use) { // USE ITEM - let item_ = ItemKind::Use(P(self.parse_use_tree(false)?)); + let item_ = ItemKind::Use(P(self.parse_use_tree()?)); self.expect(&token::Semi)?; let prev_span = self.prev_span; @@ -6984,7 +6984,7 @@ impl<'a> Parser<'a> { /// PATH `::` `*` | /// PATH `::` `{` USE_TREE_LIST `}` | /// PATH [`as` IDENT] - fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> { + fn parse_use_tree(&mut self) -> PResult<'a, UseTree> { let lo = self.span; let mut prefix = ast::Path { @@ -6998,8 +6998,6 @@ impl<'a> Parser<'a> { // Remove the first `::` if self.eat(&token::ModSep) { prefix.segments.push(PathSegment::crate_root(self.prev_span)); - } else if !nested { - prefix.segments.push(PathSegment::crate_root(self.span)); } if self.eat(&token::BinOp(token::Star)) { @@ -7014,9 +7012,6 @@ impl<'a> Parser<'a> { } else { // `use path::...;` let mut parsed = self.parse_path(PathStyle::Mod)?; - if !nested { - parsed = parsed.default_to_global(); - } prefix.segments.append(&mut parsed.segments); prefix.span = prefix.span.to(parsed.span); @@ -7051,7 +7046,7 @@ impl<'a> Parser<'a> { self.parse_unspanned_seq(&token::OpenDelim(token::Brace), &token::CloseDelim(token::Brace), SeqSep::trailing_allowed(token::Comma), |this| { - Ok((this.parse_use_tree(true)?, ast::DUMMY_NODE_ID)) + Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID)) }) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 097a2eb89fd..3c602f1d1a8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -362,6 +362,7 @@ impl Token { id.name == keywords::SelfType.name() || id.name == keywords::Extern.name() || id.name == keywords::Crate.name() || + id.name == keywords::CrateRoot.name() || id.name == keywords::DollarCrate.name(), None => false, } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 18a758ba968..319a9a3bbae 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -353,7 +353,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String { } pub fn path_to_string(p: &ast::Path) -> String { - to_string(|s| s.print_path(p, false, 0, false)) + to_string(|s| s.print_path(p, false, 0)) } pub fn path_segment_to_string(p: &ast::PathSegment) -> String { @@ -1051,7 +1051,7 @@ impl<'a> State<'a> { &f.generic_params)?; } ast::TyKind::Path(None, ref path) => { - self.print_path(path, false, 0, false)?; + self.print_path(path, false, 0)?; } ast::TyKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, false)? @@ -1378,7 +1378,7 @@ impl<'a> State<'a> { self.s.word(";")?; } ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => { - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.print_ident(item.ident)?; self.cbox(INDENT_UNIT)?; @@ -1403,7 +1403,7 @@ impl<'a> State<'a> { } fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> { - self.print_path(&t.path, false, 0, false) + self.print_path(&t.path, false, 0) } fn print_formal_generic_params( @@ -1460,7 +1460,7 @@ impl<'a> State<'a> { ast::CrateSugar::JustCrate => self.word_nbsp("crate") } ast::VisibilityKind::Restricted { ref path, .. } => { - let path = to_string(|s| s.print_path(path, false, 0, true)); + let path = to_string(|s| s.print_path(path, false, 0)); if path == "self" || path == "super" { self.word_nbsp(&format!("pub({})", path)) } else { @@ -1594,7 +1594,7 @@ impl<'a> State<'a> { } ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; @@ -1628,7 +1628,7 @@ impl<'a> State<'a> { } ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; @@ -1814,7 +1814,7 @@ impl<'a> State<'a> { pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) -> io::Result<()> { - self.print_path(&m.node.path, false, 0, false)?; + self.print_path(&m.node.path, false, 0)?; self.s.word("!")?; match delim { token::Paren => self.popen()?, @@ -1915,7 +1915,7 @@ impl<'a> State<'a> { fields: &[ast::Field], wth: &Option>, attrs: &[Attribute]) -> io::Result<()> { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.s.word("{")?; self.print_inner_attributes_inline(attrs)?; self.commasep_cmnt( @@ -2236,7 +2236,7 @@ impl<'a> State<'a> { } } ast::ExprKind::Path(None, ref path) => { - self.print_path(path, true, 0, false)? + self.print_path(path, true, 0)? } ast::ExprKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, true)? @@ -2396,17 +2396,12 @@ impl<'a> State<'a> { fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, - depth: usize, - defaults_to_global: bool) + depth: usize) -> io::Result<()> { self.maybe_print_comment(path.span.lo())?; - let mut segments = path.segments[..path.segments.len()-depth].iter(); - if defaults_to_global && path.is_global() { - segments.next(); - } - for (i, segment) in segments.enumerate() { + for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() { if i > 0 { self.s.word("::")? } @@ -2445,7 +2440,7 @@ impl<'a> State<'a> { self.s.space()?; self.word_space("as")?; let depth = path.segments.len() - qself.position; - self.print_path(path, false, depth, false)?; + self.print_path(path, false, depth)?; } self.s.word(">")?; self.s.word("::")?; @@ -2548,7 +2543,7 @@ impl<'a> State<'a> { } } PatKind::TupleStruct(ref path, ref elts, ddpos) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.popen()?; if let Some(ddpos) = ddpos { self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?; @@ -2566,13 +2561,13 @@ impl<'a> State<'a> { self.pclose()?; } PatKind::Path(None, ref path) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; } PatKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, false)?; } PatKind::Struct(ref path, ref fields, etc) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.nbsp()?; self.word_space("{")?; self.commasep_cmnt( @@ -2950,7 +2945,7 @@ impl<'a> State<'a> { pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> { match tree.kind { ast::UseTreeKind::Simple(rename) => { - self.print_path(&tree.prefix, false, 0, true)?; + self.print_path(&tree.prefix, false, 0)?; if let Some(rename) = rename { self.s.space()?; self.word_space("as")?; @@ -2959,7 +2954,7 @@ impl<'a> State<'a> { } ast::UseTreeKind::Glob => { if !tree.prefix.segments.is_empty() { - self.print_path(&tree.prefix, false, 0, true)?; + self.print_path(&tree.prefix, false, 0)?; self.s.word("::")?; } self.s.word("*")?; @@ -2968,7 +2963,7 @@ impl<'a> State<'a> { if tree.prefix.segments.is_empty() { self.s.word("{")?; } else { - self.print_path(&tree.prefix, false, 0, true)?; + self.print_path(&tree.prefix, false, 0)?; self.s.word("::{")?; } self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 59425929f7e..401183e7c7d 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -79,7 +79,7 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str> vis: respan(span.empty(), ast::VisibilityKind::Inherited), node: ast::ItemKind::Use(P(ast::UseTree { prefix: ast::Path { - segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| { + segments: [name, "prelude", "v1"].into_iter().map(|name| { ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP) }).collect(), span, -- cgit 1.4.1-3-g733a5