From f2bd6274be8869080db2171c9534ecf02bbd2b84 Mon Sep 17 00:00:00 2001 From: Usman Akinyemi Date: Sun, 19 Jul 2026 03:44:53 +0530 Subject: [PATCH] Reject cfg on expressions that cannot be safely removed Previously, expressions behind stmt_expr_attributes were only rejected when the cfg condition evaluated to false. If the condition was true, the code compiled successfully. This meant code like an attributed binary operand could compile on one platform but fail on another, even though removing the operand would leave an invalid expression. This change always rejects cfg in expression positions where removing the expression would produce invalid code. Expression positions where removal is safe continue to work as before. Signed-off-by: Usman Akinyemi --- compiler/rustc_expand/src/expand.rs | 6 +++++ .../cfg-non-opt-expr.rs | 7 +++++ .../cfg-non-opt-expr.stderr | 26 ++++++++++++++++--- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index b35f6dcb0af6f..f821163b1980e 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -2410,6 +2410,12 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { Some(sym::cfg) => { let span = attr.span; if self.expand_cfg_true(node, attr, pos).as_bool() { + if matches!( + Node::KIND, + AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr + ) { + self.cx.dcx().emit_err(RemoveExprNotSupported { span }); + } continue; } diff --git a/tests/ui/conditional-compilation/cfg-non-opt-expr.rs b/tests/ui/conditional-compilation/cfg-non-opt-expr.rs index cae07ae0ced10..d8a3741d9d077 100644 --- a/tests/ui/conditional-compilation/cfg-non-opt-expr.rs +++ b/tests/ui/conditional-compilation/cfg-non-opt-expr.rs @@ -2,6 +2,13 @@ #![feature(custom_test_frameworks)] fn main() { + let _ = 1 + #[cfg(unix)] 2; + //~^ ERROR removing an expression is not supported in this position + let _ = 1 + #[cfg(windows)] 2; + //~^ ERROR removing an expression is not supported in this position + + let _ = 1 + #[cfg(all())] 2; + //~^ ERROR removing an expression is not supported in this position let _ = #[cfg(false)] (); //~^ ERROR removing an expression is not supported in this position let _ = 1 + 2 + #[cfg(false)] 3; diff --git a/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr b/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr index bd1bfeb06c7ad..cb35bf94a64fb 100644 --- a/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr +++ b/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr @@ -1,20 +1,38 @@ error: removing an expression is not supported in this position - --> $DIR/cfg-non-opt-expr.rs:5:13 + --> $DIR/cfg-non-opt-expr.rs:5:17 + | +LL | let _ = 1 + #[cfg(unix)] 2; + | ^^^^^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:7:17 + | +LL | let _ = 1 + #[cfg(windows)] 2; + | ^^^^^^^^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:10:17 + | +LL | let _ = 1 + #[cfg(all())] 2; + | ^^^^^^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:12:13 | LL | let _ = #[cfg(false)] (); | ^^^^^^^^^^^^^ error: removing an expression is not supported in this position - --> $DIR/cfg-non-opt-expr.rs:7:21 + --> $DIR/cfg-non-opt-expr.rs:14:21 | LL | let _ = 1 + 2 + #[cfg(false)] 3; | ^^^^^^^^^^^^^ error: removing an expression is not supported in this position - --> $DIR/cfg-non-opt-expr.rs:9:23 + --> $DIR/cfg-non-opt-expr.rs:16:23 | LL | let _ = [1, 2, 3][#[cfg(false)] 1]; | ^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors