about summary refs log tree commit diff
path: root/compiler/rustc_parse/src
diff options
context:
space:
mode:
authorJosh Triplett <josh@joshtriplett.org>2025-08-10 16:17:26 -0700
committerJosh Triplett <josh@joshtriplett.org>2025-08-10 16:18:01 -0700
commit38df15805ba5be78d70c515f1d585ee6be95e13b (patch)
tree9ab0eb80fa5284cc9bed785fa4e980a7090e8a54 /compiler/rustc_parse/src
parent29737cb44beb67dbcf001ca1f11b7ec8964d8d06 (diff)
downloadrust-38df15805ba5be78d70c515f1d585ee6be95e13b.tar.gz
rust-38df15805ba5be78d70c515f1d585ee6be95e13b.zip
cfg_select: Support unbraced expressions
When operating on expressions, `cfg_select!` can now handle expressions
without braces. (It still requires braces for other things, such as
items.)

Expand the test coverage and documentation accordingly.
Diffstat (limited to 'compiler/rustc_parse/src')
-rw-r--r--compiler/rustc_parse/src/parser/cfg_select.rs30
1 files changed, 19 insertions, 11 deletions
diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs
index 2c6fb224d70..08a71db4de8 100644
--- a/compiler/rustc_parse/src/parser/cfg_select.rs
+++ b/compiler/rustc_parse/src/parser/cfg_select.rs
@@ -1,11 +1,12 @@
 use rustc_ast::token::Token;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_ast::util::classify;
 use rustc_ast::{MetaItemInner, token};
 use rustc_errors::PResult;
 use rustc_span::Span;
 
 use crate::exp;
-use crate::parser::Parser;
+use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos};
 
 pub enum CfgSelectPredicate {
     Cfg(MetaItemInner),
@@ -23,19 +24,26 @@ pub struct CfgSelectBranches {
     pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>,
 }
 
-/// Parses a `TokenTree` that must be of the form `{ /* ... */ }`, and returns a `TokenStream` where
-/// the surrounding braces are stripped.
+/// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an
+/// expression followed by a comma (and strip the comma).
 fn parse_token_tree<'a>(p: &mut Parser<'a>) -> PResult<'a, TokenStream> {
-    // Generate an error if the `=>` is not followed by `{`.
-    if p.token != token::OpenBrace {
-        p.expect(exp!(OpenBrace))?;
+    if p.token == token::OpenBrace {
+        // Strip the outer '{' and '}'.
+        match p.parse_token_tree() {
+            TokenTree::Token(..) => unreachable!("because of the expect above"),
+            TokenTree::Delimited(.., tts) => return Ok(tts),
+        }
     }
-
-    // Strip the outer '{' and '}'.
-    match p.parse_token_tree() {
-        TokenTree::Token(..) => unreachable!("because of the expect above"),
-        TokenTree::Delimited(.., tts) => Ok(tts),
+    let expr = p.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| {
+        p.parse_expr_res(Restrictions::STMT_EXPR, AttrWrapper::empty())
+            .map(|(expr, _)| (expr, Trailing::No, UsePreAttrPos::No))
+    })?;
+    if !classify::expr_is_complete(&expr) && p.token != token::CloseBrace && p.token != token::Eof {
+        p.expect(exp!(Comma))?;
+    } else {
+        let _ = p.eat(exp!(Comma));
     }
+    Ok(TokenStream::from_ast(&expr))
 }
 
 pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> {