syntax: Make _
an identifier
This commit is contained in:
parent
61b6bf54fd
commit
5d06c890fe
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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 => {}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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")),
|
||||
|
@ -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(_) => {
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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()))
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 `_`
|
||||
}
|
||||
|
@ -39,5 +39,5 @@ fn main() {
|
||||
}
|
||||
}
|
||||
// still recover later
|
||||
let bad_syntax = _; //~ ERROR: found `_`
|
||||
let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -71,4 +71,6 @@ pub fn main() {
|
||||
let ident_pat!(x) = 2;
|
||||
x+1
|
||||
});
|
||||
|
||||
let ident_pat!(_) = 2; // OK
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: expected expression, found `_`
|
||||
error: expected expression, found reserved identifier `_`
|
||||
--> $DIR/underscore.rs:18:9
|
||||
|
|
||||
LL | _
|
||||
|
Loading…
Reference in New Issue
Block a user