Reject _
in ident
matcher
This commit is contained in:
parent
5d06c890fe
commit
ed5ea5c705
4 changed files with 46 additions and 19 deletions
|
@ -86,7 +86,7 @@ use self::TokenTreeOrTokenTreeVec::*;
|
||||||
|
|
||||||
use ast::Ident;
|
use ast::Ident;
|
||||||
use syntax_pos::{self, BytePos, Span};
|
use syntax_pos::{self, BytePos, Span};
|
||||||
use codemap::Spanned;
|
use codemap::respan;
|
||||||
use errors::FatalError;
|
use errors::FatalError;
|
||||||
use ext::tt::quoted::{self, TokenTree};
|
use ext::tt::quoted::{self, TokenTree};
|
||||||
use parse::{Directory, ParseSess};
|
use parse::{Directory, ParseSess};
|
||||||
|
@ -709,6 +709,15 @@ pub fn parse(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The token is an identifier, but not `_`.
|
||||||
|
/// We prohibit passing `_` to macros expecting `ident` for now.
|
||||||
|
fn get_macro_ident(token: &Token) -> Option<Ident> {
|
||||||
|
match *token {
|
||||||
|
token::Ident(ident) if ident.name != keywords::Underscore.name() => Some(ident),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether a non-terminal may begin with a particular token.
|
/// Checks whether a non-terminal may begin with a particular token.
|
||||||
///
|
///
|
||||||
/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
|
/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
|
||||||
|
@ -725,7 +734,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
|
||||||
match name {
|
match name {
|
||||||
"expr" => token.can_begin_expr(),
|
"expr" => token.can_begin_expr(),
|
||||||
"ty" => token.can_begin_type(),
|
"ty" => token.can_begin_type(),
|
||||||
"ident" => token.is_ident(),
|
"ident" => get_macro_ident(token).is_some(),
|
||||||
"vis" => match *token {
|
"vis" => match *token {
|
||||||
// The follow-set of :vis + "priv" keyword + interpolated
|
// The follow-set of :vis + "priv" keyword + interpolated
|
||||||
Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true,
|
Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true,
|
||||||
|
@ -814,21 +823,14 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
|
||||||
"expr" => token::NtExpr(panictry!(p.parse_expr())),
|
"expr" => token::NtExpr(panictry!(p.parse_expr())),
|
||||||
"ty" => token::NtTy(panictry!(p.parse_ty())),
|
"ty" => token::NtTy(panictry!(p.parse_ty())),
|
||||||
// this could be handled like a token, since it is one
|
// this could be handled like a token, since it is one
|
||||||
"ident" => match p.token {
|
"ident" => if let Some(ident) = get_macro_ident(&p.token) {
|
||||||
token::Ident(sn) => {
|
|
||||||
p.bump();
|
p.bump();
|
||||||
token::NtIdent(Spanned::<Ident> {
|
token::NtIdent(respan(p.prev_span, ident))
|
||||||
node: sn,
|
} else {
|
||||||
span: p.prev_span,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let token_str = pprust::token_to_string(&p.token);
|
let token_str = pprust::token_to_string(&p.token);
|
||||||
p.fatal(&format!("expected ident, found {}", &token_str[..]))
|
p.fatal(&format!("expected ident, found {}", &token_str)).emit();
|
||||||
.emit();
|
|
||||||
FatalError.raise()
|
FatalError.raise()
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
|
"path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
|
||||||
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
|
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
|
||||||
"vis" => token::NtVis(panictry!(p.parse_visibility(true))),
|
"vis" => token::NtVis(panictry!(p.parse_visibility(true))),
|
||||||
|
|
|
@ -71,6 +71,4 @@ pub fn main() {
|
||||||
let ident_pat!(x) = 2;
|
let ident_pat!(x) = 2;
|
||||||
x+1
|
x+1
|
||||||
});
|
});
|
||||||
|
|
||||||
let ident_pat!(_) = 2; // OK
|
|
||||||
}
|
}
|
||||||
|
|
19
src/test/ui/underscore-ident-matcher.rs
Normal file
19
src/test/ui/underscore-ident-matcher.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
macro_rules! identity {
|
||||||
|
($i: ident) => (
|
||||||
|
$i
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let identity!(_) = 10; //~ ERROR no rules expected the token `_`
|
||||||
|
}
|
8
src/test/ui/underscore-ident-matcher.stderr
Normal file
8
src/test/ui/underscore-ident-matcher.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
error: no rules expected the token `_`
|
||||||
|
--> $DIR/underscore-ident-matcher.rs:18:19
|
||||||
|
|
|
||||||
|
LL | let identity!(_) = 10; //~ ERROR no rules expected the token `_`
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue