Skip to content

Commit 67e418c

Browse files
authored
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 #70050. r? @petrochenkov
2 parents 45b10f6 + 9b9a22c commit 67e418c

File tree

8 files changed

+55
-9
lines changed

8 files changed

+55
-9
lines changed

src/librustc_ast/token.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ impl Token {
424424
NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
425425
_ => false,
426426
},
427-
_ => self.can_begin_literal_or_bool(),
427+
_ => self.can_begin_literal_maybe_minus(),
428428
}
429429
}
430430

@@ -448,13 +448,22 @@ impl Token {
448448
/// Returns `true` if the token is any literal, a minus (which can prefix a literal,
449449
/// for example a '-42', or one of the boolean idents).
450450
///
451-
/// Keep this in sync with `Lit::from_token`.
452-
pub fn can_begin_literal_or_bool(&self) -> bool {
451+
/// In other words, would this token be a valid start of `parse_literal_maybe_minus`?
452+
///
453+
/// Keep this in sync with and `Lit::from_token`, excluding unary negation.
454+
pub fn can_begin_literal_maybe_minus(&self) -> bool {
453455
match self.uninterpolate().kind {
454456
Literal(..) | BinOp(Minus) => true,
455457
Ident(name, false) if name.is_bool_lit() => true,
456458
Interpolated(ref nt) => match &**nt {
457-
NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)),
459+
NtLiteral(_) => true,
460+
NtExpr(e) => match &e.kind {
461+
ast::ExprKind::Lit(_) => true,
462+
ast::ExprKind::Unary(ast::UnOp::Neg, e) => {
463+
matches!(&e.kind, ast::ExprKind::Lit(_))
464+
}
465+
_ => false,
466+
},
458467
_ => false,
459468
},
460469
_ => false,

src/librustc_ast/util/literal.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ impl Lit {
189189

190190
/// Converts arbitrary token into an AST literal.
191191
///
192-
/// Keep this in sync with `Token::can_begin_literal_or_bool`.
192+
/// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation.
193193
pub fn from_token(token: &Token) -> Result<Lit, LitError> {
194194
let lit = match token.uninterpolate().kind {
195195
token::Ident(name, false) if name.is_bool_lit() => {

src/librustc_expand/mbe/macro_parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
778778
}
779779
sym::ty => token.can_begin_type(),
780780
sym::ident => get_macro_ident(token).is_some(),
781-
sym::literal => token.can_begin_literal_or_bool(),
781+
sym::literal => token.can_begin_literal_maybe_minus(),
782782
sym::vis => match token.kind {
783783
// The follow-set of :vis + "priv" keyword + interpolated
784784
token::Comma | token::Ident(..) | token::Interpolated(_) => true,

src/librustc_parse/parser/expr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,7 @@ impl<'a> Parser<'a> {
13741374
}
13751375

13761376
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
1377+
/// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
13771378
pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
13781379
maybe_whole_expr!(self);
13791380

src/librustc_parse/parser/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1509,7 +1509,7 @@ impl<'a> Parser<'a> {
15091509
})
15101510
// `extern ABI fn`
15111511
|| self.check_keyword(kw::Extern)
1512-
&& self.look_ahead(1, |t| t.can_begin_literal_or_bool())
1512+
&& self.look_ahead(1, |t| t.can_begin_literal_maybe_minus())
15131513
&& self.look_ahead(2, |t| t.is_keyword(kw::Fn))
15141514
}
15151515

src/librustc_parse/parser/pat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ impl<'a> Parser<'a> {
696696
self.look_ahead(dist, |t| {
697697
t.is_path_start() // e.g. `MY_CONST`;
698698
|| t.kind == token::Dot // e.g. `.5` for recovery;
699-
|| t.can_begin_literal_or_bool() // e.g. `42`.
699+
|| t.can_begin_literal_maybe_minus() // e.g. `42`.
700700
|| t.is_whole_expr()
701701
})
702702
}

src/test/ui/parser/extern-abi-from-mac-literal-frag.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// check-pass
22

33
// In this test we check that the parser accepts an ABI string when it
4-
// comes from a macro `literal` fragment as opposed to a hardcoded string.
4+
// comes from a macro `literal` or `expr` fragment as opposed to a hardcoded string.
55

66
fn main() {}
77

@@ -17,10 +17,30 @@ macro_rules! abi_from_lit_frag {
1717
}
1818
}
1919

20+
macro_rules! abi_from_expr_frag {
21+
($abi:expr) => {
22+
extern $abi {
23+
fn _import();
24+
}
25+
26+
extern $abi fn _export() {}
27+
28+
type _PTR = extern $abi fn();
29+
};
30+
}
31+
2032
mod rust {
2133
abi_from_lit_frag!("Rust");
2234
}
2335

2436
mod c {
2537
abi_from_lit_frag!("C");
2638
}
39+
40+
mod rust_expr {
41+
abi_from_expr_frag!("Rust");
42+
}
43+
44+
mod c_expr {
45+
abi_from_expr_frag!("C");
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// check-pass
2+
3+
macro_rules! foo {
4+
($a:literal) => {
5+
bar!($a)
6+
};
7+
}
8+
9+
macro_rules! bar {
10+
($b:literal) => {};
11+
}
12+
13+
fn main() {
14+
foo!(-2);
15+
bar!(-2);
16+
}

0 commit comments

Comments
 (0)