diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 9f032fa588195..e2c62e60ecced 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -107,41 +107,42 @@ impl CfgEval<'_> { // our attribute target will correctly configure the tokens as well. let mut parser = Parser::new(&self.0.sess.psess, orig_tokens, None); parser.capture_cfg = true; - let res: PResult<'_, Annotatable> = try { - match annotatable { - Annotatable::Item(_) => { - let item = - parser.parse_item(ForceCollect::Yes, AllowConstBlockItems::Yes)?.unwrap(); - Annotatable::Item(self.flat_map_item(item).pop().unwrap()) - } + let res: PResult<'_, Option> = try { + match &annotatable { + Annotatable::Item(_) => parser + .parse_item(ForceCollect::Yes, AllowConstBlockItems::Yes)? + .and_then(|item| self.flat_map_item(item).pop().map(Annotatable::Item)), Annotatable::AssocItem(_, ctxt) => { - let item = parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(); - Annotatable::AssocItem( - self.flat_map_assoc_item(item, ctxt).pop().unwrap(), - ctxt, - ) + parser.parse_trait_item(ForceCollect::Yes)?.flatten().and_then(|item| { + self.flat_map_assoc_item(item, *ctxt) + .pop() + .map(|item| Annotatable::AssocItem(item, *ctxt)) + }) } Annotatable::ForeignItem(_) => { - let item = parser.parse_foreign_item(ForceCollect::Yes)?.unwrap().unwrap(); - Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap()) - } - Annotatable::Stmt(_) => { - let stmt = parser - .parse_stmt_without_recovery(false, ForceCollect::Yes, false)? - .unwrap(); - Annotatable::Stmt(Box::new(self.flat_map_stmt(stmt).pop().unwrap())) + parser.parse_foreign_item(ForceCollect::Yes)?.flatten().and_then(|item| { + self.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem) + }) } + Annotatable::Stmt(_) => parser + .parse_stmt_without_recovery(false, ForceCollect::Yes, false)? + .and_then(|stmt| { + self.flat_map_stmt(stmt).pop().map(|stmt| Annotatable::Stmt(Box::new(stmt))) + }), Annotatable::Expr(_) => { let mut expr = parser.parse_expr_force_collect()?; self.visit_expr(&mut expr); - Annotatable::Expr(expr) + Some(Annotatable::Expr(expr)) } _ => unreachable!(), } }; match res { - Ok(ann) => ann, + Ok(Some(ann)) => ann, + // Parser recovery may emit errors without reconstructing an annotatable. + // Keep the original node so cfg-eval stays best-effort instead of ICEing. + Ok(None) => annotatable, Err(err) => { err.emit(); annotatable diff --git a/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.rs b/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.rs new file mode 100644 index 0000000000000..1f0215afadc7b --- /dev/null +++ b/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.rs @@ -0,0 +1,17 @@ +// Regression test for https://github.com/rust-lang/rust/issues/148891. + +macro_rules! values { + ($inner:ty) => { + #[derive(Debug)] + pub enum TokenKind { + #[cfg(test)] + STRING([u8; $inner]), + //~^ ERROR expected expression, found `ty` metavariable + //~| ERROR macro expansion ignores `)` and any tokens following + } + }; +} + +values!(String); + +fn main() {} diff --git a/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.stderr b/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.stderr new file mode 100644 index 0000000000000..0248b6636fb7a --- /dev/null +++ b/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.stderr @@ -0,0 +1,28 @@ +error: expected expression, found `ty` metavariable + --> $DIR/cfg-eval-derive-invalid-reparse-no-ice.rs:8:25 + | +LL | pub enum TokenKind { + | --------- while parsing this enum +LL | #[cfg(test)] +LL | STRING([u8; $inner]), + | ^^^^^^ expected expression +... +LL | values!(String); + | --------------- in this macro invocation + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macro expansion ignores `)` and any tokens following + --> $DIR/cfg-eval-derive-invalid-reparse-no-ice.rs:8:32 + | +LL | STRING([u8; $inner]), + | ^ +... +LL | values!(String); + | --------------- caused by the macro expansion here + | + = note: the usage of `values!` is likely invalid in item context + +error: aborting due to 2 previous errors +