diff options
| author | bors <bors@rust-lang.org> | 2017-11-21 12:32:59 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-11-21 12:32:59 +0000 |
| commit | f28df200260c89b2a0bdf942510e0f888c29a70d (patch) | |
| tree | 731a918787dcc36a4ce994d5a79626d59b61ee13 /src/libsyntax | |
| parent | ebda7662dbb79ab0a9feb79d367d0818c23ff1dc (diff) | |
| parent | 90f5cfdfbd3c9e39f897fd2271c7b1c7fdaae58e (diff) | |
| download | rust-f28df200260c89b2a0bdf942510e0f888c29a70d.tar.gz rust-f28df200260c89b2a0bdf942510e0f888c29a70d.zip | |
Auto merge of #45771 - petrochenkov:crate, r=nikomatsakis
Support `::crate` in paths cc https://github.com/rust-lang/rust/issues/45477 Fixes https://github.com/rust-lang/rust/issues/45229
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 17 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 1 |
4 files changed, 38 insertions, 7 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 99dff4edaad..ad9d5865120 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -96,10 +96,15 @@ 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() && - !::parse::token::Ident(self.segments[0].identifier).is_path_segment_keyword() { - self.segments.insert(0, PathSegment::crate_root(self.span)); + 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)); + } } self } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 5c7450baa2f..036c9414990 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -33,7 +33,7 @@ use syntax_pos::Span; use errors::{DiagnosticBuilder, Handler, FatalError}; use visit::{self, FnKind, Visitor}; use parse::ParseSess; -use symbol::Symbol; +use symbol::{keywords, Symbol}; use std::env; @@ -420,6 +420,9 @@ declare_features! ( // #![wasm_import_memory] attribute (active, wasm_import_memory, "1.22.0", None), + + // `crate` in paths + (active, crate_in_paths, "1.23.0", Some(45477)), ); declare_features! ( @@ -1634,6 +1637,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_impl_item(self, ii); } + fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) { + for segment in &path.segments { + if segment.identifier.name == keywords::Crate.name() { + gate_feature_post!(&self, crate_in_paths, segment.span, + "`crate` in paths is experimental"); + } + } + + visit::walk_path(self, path); + } + fn visit_vis(&mut self, vis: &'a ast::Visibility) { if let ast::Visibility::Crate(span, ast::CrateSugar::JustCrate) = *vis { gate_feature_post!(&self, crate_visibility_modifier, span, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c1819307928..0b03429ea2e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3916,6 +3916,10 @@ impl<'a> Parser<'a> { self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) } + fn is_crate_vis(&self) -> bool { + self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep) + } + fn eat_auto_trait(&mut self) -> bool { if self.token.is_keyword(keywords::Auto) && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) @@ -4026,10 +4030,15 @@ impl<'a> Parser<'a> { node: StmtKind::Item(macro_def), span: lo.to(self.prev_span), } - // Starts like a simple path, but not a union item. + // Starts like a simple path, but not a union item or item with `crate` visibility. + // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts + // like a path (1 token), but it fact not a path. + // `union::b::c` - path, `union U { ... }` - not a path. + // `crate::b::c` - path, `crate struct S;` - not a path. } else if self.token.is_path_start() && !self.token.is_qpath_start() && - !self.is_union_item() { + !self.is_union_item() && + !self.is_crate_vis() { let pth = self.parse_path(PathStyle::Expr)?; if !self.eat(&token::Not) { @@ -5399,7 +5408,9 @@ impl<'a> Parser<'a> { pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { maybe_whole!(self, NtVis, |x| x); - if self.eat_keyword(keywords::Crate) { + self.expected_tokens.push(TokenType::Keyword(keywords::Crate)); + if self.is_crate_vis() { + self.bump(); // `crate` return Ok(Visibility::Crate(self.prev_span, CrateSugar::JustCrate)); } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index f83343bf9af..ff87f146c0a 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -347,6 +347,7 @@ impl Token { Some(id) => id.name == keywords::Super.name() || id.name == keywords::SelfValue.name() || id.name == keywords::SelfType.name() || + id.name == keywords::Crate.name() || id.name == keywords::DollarCrate.name(), None => false, } |
