syntax: Make _ an identifier

This commit is contained in:
Vadim Petrochenkov 2018-03-08 14:27:23 +03:00
parent 61b6bf54fd
commit 5d06c890fe
20 changed files with 109 additions and 119 deletions

View File

@ -680,7 +680,6 @@ impl TokenTree {
Pound => op!('#'),
Dollar => op!('$'),
Question => op!('?'),
Underscore => op!('_'),
Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)),
Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)),
@ -743,7 +742,6 @@ impl TokenTree {
'#' => Pound,
'$' => Dollar,
'?' => Question,
'_' => Underscore,
_ => panic!("unsupported character {}", op),
};

View File

@ -214,7 +214,7 @@ impl LifetimeName {
use self::LifetimeName::*;
match *self {
Implicit => keywords::Invalid.name(),
Underscore => Symbol::intern("'_"),
Underscore => keywords::UnderscoreLifetime.name(),
Static => keywords::StaticLifetime.name(),
Name(name) => name,
}

View File

@ -287,7 +287,6 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
token::Token::Pound |
token::Token::Dollar |
token::Token::Question |
token::Token::Underscore |
token::Token::Whitespace |
token::Token::Comment |
token::Token::Eof => {}

View File

@ -37,7 +37,9 @@ impl<'a> AstValidator<'a> {
}
fn check_lifetime(&self, lifetime: &Lifetime) {
let valid_names = [keywords::StaticLifetime.name(), keywords::Invalid.name()];
let valid_names = [keywords::UnderscoreLifetime.name(),
keywords::StaticLifetime.name(),
keywords::Invalid.name()];
if !valid_names.contains(&lifetime.ident.name) &&
token::Ident(lifetime.ident.without_first_quote()).is_reserved_ident() {
self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names");
@ -45,7 +47,7 @@ impl<'a> AstValidator<'a> {
}
fn check_label(&self, label: Ident, span: Span) {
if token::Ident(label.without_first_quote()).is_reserved_ident() || label.name == "'_" {
if token::Ident(label.without_first_quote()).is_reserved_ident() {
self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
}
}

View File

@ -352,7 +352,7 @@ impl<'a> Classifier<'a> {
token::Lifetime(..) => Class::Lifetime,
token::Underscore | token::Eof | token::Interpolated(..) |
token::Eof | token::Interpolated(..) |
token::Tilde | token::At | token::DotEq => Class::None,
};

View File

@ -19,7 +19,7 @@ use ext::base::{ExtCtxt, MacEager, MacResult};
use ext::build::AstBuilder;
use parse::token;
use ptr::P;
use symbol::Symbol;
use symbol::{keywords, Symbol};
use tokenstream::{TokenTree};
use util::small_vector::SmallVector;
@ -192,7 +192,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
(descriptions.len(), ecx.expr_vec(span, descriptions))
});
let static_ = ecx.lifetime(span, Ident::from_str("'static"));
let static_ = ecx.lifetime(span, keywords::StaticLifetime.ident());
let ty_str = ecx.ty_rptr(
span,
ecx.ty_ident(span, ecx.ident_of("str")),

View File

@ -709,7 +709,6 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
token::Pound => "Pound",
token::Dollar => "Dollar",
token::Question => "Question",
token::Underscore => "Underscore",
token::Eof => "Eof",
token::Whitespace | token::Comment | token::Shebang(_) => {

View File

@ -765,8 +765,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
Token::DotDotDot | // range pattern (future compat)
Token::ModSep | // path
Token::Lt | // path (UFCS constant)
Token::BinOp(token::Shl) | // path (double UFCS)
Token::Underscore => true, // placeholder
Token::BinOp(token::Shl) => true, // path (double UFCS)
Token::Interpolated(ref nt) => may_be_ident(&nt.0),
_ => false,
},

View File

@ -1790,7 +1790,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
if lt.ident.name == "'_" {
if lt.ident.name == keywords::UnderscoreLifetime.name() {
gate_feature_post!(&self, underscore_lifetimes, lt.span,
"underscore lifetimes are unstable");
}

View File

@ -34,7 +34,7 @@ pub struct TokenAndSpan {
impl Default for TokenAndSpan {
fn default() -> Self {
TokenAndSpan { tok: token::Underscore, sp: syntax_pos::DUMMY_SP }
TokenAndSpan { tok: token::Whitespace, sp: syntax_pos::DUMMY_SP }
}
}
@ -126,7 +126,7 @@ impl<'a> StringReader<'a> {
pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
assert!(self.fatal_errs.is_empty());
let ret_val = TokenAndSpan {
tok: replace(&mut self.peek_tok, token::Underscore),
tok: replace(&mut self.peek_tok, token::Whitespace),
sp: self.peek_span,
};
self.advance_token()?;
@ -1133,14 +1133,8 @@ impl<'a> StringReader<'a> {
self.bump();
}
return Ok(self.with_str_from(start, |string| {
if string == "_" {
token::Underscore
} else {
// FIXME: perform NFKC normalization here. (Issue #2253)
token::Ident(self.mk_ident(string))
}
}));
// FIXME: perform NFKC normalization here. (Issue #2253)
return Ok(self.with_str_from(start, |string| token::Ident(self.mk_ident(string))));
}
if is_dec_digit(c) {

View File

@ -549,7 +549,7 @@ impl<'a> Parser<'a> {
-> Self {
let mut parser = Parser {
sess,
token: token::Underscore,
token: token::Whitespace,
span: syntax_pos::DUMMY_SP,
prev_span: syntax_pos::DUMMY_SP,
meta_var_span: None,
@ -800,11 +800,7 @@ impl<'a> Parser<'a> {
Err(if self.prev_token_kind == PrevTokenKind::DocComment {
self.span_fatal_err(self.prev_span, Error::UselessDocComment)
} else {
let mut err = self.expected_ident_found();
if self.token == token::Underscore {
err.note("`_` is a wildcard pattern, not an identifier");
}
err
self.expected_ident_found()
})
}
}
@ -1602,7 +1598,7 @@ impl<'a> Parser<'a> {
let e = self.parse_expr()?;
self.expect(&token::CloseDelim(token::Paren))?;
TyKind::Typeof(e)
} else if self.eat(&token::Underscore) {
} else if self.eat_keyword(keywords::Underscore) {
// A type to be inferred `_`
TyKind::Infer
} else if self.token_is_bare_fn_keyword() {
@ -1796,7 +1792,7 @@ impl<'a> Parser<'a> {
_ => 0,
};
self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) &&
self.look_ahead(offset, |t| t.is_ident()) &&
self.look_ahead(offset + 1, |t| t == &token::Colon)
}
@ -2782,7 +2778,7 @@ impl<'a> Parser<'a> {
},
token::CloseDelim(_) | token::Eof => unreachable!(),
_ => {
let (token, span) = (mem::replace(&mut self.token, token::Underscore), self.span);
let (token, span) = (mem::replace(&mut self.token, token::Whitespace), self.span);
self.bump();
TokenTree::Token(span, token)
}
@ -3815,11 +3811,6 @@ impl<'a> Parser<'a> {
let lo = self.span;
let pat;
match self.token {
token::Underscore => {
// Parse _
self.bump();
pat = PatKind::Wild;
}
token::BinOp(token::And) | token::AndAnd => {
// Parse &pat / &mut pat
self.expect_and()?;
@ -3849,8 +3840,11 @@ impl<'a> Parser<'a> {
self.expect(&token::CloseDelim(token::Bracket))?;
pat = PatKind::Slice(before, slice, after);
}
// At this point, token != _, &, &&, (, [
_ => if self.eat_keyword(keywords::Mut) {
// At this point, token != &, &&, (, [
_ => if self.eat_keyword(keywords::Underscore) {
// Parse _
pat = PatKind::Wild;
} else if self.eat_keyword(keywords::Mut) {
// Parse mut ident @ pat / mut ref ident @ pat
let mutref_span = self.prev_span.to(self.span);
let binding_mode = if self.eat_keyword(keywords::Ref) {
@ -7065,10 +7059,12 @@ impl<'a> Parser<'a> {
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
if self.eat_keyword(keywords::As) {
if self.eat(&token::Underscore) {
Ok(Some(Ident::with_empty_ctxt(Symbol::gensym("_"))))
} else {
self.parse_ident().map(Some)
match self.token {
token::Ident(ident) if ident.name == keywords::Underscore.name() => {
self.bump(); // `_`
Ok(Some(Ident { name: ident.name.gensymed(), ..ident }))
}
_ => self.parse_ident().map(Some),
}
} else {
Ok(None)

View File

@ -122,6 +122,7 @@ fn ident_can_begin_type(ident: ast::Ident) -> bool {
!ident_token.is_reserved_ident() ||
ident_token.is_path_segment_keyword() ||
[
keywords::Underscore.name(),
keywords::For.name(),
keywords::Impl.name(),
keywords::Fn.name(),
@ -175,7 +176,6 @@ pub enum Token {
/* Name components */
Ident(ast::Ident),
Underscore,
Lifetime(ast::Ident),
// The `LazyTokenStream` is a pure function of the `Nonterminal`,
@ -242,7 +242,6 @@ impl Token {
Ident(ident) => ident_can_begin_type(ident), // type name or keyword
OpenDelim(Paren) | // tuple
OpenDelim(Bracket) | // array
Underscore | // placeholder
Not | // never
BinOp(Star) | // raw pointer
BinOp(And) | // reference
@ -371,7 +370,7 @@ impl Token {
// unnamed method parameters, crate root module, error recovery etc.
pub fn is_special_ident(&self) -> bool {
match self.ident() {
Some(id) => id.name <= keywords::DollarCrate.name(),
Some(id) => id.name <= keywords::Underscore.name(),
_ => false,
}
}
@ -441,7 +440,7 @@ impl Token {
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq |
DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None,
Question | OpenDelim(..) | CloseDelim(..) => return None,
Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
Whitespace | Comment | Shebang(..) | Eof => return None,
@ -573,7 +572,7 @@ impl fmt::Debug for Nonterminal {
pub fn is_op(tok: &Token) -> bool {
match *tok {
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) |
Ident(..) | Underscore | Lifetime(..) | Interpolated(..) |
Ident(..) | Lifetime(..) | Interpolated(..) |
Whitespace | Comment | Shebang(..) | Eof => false,
_ => true,
}

View File

@ -252,7 +252,6 @@ pub fn token_to_string(tok: &Token) -> String {
/* Name components */
token::Ident(s) => s.to_string(),
token::Lifetime(s) => s.to_string(),
token::Underscore => "_".to_string(),
/* Other */
token::DocComment(s) => s.to_string(),

View File

@ -17,7 +17,7 @@ use syntax::ast::{self, Ident};
use syntax::ext::base::*;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
use syntax::symbol::Symbol;
use syntax::symbol::{keywords, Symbol};
use syntax_pos::Span;
use syntax::tokenstream;
@ -35,14 +35,14 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
let e = match env::var(&*var.as_str()) {
Err(..) => {
let lt = cx.lifetime(sp, keywords::StaticLifetime.ident());
cx.expr_path(cx.path_all(sp,
true,
cx.std_path(&["option", "Option", "None"]),
Vec::new(),
vec![cx.ty_rptr(sp,
cx.ty_ident(sp, Ident::from_str("str")),
Some(cx.lifetime(sp,
Ident::from_str("'static"))),
Some(lt),
ast::Mutability::Immutable)],
Vec::new()))
}

View File

@ -261,73 +261,77 @@ macro_rules! declare_keywords {(
declare_keywords! {
// Special reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
(0, Invalid, "")
(1, CrateRoot, "{{root}}")
(2, DollarCrate, "$crate")
(0, Invalid, "")
(1, CrateRoot, "{{root}}")
(2, DollarCrate, "$crate")
(3, Underscore, "_")
// Keywords used in the language.
(3, As, "as")
(4, Box, "box")
(5, Break, "break")
(6, Const, "const")
(7, Continue, "continue")
(8, Crate, "crate")
(9, Else, "else")
(10, Enum, "enum")
(11, Extern, "extern")
(12, False, "false")
(13, Fn, "fn")
(14, For, "for")
(15, If, "if")
(16, Impl, "impl")
(17, In, "in")
(18, Let, "let")
(19, Loop, "loop")
(20, Match, "match")
(21, Mod, "mod")
(22, Move, "move")
(23, Mut, "mut")
(24, Pub, "pub")
(25, Ref, "ref")
(26, Return, "return")
(27, SelfValue, "self")
(28, SelfType, "Self")
(29, Static, "static")
(30, Struct, "struct")
(31, Super, "super")
(32, Trait, "trait")
(33, True, "true")
(34, Type, "type")
(35, Unsafe, "unsafe")
(36, Use, "use")
(37, Where, "where")
(38, While, "while")
(4, As, "as")
(5, Box, "box")
(6, Break, "break")
(7, Const, "const")
(8, Continue, "continue")
(9, Crate, "crate")
(10, Else, "else")
(11, Enum, "enum")
(12, Extern, "extern")
(13, False, "false")
(14, Fn, "fn")
(15, For, "for")
(16, If, "if")
(17, Impl, "impl")
(18, In, "in")
(19, Let, "let")
(20, Loop, "loop")
(21, Match, "match")
(22, Mod, "mod")
(23, Move, "move")
(24, Mut, "mut")
(25, Pub, "pub")
(26, Ref, "ref")
(27, Return, "return")
(28, SelfValue, "self")
(29, SelfType, "Self")
(30, Static, "static")
(31, Struct, "struct")
(32, Super, "super")
(33, Trait, "trait")
(34, True, "true")
(35, Type, "type")
(36, Unsafe, "unsafe")
(37, Use, "use")
(38, Where, "where")
(39, While, "while")
// Keywords reserved for future use.
(39, Abstract, "abstract")
(40, Alignof, "alignof")
(41, Become, "become")
(42, Do, "do")
(43, Final, "final")
(44, Macro, "macro")
(45, Offsetof, "offsetof")
(46, Override, "override")
(47, Priv, "priv")
(48, Proc, "proc")
(49, Pure, "pure")
(50, Sizeof, "sizeof")
(51, Typeof, "typeof")
(52, Unsized, "unsized")
(53, Virtual, "virtual")
(54, Yield, "yield")
(40, Abstract, "abstract")
(41, Alignof, "alignof")
(42, Become, "become")
(43, Do, "do")
(44, Final, "final")
(45, Macro, "macro")
(46, Offsetof, "offsetof")
(47, Override, "override")
(48, Priv, "priv")
(49, Proc, "proc")
(50, Pure, "pure")
(51, Sizeof, "sizeof")
(52, Typeof, "typeof")
(53, Unsized, "unsized")
(54, Virtual, "virtual")
(55, Yield, "yield")
// Special lifetime names
(56, UnderscoreLifetime, "'_")
(57, StaticLifetime, "'static")
// Weak keywords, have special meaning only in specific contexts.
(55, Auto, "auto")
(56, Catch, "catch")
(57, Default, "default")
(58, Dyn, "dyn")
(59, StaticLifetime, "'static")
(60, Union, "union")
(58, Auto, "auto")
(59, Catch, "catch")
(60, Default, "default")
(61, Dyn, "dyn")
(62, Union, "union")
}
// If an interner exists, return it. Otherwise, prepare a fresh one.

View File

@ -16,7 +16,5 @@ fn main() {
let _ = 0;
let mut b = 0;
let mut _b = 0;
let mut _ = 0; //~ ERROR expected identifier, found `_`
//~^ NOTE `_` is a wildcard pattern, not an identifier
//~| NOTE expected identifier
let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_`
}

View File

@ -39,5 +39,5 @@ fn main() {
}
}
// still recover later
let bad_syntax = _; //~ ERROR: found `_`
let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`
}

View File

@ -9,5 +9,6 @@
// except according to those terms.
fn main() {
let a = 42._; //~ ERROR unexpected token: `_`
let a = 42._; //~ ERROR expected identifier, found reserved identifier `_`
//~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields
}

View File

@ -71,4 +71,6 @@ pub fn main() {
let ident_pat!(x) = 2;
x+1
});
let ident_pat!(_) = 2; // OK
}

View File

@ -1,4 +1,4 @@
error: expected expression, found `_`
error: expected expression, found reserved identifier `_`
--> $DIR/underscore.rs:18:9
|
LL | _