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
-2
View File
@@ -680,7 +680,6 @@ fn joint(first: char, rest: Token, is_joint: bool, span: &mut syntax_pos::Span,
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 @@ fn to_internal(self) -> tokenstream::TokenStream {
'#' => Pound,
'$' => Dollar,
'?' => Question,
'_' => Underscore,
_ => panic!("unsupported character {}", op),
};
+1 -1
View File
@@ -214,7 +214,7 @@ pub fn name(&self) -> Name {
use self::LifetimeName::*;
match *self {
Implicit => keywords::Invalid.name(),
Underscore => Symbol::intern("'_"),
Underscore => keywords::UnderscoreLifetime.name(),
Static => keywords::StaticLifetime.name(),
Name(name) => name,
}
-1
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 => {}
+4 -2
View File
@@ -37,7 +37,9 @@ fn err_handler(&self) -> &errors::Handler {
}
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 @@ fn check_lifetime(&self, lifetime: &Lifetime) {
}
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));
}
}
+1 -1
View File
@@ -352,7 +352,7 @@ fn write_token<W: Writer>(&mut self,
token::Lifetime(..) => Class::Lifetime,
token::Underscore | token::Eof | token::Interpolated(..) |
token::Eof | token::Interpolated(..) |
token::Tilde | token::At | token::DotEq => Class::None,
};
+2 -2
View File
@@ -19,7 +19,7 @@
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")),
-1
View File
@@ -709,7 +709,6 @@ macro_rules! mk_lit {
token::Pound => "Pound",
token::Dollar => "Dollar",
token::Question => "Question",
token::Underscore => "Underscore",
token::Eof => "Eof",
token::Whitespace | token::Comment | token::Shebang(_) => {
+1 -2
View File
@@ -765,8 +765,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> 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,
},
+1 -1
View File
@@ -1790,7 +1790,7 @@ fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
}
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");
}
+4 -10
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 @@ fn is_eof(&self) -> bool {
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 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
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) {
+16 -20
View File
@@ -549,7 +549,7 @@ pub fn new(sess: &'a ParseSess,
-> 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 @@ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
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 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
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 @@ fn is_named_argument(&mut self) -> bool {
_ => 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 @@ pub fn parse_token_tree(&mut self) -> TokenTree {
},
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 @@ fn parse_pat_with_range_pat(&mut self, allow_range_pat: bool) -> PResult<'a, P<P
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 @@ fn parse_pat_with_range_pat(&mut self, allow_range_pat: bool) -> PResult<'a, P<P
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 @@ fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
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)
+4 -5
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 @@ pub fn can_begin_type(&self) -> bool {
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 @@ pub fn is_path_segment_keyword(&self) -> bool {
// 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 @@ pub fn glue(self, joint: Token) -> Option<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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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,
}
-1
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(),
+3 -3
View File
@@ -17,7 +17,7 @@
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()))
}
+65 -61
View File
@@ -261,73 +261,77 @@ pub fn fresh() -> Self {
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.
+1 -3
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 `_`
}
+1 -1
View File
@@ -39,5 +39,5 @@ enum Test4 {
}
}
// 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
}
+2
View File
@@ -71,4 +71,6 @@ pub fn main() {
let ident_pat!(x) = 2;
x+1
});
let ident_pat!(_) = 2; // OK
}
+1 -1
View File
@@ -1,4 +1,4 @@
error: expected expression, found `_`
error: expected expression, found reserved identifier `_`
--> $DIR/underscore.rs:18:9
|
LL | _