Rollup merge of #33041 - petrochenkov:path, r=nrc,Manishearth

Paths are mostly parsed without taking whitespaces into account, e.g. `std :: vec :: Vec :: new ()` parses successfully, however, there are some special cases involving keywords `super`, `self` and `Self`. For example, `self::` is considered a path start only if there are no spaces between `self` and `::`. These restrictions probably made sense when `self` and friends weren't keywords, but now they are unnecessary.

The first two commits remove this special treatment of whitespaces by removing `token::IdentStyle` entirely and therefore fix https://github.com/rust-lang/rust/issues/14109.
This change also affects naked `self` and `super` (which are not tightly followed by `::`, obviously) they can now be parsed as paths, however they are still not resolved correctly in imports (cc @jseyfried, see `compile-fail/use-keyword.rs`), so https://github.com/rust-lang/rust/issues/29036 is not completely fixed.

The third commit also makes `super`, `self`, `Self` and `static` keywords nominally (before this they acted as keywords for all purposes) and removes most of remaining \"special idents\".

The last commit (before tests) contains some small improvements - some qualified paths with type parameters are parsed correctly, `parse_path` is not used for parsing single identifiers, imports are sanity checked for absence of type parameters - such type parameters can be generated by syntax extensions or by macros when https://github.com/rust-lang/rust/issues/10415 is fixed (~~soon!~~already!).

This patch changes some pretty basic things in `libsyntax`, like `token::Token` and the keyword list, so it's a plugin-[breaking-change].

r? @eddyb
This commit is contained in:
Manish Goregaokar
2016-04-25 00:45:16 +05:30
111 changed files with 807 additions and 867 deletions

View File

@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use self::PathParsingMode::*;
use abi::{self, Abi};
use ast::BareFnTy;
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
@@ -51,7 +49,7 @@ use parse::common::SeqSep;
use parse::lexer::{Reader, TokenAndSpan};
use parse::obsolete::{ParserObsoleteMethods, ObsoleteSyntax};
use parse::token::{self, intern, MatchNt, SubstNt, SpecialVarNt, InternedString};
use parse::token::{keywords, special_idents, SpecialMacroVar};
use parse::token::{keywords, SpecialMacroVar};
use parse::{new_sub_parser_from_file, ParseSess};
use util::parser::{AssocOp, Fixity};
use print::pprust;
@@ -69,26 +67,24 @@ bitflags! {
const RESTRICTION_STMT_EXPR = 1 << 0,
const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
const NO_NONINLINE_MOD = 1 << 2,
const ALLOW_MODULE_PATHS = 1 << 3,
}
}
type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
/// How to parse a path. There are four different kinds of paths, all of which
/// How to parse a path. There are three different kinds of paths, all of which
/// are parsed somewhat differently.
#[derive(Copy, Clone, PartialEq)]
pub enum PathParsingMode {
/// A path with no type parameters; e.g. `foo::bar::Baz`
NoTypesAllowed,
/// Same as `NoTypesAllowed`, but may end with `::{` or `::*`, which are left unparsed
ImportPrefix,
pub enum PathStyle {
/// A path with no type parameters, e.g. `foo::bar::Baz`, used in imports or visibilities.
Mod,
/// A path with a lifetime and type parameters, with no double colons
/// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
LifetimeAndTypesWithoutColons,
/// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`, used in types.
/// Paths using this style can be passed into macros expecting `path` nonterminals.
Type,
/// A path with a lifetime and type parameters with double colons before
/// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
LifetimeAndTypesWithColons,
/// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`, used in expressions or patterns.
Expr,
}
/// How to parse a bound, whether to allow bound modifiers such as `?`.
@@ -292,13 +288,13 @@ impl TokenType {
match *self {
TokenType::Token(ref t) => format!("`{}`", Parser::token_to_string(t)),
TokenType::Operator => "an operator".to_string(),
TokenType::Keyword(kw) => format!("`{}`", kw.to_name()),
TokenType::Keyword(kw) => format!("`{}`", kw.name()),
}
}
}
fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
t.is_plain_ident() || *t == token::Underscore
fn is_ident_or_underscore(t: &token::Token) -> bool {
t.is_ident() || *t == token::Underscore
}
/// Information about the path to a module.
@@ -398,6 +394,17 @@ impl<'a> Parser<'a> {
Parser::token_to_string(&self.token)
}
pub fn this_token_descr(&self) -> String {
let s = self.this_token_to_string();
if self.token.is_strict_keyword() {
format!("keyword `{}`", s)
} else if self.token.is_reserved_keyword() {
format!("reserved keyword `{}`", s)
} else {
format!("`{}`", s)
}
}
pub fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> {
let token_str = Parser::token_to_string(t);
let last_span = self.last_span;
@@ -562,12 +569,10 @@ impl<'a> Parser<'a> {
}
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
if !self.restrictions.contains(Restrictions::ALLOW_MODULE_PATHS) {
self.check_strict_keywords();
}
self.check_strict_keywords();
self.check_reserved_keywords();
match self.token {
token::Ident(i, _) => {
token::Ident(i) => {
self.bump();
Ok(i)
}
@@ -585,12 +590,9 @@ impl<'a> Parser<'a> {
}
}
pub fn parse_ident_or_self_type(&mut self) -> PResult<'a, ast::Ident> {
if self.is_self_type_ident() {
self.expect_self_type_ident()
} else {
self.parse_ident()
}
fn parse_ident_into_path(&mut self) -> PResult<'a, ast::Path> {
let ident = self.parse_ident()?;
Ok(ast::Path::from_ident(self.last_span, ident))
}
/// Check if the next token is `tok`, and return `true` if so.
@@ -637,9 +639,8 @@ impl<'a> Parser<'a> {
}
pub fn check_contextual_keyword(&mut self, ident: Ident) -> bool {
let tok = token::Ident(ident, token::Plain);
self.expected_tokens.push(TokenType::Token(tok));
if let token::Ident(ref cur_ident, _) = self.token {
self.expected_tokens.push(TokenType::Token(token::Ident(ident)));
if let token::Ident(ref cur_ident) = self.token {
cur_ident.name == ident.name
} else {
false
@@ -1159,7 +1160,7 @@ impl<'a> Parser<'a> {
let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
self.parse_ty_param_bounds(BoundParsingMode::Bare)?
} else {
P::empty()
P::new()
};
let all_bounds =
Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
@@ -1170,7 +1171,7 @@ impl<'a> Parser<'a> {
}
pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> {
Ok(TyKind::Path(None, self.parse_path(LifetimeAndTypesWithoutColons)?))
Ok(TyKind::Path(None, self.parse_path(PathStyle::Type)?))
}
/// parse a TyKind::BareFn type:
@@ -1473,13 +1474,11 @@ impl<'a> Parser<'a> {
} else if self.eat_lt() {
let (qself, path) =
self.parse_qualified_path(NoTypesAllowed)?;
self.parse_qualified_path(PathStyle::Type)?;
TyKind::Path(Some(qself), path)
} else if self.check(&token::ModSep) ||
self.token.is_ident() ||
self.token.is_path() {
let path = self.parse_path(LifetimeAndTypesWithoutColons)?;
} else if self.token.is_path_start() {
let path = self.parse_path(PathStyle::Type)?;
if self.check(&token::Not) {
// MACRO INVOCATION
self.bump();
@@ -1497,9 +1496,8 @@ impl<'a> Parser<'a> {
// TYPE TO BE INFERRED
TyKind::Infer
} else {
let this_token_str = self.this_token_to_string();
let msg = format!("expected type, found `{}`", this_token_str);
return Err(self.fatal(&msg[..]));
let msg = format!("expected type, found {}", self.this_token_descr());
return Err(self.fatal(&msg));
};
let sp = mk_sp(lo, self.last_span.hi);
@@ -1541,10 +1539,10 @@ impl<'a> Parser<'a> {
debug!("parser is_named_argument offset:{}", offset);
if offset == 0 {
is_plain_ident_or_underscore(&self.token)
is_ident_or_underscore(&self.token)
&& self.look_ahead(1, |t| *t == token::Colon)
} else {
self.look_ahead(offset, |t| is_plain_ident_or_underscore(t))
self.look_ahead(offset, |t| is_ident_or_underscore(t))
&& self.look_ahead(offset + 1, |t| *t == token::Colon)
}
}
@@ -1564,7 +1562,7 @@ impl<'a> Parser<'a> {
} else {
debug!("parse_arg_general ident_to_pat");
let sp = self.last_span;
let spanned = Spanned { span: sp, node: special_idents::invalid };
let spanned = Spanned { span: sp, node: keywords::Invalid.ident() };
P(Pat {
id: ast::DUMMY_NODE_ID,
node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable),
@@ -1616,12 +1614,12 @@ impl<'a> Parser<'a> {
}
/// Matches token_lit = LIT_INTEGER | ...
pub fn lit_from_token(&self, tok: &token::Token) -> PResult<'a, LitKind> {
match *tok {
pub fn parse_lit_token(&mut self) -> PResult<'a, LitKind> {
let out = match self.token {
token::Interpolated(token::NtExpr(ref v)) => {
match v.node {
ExprKind::Lit(ref lit) => { Ok(lit.node.clone()) }
_ => { return self.unexpected_last(tok); }
ExprKind::Lit(ref lit) => { lit.node.clone() }
_ => { return self.unexpected_last(&self.token); }
}
}
token::Literal(lit, suf) => {
@@ -1636,13 +1634,13 @@ impl<'a> Parser<'a> {
(false, parse::integer_lit(&s.as_str(),
suf.as_ref().map(|s| s.as_str()),
&self.sess.span_diagnostic,
self.last_span))
self.span))
}
token::Float(s) => {
(false, parse::float_lit(&s.as_str(),
suf.as_ref().map(|s| s.as_str()),
&self.sess.span_diagnostic,
self.last_span))
self.span))
}
token::Str_(s) => {
@@ -1664,14 +1662,17 @@ impl<'a> Parser<'a> {
};
if suffix_illegal {
let sp = self.last_span;
let sp = self.span;
self.expect_no_suffix(sp, &format!("{} literal", lit.short_name()), suf)
}
Ok(out)
out
}
_ => { return self.unexpected_last(tok); }
}
_ => { return self.unexpected_last(&self.token); }
};
self.bump();
Ok(out)
}
/// Matches lit = true | false | token_lit
@@ -1682,8 +1683,7 @@ impl<'a> Parser<'a> {
} else if self.eat_keyword(keywords::False) {
LitKind::Bool(false)
} else {
let token = self.bump_and_get();
let lit = self.lit_from_token(&token)?;
let lit = self.parse_lit_token()?;
lit
};
Ok(codemap::Spanned { node: lit, span: mk_sp(lo, self.last_span.hi) })
@@ -1707,6 +1707,16 @@ impl<'a> Parser<'a> {
}
}
pub fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> {
match self.token {
token::Ident(sid) if self.token.is_path_segment_keyword() => {
self.bump();
Ok(sid)
}
_ => self.parse_ident(),
}
}
/// Parses qualified path.
///
/// Assumes that the leading `<` has been parsed already.
@@ -1722,12 +1732,12 @@ impl<'a> Parser<'a> {
///
/// `<T as U>::a`
/// `<T as U>::F::a::<S>`
pub fn parse_qualified_path(&mut self, mode: PathParsingMode)
pub fn parse_qualified_path(&mut self, mode: PathStyle)
-> PResult<'a, (QSelf, ast::Path)> {
let span = self.last_span;
let self_type = self.parse_ty_sum()?;
let mut path = if self.eat_keyword(keywords::As) {
self.parse_path(LifetimeAndTypesWithoutColons)?
self.parse_path(PathStyle::Type)?
} else {
ast::Path {
span: span,
@@ -1745,14 +1755,14 @@ impl<'a> Parser<'a> {
self.expect(&token::ModSep)?;
let segments = match mode {
LifetimeAndTypesWithoutColons => {
PathStyle::Type => {
self.parse_path_segments_without_colons()?
}
LifetimeAndTypesWithColons => {
PathStyle::Expr => {
self.parse_path_segments_with_colons()?
}
NoTypesAllowed | ImportPrefix => {
self.parse_path_segments_without_types(mode == ImportPrefix)?
PathStyle::Mod => {
self.parse_path_segments_without_types()?
}
};
path.segments.extend(segments);
@@ -1766,7 +1776,7 @@ impl<'a> Parser<'a> {
/// mode. The `mode` parameter determines whether lifetimes, types, and/or
/// bounds are permitted and whether `::` must precede type parameter
/// groups.
pub fn parse_path(&mut self, mode: PathParsingMode) -> PResult<'a, ast::Path> {
pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
// Check for a whole path...
let found = match self.token {
token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()),
@@ -1783,14 +1793,14 @@ impl<'a> Parser<'a> {
// identifier followed by an optional lifetime and a set of types.
// A bound set is a set of type parameter bounds.
let segments = match mode {
LifetimeAndTypesWithoutColons => {
PathStyle::Type => {
self.parse_path_segments_without_colons()?
}
LifetimeAndTypesWithColons => {
PathStyle::Expr => {
self.parse_path_segments_with_colons()?
}
NoTypesAllowed | ImportPrefix => {
self.parse_path_segments_without_types(mode == ImportPrefix)?
PathStyle::Mod => {
self.parse_path_segments_without_types()?
}
};
@@ -1813,7 +1823,7 @@ impl<'a> Parser<'a> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
let identifier = self.parse_ident_or_self_type()?;
let identifier = self.parse_path_segment_ident()?;
// Parse types, optionally.
let parameters = if self.eat_lt() {
@@ -1866,7 +1876,7 @@ impl<'a> Parser<'a> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
let identifier = self.parse_ident_or_self_type()?;
let identifier = self.parse_path_segment_ident()?;
// If we do not see a `::`, stop.
if !self.eat(&token::ModSep) {
@@ -1905,15 +1915,14 @@ impl<'a> Parser<'a> {
}
}
/// Examples:
/// - `a::b::c`
pub fn parse_path_segments_without_types(&mut self, import_prefix: bool)
pub fn parse_path_segments_without_types(&mut self)
-> PResult<'a, Vec<ast::PathSegment>> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
let identifier = self.parse_ident_or_self_type()?;
let identifier = self.parse_path_segment_ident()?;
// Assemble and push the result.
segments.push(ast::PathSegment {
@@ -1922,7 +1931,7 @@ impl<'a> Parser<'a> {
});
// If we do not see a `::` or see `::{`/`::*`, stop.
if !self.check(&token::ModSep) || import_prefix && self.is_import_coupler() {
if !self.check(&token::ModSep) || self.is_import_coupler() {
return Ok(segments);
} else {
self.bump();
@@ -2212,15 +2221,6 @@ impl<'a> Parser<'a> {
let lo = self.span.lo;
return self.parse_lambda_expr(lo, CaptureBy::Ref, attrs);
},
token::Ident(id @ ast::Ident {
name: token::SELF_KEYWORD_NAME,
ctxt: _
}, token::Plain) => {
self.bump();
let path = ast::Path::from_ident(mk_sp(lo, hi), id);
ex = ExprKind::Path(None, path);
hi = self.last_span.hi;
}
token::OpenDelim(token::Bracket) => {
self.bump();
@@ -2263,7 +2263,7 @@ impl<'a> Parser<'a> {
_ => {
if self.eat_lt() {
let (qself, path) =
self.parse_qualified_path(LifetimeAndTypesWithColons)?;
self.parse_qualified_path(PathStyle::Expr)?;
hi = path.span.hi;
return Ok(self.mk_expr(lo, hi, ExprKind::Path(Some(qself), path), attrs));
}
@@ -2350,12 +2350,8 @@ impl<'a> Parser<'a> {
let mut db = self.fatal("expected expression, found statement (`let`)");
db.note("variable declaration using `let` is a statement");
return Err(db);
} else if self.check(&token::ModSep) ||
self.token.is_ident() &&
!self.check_keyword(keywords::True) &&
!self.check_keyword(keywords::False) {
let pth =
self.parse_path(LifetimeAndTypesWithColons)?;
} else if self.token.is_path_start() {
let pth = self.parse_path(PathStyle::Expr)?;
// `!`, as an operator, is prefix, so we know this isn't that
if self.check(&token::Not) {
@@ -2435,10 +2431,18 @@ impl<'a> Parser<'a> {
hi = pth.span.hi;
ex = ExprKind::Path(None, pth);
} else {
// other literal expression
let lit = self.parse_lit()?;
hi = lit.span.hi;
ex = ExprKind::Lit(P(lit));
match self.parse_lit() {
Ok(lit) => {
hi = lit.span.hi;
ex = ExprKind::Lit(P(lit));
}
Err(mut err) => {
err.cancel();
let msg = format!("expected expression, found {}",
self.this_token_descr());
return Err(self.fatal(&msg));
}
}
}
}
}
@@ -2577,7 +2581,7 @@ impl<'a> Parser<'a> {
// expr.f
if self.eat(&token::Dot) {
match self.token {
token::Ident(i, _) => {
token::Ident(i) => {
let dot_pos = self.last_span.hi;
hi = self.span.hi;
self.bump();
@@ -2632,7 +2636,7 @@ impl<'a> Parser<'a> {
self.span_err(self.span, &format!("unexpected token: `{}`", actual));
let dot_pos = self.last_span.hi;
e = self.parse_dot_suffix(special_idents::invalid,
e = self.parse_dot_suffix(keywords::Invalid.ident(),
mk_sp(dot_pos, dot_pos),
e, lo)?;
}
@@ -2674,7 +2678,7 @@ impl<'a> Parser<'a> {
// Parse unquoted tokens after a `$` in a token tree
fn parse_unquoted(&mut self) -> PResult<'a, TokenTree> {
let mut sp = self.span;
let (name, namep) = match self.token {
let name = match self.token {
token::Dollar => {
self.bump();
@@ -2694,40 +2698,36 @@ impl<'a> Parser<'a> {
op: repeat,
num_captures: name_num
})));
} else if self.token.is_keyword_allow_following_colon(keywords::Crate) {
} else if self.token.is_keyword(keywords::Crate) {
self.bump();
return Ok(TokenTree::Token(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar)));
} else {
sp = mk_sp(sp.lo, self.span.hi);
let namep = match self.token { token::Ident(_, p) => p, _ => token::Plain };
let name = self.parse_ident()?;
(name, namep)
self.parse_ident()?
}
}
token::SubstNt(name, namep) => {
token::SubstNt(name) => {
self.bump();
(name, namep)
name
}
_ => unreachable!()
};
// continue by trying to parse the `:ident` after `$name`
if self.token == token::Colon && self.look_ahead(1, |t| t.is_ident() &&
!t.is_strict_keyword() &&
!t.is_reserved_keyword()) {
if self.token == token::Colon &&
self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword()) {
self.bump();
sp = mk_sp(sp.lo, self.span.hi);
let kindp = match self.token { token::Ident(_, p) => p, _ => token::Plain };
let nt_kind = self.parse_ident()?;
Ok(TokenTree::Token(sp, MatchNt(name, nt_kind, namep, kindp)))
Ok(TokenTree::Token(sp, MatchNt(name, nt_kind)))
} else {
Ok(TokenTree::Token(sp, SubstNt(name, namep)))
Ok(TokenTree::Token(sp, SubstNt(name)))
}
}
pub fn check_unknown_macro_variable(&mut self) {
if self.quote_depth == 0 {
match self.token {
token::SubstNt(name, _) =>
token::SubstNt(name) =>
self.fatal(&format!("unknown macro variable `{}`", name)).emit(),
_ => {}
}
@@ -3590,16 +3590,16 @@ impl<'a> Parser<'a> {
}
fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
if self.is_path_start() {
if self.token.is_path_start() {
let lo = self.span.lo;
let (qself, path) = if self.eat_lt() {
// Parse a qualified path
let (qself, path) =
self.parse_qualified_path(NoTypesAllowed)?;
self.parse_qualified_path(PathStyle::Expr)?;
(Some(qself), path)
} else {
// Parse an unqualified path
(None, self.parse_path(LifetimeAndTypesWithColons)?)
(None, self.parse_path(PathStyle::Expr)?)
};
let hi = self.last_span.hi;
Ok(self.mk_expr(lo, hi, ExprKind::Path(qself, path), None))
@@ -3608,12 +3608,6 @@ impl<'a> Parser<'a> {
}
}
fn is_path_start(&self) -> bool {
(self.token == token::Lt || self.token == token::ModSep
|| self.token.is_ident() || self.token.is_path())
&& !self.token.is_keyword(keywords::True) && !self.token.is_keyword(keywords::False)
}
/// Parse a pattern.
pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
maybe_whole!(self, NtPat);
@@ -3664,19 +3658,16 @@ impl<'a> Parser<'a> {
// Parse box pat
let subpat = self.parse_pat()?;
pat = PatKind::Box(subpat);
} else if self.is_path_start() {
} else if self.token.is_path_start() {
// Parse pattern starting with a path
if self.token.is_plain_ident() && self.look_ahead(1, |t| *t != token::DotDotDot &&
if self.token.is_ident() && self.look_ahead(1, |t| *t != token::DotDotDot &&
*t != token::OpenDelim(token::Brace) &&
*t != token::OpenDelim(token::Paren) &&
// Contrary to its definition, a plain ident can be followed by :: in macros
*t != token::ModSep) {
// Plain idents have some extra abilities here compared to general paths
if self.look_ahead(1, |t| *t == token::Not) {
// Parse macro invocation
let ident = self.parse_ident()?;
let ident_span = self.last_span;
let path = ast::Path::from_ident(ident_span, ident);
let path = self.parse_ident_into_path()?;
self.bump();
let delim = self.expect_open_delim()?;
let tts = self.parse_seq_to_end(
@@ -3696,11 +3687,11 @@ impl<'a> Parser<'a> {
let (qself, path) = if self.eat_lt() {
// Parse a qualified path
let (qself, path) =
self.parse_qualified_path(NoTypesAllowed)?;
self.parse_qualified_path(PathStyle::Expr)?;
(Some(qself), path)
} else {
// Parse an unqualified path
(None, self.parse_path(LifetimeAndTypesWithColons)?)
(None, self.parse_path(PathStyle::Expr)?)
};
match self.token {
token::DotDotDot => {
@@ -3757,12 +3748,20 @@ impl<'a> Parser<'a> {
}
} else {
// Try to parse everything else as literal with optional minus
let begin = self.parse_pat_literal_maybe_minus()?;
if self.eat(&token::DotDotDot) {
let end = self.parse_pat_range_end()?;
pat = PatKind::Range(begin, end);
} else {
pat = PatKind::Lit(begin);
match self.parse_pat_literal_maybe_minus() {
Ok(begin) => {
if self.eat(&token::DotDotDot) {
let end = self.parse_pat_range_end()?;
pat = PatKind::Range(begin, end);
} else {
pat = PatKind::Lit(begin);
}
}
Err(mut err) => {
err.cancel();
let msg = format!("expected pattern, found {}", self.this_token_descr());
return Err(self.fatal(&msg));
}
}
}
}
@@ -3959,11 +3958,11 @@ impl<'a> Parser<'a> {
// Potential trouble: if we allow macros with paths instead of
// idents, we'd need to look ahead past the whole path here...
let pth = self.parse_path(NoTypesAllowed)?;
let pth = self.parse_ident_into_path()?;
self.bump();
let id = match self.token {
token::OpenDelim(_) => token::special_idents::invalid, // no special identifier
token::OpenDelim(_) => keywords::Invalid.ident(), // no special identifier
_ => self.parse_ident()?,
};
@@ -3975,7 +3974,7 @@ impl<'a> Parser<'a> {
_ => {
// we only expect an ident if we didn't parse one
// above.
let ident_str = if id.name == token::special_idents::invalid.name {
let ident_str = if id.name == keywords::Invalid.name() {
"identifier, "
} else {
""
@@ -4001,7 +4000,7 @@ impl<'a> Parser<'a> {
MacStmtStyle::NoBraces
};
if id.name == token::special_idents::invalid.name {
if id.name == keywords::Invalid.name() {
let mac = P(spanned(lo, hi, Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }));
let stmt = StmtKind::Mac(mac, style, attrs.into_thin_attrs());
spanned(lo, hi, stmt)
@@ -4243,7 +4242,7 @@ impl<'a> Parser<'a> {
-> PResult<'a, TyParamBounds>
{
if !self.eat(&token::Colon) {
Ok(P::empty())
Ok(P::new())
} else {
self.parse_ty_param_bounds(mode)
}
@@ -4629,17 +4628,12 @@ impl<'a> Parser<'a> {
}))
}
fn is_self_ident(&mut self) -> bool {
match self.token {
token::Ident(id, token::Plain) => id.name == special_idents::self_.name,
_ => false
}
}
fn expect_self_ident(&mut self) -> PResult<'a, ast::Ident> {
match self.token {
token::Ident(id, token::Plain) if id.name == special_idents::self_.name => {
token::Ident(id) if id.name == keywords::SelfValue.name() => {
self.bump();
// The hygiene context of `id` needs to be preserved here,
// so we can't just return `SelfValue.ident()`.
Ok(id)
},
_ => {
@@ -4650,27 +4644,6 @@ impl<'a> Parser<'a> {
}
}
fn is_self_type_ident(&mut self) -> bool {
match self.token {
token::Ident(id, token::Plain) => id.name == special_idents::type_self.name,
_ => false
}
}
fn expect_self_type_ident(&mut self) -> PResult<'a, ast::Ident> {
match self.token {
token::Ident(id, token::Plain) if id.name == special_idents::type_self.name => {
self.bump();
Ok(id)
},
_ => {
let token_str = self.this_token_to_string();
Err(self.fatal(&format!("expected `Self`, found `{}`",
token_str)))
}
}
}
/// Parse the argument list and result type of a function
/// that may have a self type.
fn parse_fn_decl_with_self<F>(&mut self,
@@ -4739,16 +4712,16 @@ impl<'a> Parser<'a> {
} else {
Mutability::Immutable
};
if self.is_self_ident() {
if self.token.is_keyword(keywords::SelfValue) {
let span = self.span;
self.span_err(span, "cannot pass self by raw pointer");
self.bump();
}
// error case, making bogus self ident:
SelfKind::Value(special_idents::self_)
SelfKind::Value(keywords::SelfValue.ident())
}
token::Ident(..) => {
if self.is_self_ident() {
if self.token.is_keyword(keywords::SelfValue) {
let self_ident = self.expect_self_ident()?;
// Determine whether this is the fully explicit form, `self:
@@ -4972,7 +4945,7 @@ impl<'a> Parser<'a> {
Visibility::Inherited => (),
_ => {
let is_macro_rules: bool = match self.token {
token::Ident(sid, _) => sid.name == intern("macro_rules"),
token::Ident(sid) => sid.name == intern("macro_rules"),
_ => false,
};
if is_macro_rules {
@@ -5005,7 +4978,7 @@ impl<'a> Parser<'a> {
self.complain_if_pub_macro(&vis, last_span);
let lo = self.span.lo;
let pth = self.parse_path(NoTypesAllowed)?;
let pth = self.parse_ident_into_path()?;
self.expect(&token::Not)?;
// eat a matched-delimiter token tree:
@@ -5020,7 +4993,7 @@ impl<'a> Parser<'a> {
if delim != token::Brace {
self.expect(&token::Semi)?
}
Ok((token::special_idents::invalid, vec![], ast::ImplItemKind::Macro(m)))
Ok((keywords::Invalid.ident(), vec![], ast::ImplItemKind::Macro(m)))
} else {
let (constness, unsafety, abi) = self.parse_fn_front_matter()?;
let ident = self.parse_ident()?;
@@ -5115,7 +5088,7 @@ impl<'a> Parser<'a> {
self.expect(&token::OpenDelim(token::Brace))?;
self.expect(&token::CloseDelim(token::Brace))?;
Ok((special_idents::invalid,
Ok((keywords::Invalid.ident(),
ItemKind::DefaultImpl(unsafety, opt_trait.unwrap()), None))
} else {
if opt_trait.is_some() {
@@ -5131,7 +5104,7 @@ impl<'a> Parser<'a> {
impl_items.push(self.parse_impl_item()?);
}
Ok((special_idents::invalid,
Ok((keywords::Invalid.ident(),
ItemKind::Impl(unsafety, polarity, generics, opt_trait, ty, impl_items),
Some(attrs)))
}
@@ -5140,7 +5113,7 @@ impl<'a> Parser<'a> {
/// Parse a::B<String,i32>
fn parse_trait_ref(&mut self) -> PResult<'a, TraitRef> {
Ok(ast::TraitRef {
path: self.parse_path(LifetimeAndTypesWithoutColons)?,
path: self.parse_path(PathStyle::Type)?,
ref_id: ast::DUMMY_NODE_ID,
})
}
@@ -5300,8 +5273,7 @@ impl<'a> Parser<'a> {
self.expect(&token::CloseDelim(token::Paren))?;
Ok(Visibility::Crate(span))
} else {
let path = self.with_res(Restrictions::ALLOW_MODULE_PATHS,
|this| this.parse_path(NoTypesAllowed))?;
let path = self.parse_path(PathStyle::Mod)?;
self.expect(&token::CloseDelim(token::Paren))?;
Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID })
}
@@ -5309,7 +5281,7 @@ impl<'a> Parser<'a> {
/// Parse defaultness: DEFAULT or nothing
fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> {
if self.eat_contextual_keyword(special_idents::DEFAULT) {
if self.eat_contextual_keyword(keywords::Default.ident()) {
Ok(Defaultness::Default)
} else {
Ok(Defaultness::Final)
@@ -5637,7 +5609,7 @@ impl<'a> Parser<'a> {
};
Ok(self.mk_item(lo,
last_span.hi,
special_idents::invalid,
keywords::Invalid.ident(),
ItemKind::ForeignMod(m),
visibility,
attrs))
@@ -5776,7 +5748,7 @@ impl<'a> Parser<'a> {
let last_span = self.last_span;
let item = self.mk_item(lo,
last_span.hi,
token::special_idents::invalid,
keywords::Invalid.ident(),
item_,
visibility,
attrs);
@@ -6047,7 +6019,7 @@ impl<'a> Parser<'a> {
) -> PResult<'a, Option<P<Item>>> {
if macros_allowed && !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not)
&& (self.look_ahead(2, |t| t.is_plain_ident())
&& (self.look_ahead(2, |t| t.is_ident())
|| self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren))
|| self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) {
// MACRO INVOCATION ITEM
@@ -6058,16 +6030,16 @@ impl<'a> Parser<'a> {
let mac_lo = self.span.lo;
// item macro.
let pth = self.parse_path(NoTypesAllowed)?;
let pth = self.parse_ident_into_path()?;
self.expect(&token::Not)?;
// a 'special' identifier (like what `macro_rules!` uses)
// is optional. We should eventually unify invoc syntax
// and remove this.
let id = if self.token.is_plain_ident() {
let id = if self.token.is_ident() {
self.parse_ident()?
} else {
token::special_idents::invalid // no special identifier
keywords::Invalid.ident() // no special identifier
};
// eat a matched-delimiter token tree:
let delim = self.expect_open_delim()?;
@@ -6164,7 +6136,7 @@ impl<'a> Parser<'a> {
let items = self.parse_path_list_items()?;
Ok(P(spanned(lo, self.span.hi, ViewPathList(prefix, items))))
} else {
let prefix = self.parse_path(ImportPrefix)?;
let prefix = self.parse_path(PathStyle::Mod)?;
if self.is_import_coupler() {
// `foo::bar::{a, b}` or `foo::bar::*`
self.bump();