Rollup merge of #70058 - Centril:fix-70050, r=petrochenkov
can_begin_literal_maybe_minus: `true` on `"-"? lit` NTs. Make `can_begin_literal_or_bool` (renamed to `can_begin_literal_maybe_minus`) accept `NtLiteral(e) | NtExpr(e)` where `e` is either a literal or a negated literal. Fixes https://github.com/rust-lang/rust/issues/70050. r? @petrochenkov
This commit is contained in:
commit
67e418ce75
@ -424,7 +424,7 @@ impl Token {
|
||||
NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
_ => self.can_begin_literal_or_bool(),
|
||||
_ => self.can_begin_literal_maybe_minus(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,13 +448,22 @@ impl Token {
|
||||
/// Returns `true` if the token is any literal, a minus (which can prefix a literal,
|
||||
/// for example a '-42', or one of the boolean idents).
|
||||
///
|
||||
/// Keep this in sync with `Lit::from_token`.
|
||||
pub fn can_begin_literal_or_bool(&self) -> bool {
|
||||
/// In other words, would this token be a valid start of `parse_literal_maybe_minus`?
|
||||
///
|
||||
/// Keep this in sync with and `Lit::from_token`, excluding unary negation.
|
||||
pub fn can_begin_literal_maybe_minus(&self) -> bool {
|
||||
match self.uninterpolate().kind {
|
||||
Literal(..) | BinOp(Minus) => true,
|
||||
Ident(name, false) if name.is_bool_lit() => true,
|
||||
Interpolated(ref nt) => match &**nt {
|
||||
NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)),
|
||||
NtLiteral(_) => true,
|
||||
NtExpr(e) => match &e.kind {
|
||||
ast::ExprKind::Lit(_) => true,
|
||||
ast::ExprKind::Unary(ast::UnOp::Neg, e) => {
|
||||
matches!(&e.kind, ast::ExprKind::Lit(_))
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
|
@ -189,7 +189,7 @@ impl Lit {
|
||||
|
||||
/// Converts arbitrary token into an AST literal.
|
||||
///
|
||||
/// Keep this in sync with `Token::can_begin_literal_or_bool`.
|
||||
/// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation.
|
||||
pub fn from_token(token: &Token) -> Result<Lit, LitError> {
|
||||
let lit = match token.uninterpolate().kind {
|
||||
token::Ident(name, false) if name.is_bool_lit() => {
|
||||
|
@ -778,7 +778,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
|
||||
}
|
||||
sym::ty => token.can_begin_type(),
|
||||
sym::ident => get_macro_ident(token).is_some(),
|
||||
sym::literal => token.can_begin_literal_or_bool(),
|
||||
sym::literal => token.can_begin_literal_maybe_minus(),
|
||||
sym::vis => match token.kind {
|
||||
// The follow-set of :vis + "priv" keyword + interpolated
|
||||
token::Comma | token::Ident(..) | token::Interpolated(_) => true,
|
||||
|
@ -1374,6 +1374,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
|
||||
/// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
|
||||
pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
|
||||
maybe_whole_expr!(self);
|
||||
|
||||
|
@ -1509,7 +1509,7 @@ impl<'a> Parser<'a> {
|
||||
})
|
||||
// `extern ABI fn`
|
||||
|| self.check_keyword(kw::Extern)
|
||||
&& self.look_ahead(1, |t| t.can_begin_literal_or_bool())
|
||||
&& self.look_ahead(1, |t| t.can_begin_literal_maybe_minus())
|
||||
&& self.look_ahead(2, |t| t.is_keyword(kw::Fn))
|
||||
}
|
||||
|
||||
|
@ -696,7 +696,7 @@ impl<'a> Parser<'a> {
|
||||
self.look_ahead(dist, |t| {
|
||||
t.is_path_start() // e.g. `MY_CONST`;
|
||||
|| t.kind == token::Dot // e.g. `.5` for recovery;
|
||||
|| t.can_begin_literal_or_bool() // e.g. `42`.
|
||||
|| t.can_begin_literal_maybe_minus() // e.g. `42`.
|
||||
|| t.is_whole_expr()
|
||||
})
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// check-pass
|
||||
|
||||
// In this test we check that the parser accepts an ABI string when it
|
||||
// comes from a macro `literal` fragment as opposed to a hardcoded string.
|
||||
// comes from a macro `literal` or `expr` fragment as opposed to a hardcoded string.
|
||||
|
||||
fn main() {}
|
||||
|
||||
@ -17,6 +17,18 @@ macro_rules! abi_from_lit_frag {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! abi_from_expr_frag {
|
||||
($abi:expr) => {
|
||||
extern $abi {
|
||||
fn _import();
|
||||
}
|
||||
|
||||
extern $abi fn _export() {}
|
||||
|
||||
type _PTR = extern $abi fn();
|
||||
};
|
||||
}
|
||||
|
||||
mod rust {
|
||||
abi_from_lit_frag!("Rust");
|
||||
}
|
||||
@ -24,3 +36,11 @@ mod rust {
|
||||
mod c {
|
||||
abi_from_lit_frag!("C");
|
||||
}
|
||||
|
||||
mod rust_expr {
|
||||
abi_from_expr_frag!("Rust");
|
||||
}
|
||||
|
||||
mod c_expr {
|
||||
abi_from_expr_frag!("C");
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
// check-pass
|
||||
|
||||
macro_rules! foo {
|
||||
($a:literal) => {
|
||||
bar!($a)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! bar {
|
||||
($b:literal) => {};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo!(-2);
|
||||
bar!(-2);
|
||||
}
|
Loading…
Reference in New Issue
Block a user