about summary refs log tree commit diff
path: root/src/tools/rustfmt
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-03-03 10:40:56 +0100
committerGitHub <noreply@github.com>2025-03-03 10:40:56 +0100
commit2344a34241e2cf08e6285ddf7755b70bfa306e5a (patch)
tree5e72f03cef42d18af3990ac2e88a906d730d70c2 /src/tools/rustfmt
parent81d8edc2000aa38b08ad09fce22d90f1990b6459 (diff)
parent42f51d4fd42c95e0c51c3f8742d63db0548cd5a0 (diff)
downloadrust-2344a34241e2cf08e6285ddf7755b70bfa306e5a.tar.gz
rust-2344a34241e2cf08e6285ddf7755b70bfa306e5a.zip
Rollup merge of #132388 - frank-king:feature/where-cfg, r=petrochenkov
Implement `#[cfg]` in `where` clauses

This PR implements #115590, which supports `#[cfg]` attributes in `where` clauses.

The biggest change is, that it adds `AttrsVec` and  `NodeId` to the `ast::WherePredicate` and `HirId` to the `hir::WherePredicate`.
Diffstat (limited to 'src/tools/rustfmt')
-rw-r--r--src/tools/rustfmt/src/spanned.rs7
-rw-r--r--src/tools/rustfmt/src/types.rs35
-rw-r--r--src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs116
3 files changed, 151 insertions, 7 deletions
diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs
index e93eb53cd87..507647566d4 100644
--- a/src/tools/rustfmt/src/spanned.rs
+++ b/src/tools/rustfmt/src/spanned.rs
@@ -58,6 +58,7 @@ implement_spanned!(ast::ExprField);
 implement_spanned!(ast::ForeignItem);
 implement_spanned!(ast::Item);
 implement_spanned!(ast::Local);
+implement_spanned!(ast::WherePredicate);
 
 impl Spanned for ast::Stmt {
     fn span(&self) -> Span {
@@ -149,12 +150,6 @@ impl Spanned for ast::FieldDef {
     }
 }
 
-impl Spanned for ast::WherePredicate {
-    fn span(&self) -> Span {
-        self.span
-    }
-}
-
 impl Spanned for ast::FnRetTy {
     fn span(&self) -> Span {
         match *self {
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 7b44b47c719..06a67334086 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -463,8 +463,9 @@ impl Rewrite for ast::WherePredicate {
     }
 
     fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        let attrs_str = self.attrs.rewrite_result(context, shape)?;
         // FIXME: dead spans?
-        let result = match self.kind {
+        let pred_str = &match self.kind {
             ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
                 ref bound_generic_params,
                 ref bounded_ty,
@@ -499,6 +500,38 @@ impl Rewrite for ast::WherePredicate {
             }
         };
 
+        let mut result = String::with_capacity(attrs_str.len() + pred_str.len() + 1);
+        result.push_str(&attrs_str);
+        let pred_start = self.span.lo();
+        let line_len = last_line_width(&attrs_str) + 1 + first_line_width(&pred_str);
+        if let Some(last_attr) = self.attrs.last().filter(|last_attr| {
+            contains_comment(context.snippet(mk_sp(last_attr.span.hi(), pred_start)))
+        }) {
+            result = combine_strs_with_missing_comments(
+                context,
+                &result,
+                &pred_str,
+                mk_sp(last_attr.span.hi(), pred_start),
+                Shape {
+                    width: shape.width.min(context.config.inline_attribute_width()),
+                    ..shape
+                },
+                !last_attr.is_doc_comment(),
+            )?;
+        } else {
+            if !self.attrs.is_empty() {
+                if context.config.inline_attribute_width() < line_len
+                    || self.attrs.len() > 1
+                    || self.attrs.last().is_some_and(|a| a.is_doc_comment())
+                {
+                    result.push_str(&shape.indent.to_string_with_newline(context.config));
+                } else {
+                    result.push(' ');
+                }
+            }
+            result.push_str(&pred_str);
+        }
+
         Ok(result)
     }
 }
diff --git a/src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs b/src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs
new file mode 100644
index 00000000000..11f495b1629
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs
@@ -0,0 +1,116 @@
+// rustfmt-inline_attribute_width: 40
+
+#![crate_type = "lib"]
+#![feature(cfg_attribute_in_where)]
+use std::marker::PhantomData;
+
+#[cfg(a)]
+trait TraitA {}
+
+#[cfg(b)]
+trait TraitB {}
+
+trait A<T>
+where
+    #[cfg = a_very_long_attribute_name]
+    T: TraitA,
+    #[cfg = another_very_long_attribute_name]
+    T: TraitB,
+{
+    type B<U>
+    where
+        #[cfg = a]
+        // line comment after the attribute
+        U: TraitA,
+        #[cfg = b]
+        /* block comment after the attribute */
+        U: TraitB,
+        #[cfg = a] // short
+        U: TraitA,
+        #[cfg = b] /* short */ U: TraitB;
+
+    fn foo<U>(&self)
+    where
+        /// line doc comment before the attribute
+        U: TraitA,
+        /** line doc block comment before the attribute */
+        U: TraitB;
+}
+
+impl<T> A<T> for T
+where
+    #[doc = "line doc before the attribute"]
+    T: TraitA,
+    /** short doc */
+    T: TraitB,
+{
+    type B<U>
+        = ()
+    where
+        #[doc = "short"] U: TraitA,
+        #[doc = "short"]
+        #[cfg = a]
+        U: TraitB;
+
+    fn foo<U>(&self)
+    where
+        #[cfg = a]
+        #[cfg = b]
+        U: TraitA,
+        /// line doc
+        #[cfg = c]
+        U: TraitB,
+    {
+    }
+}
+
+struct C<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+    _t: PhantomData<T>,
+}
+
+union D<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+    _t: PhantomData<T>,
+}
+
+enum E<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+    E(PhantomData<T>),
+}
+
+#[allow(type_alias_bounds)]
+type F<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+= T;
+
+impl<T> C<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+    fn new<U>()
+    where
+        #[cfg = a] U: TraitA,
+        #[cfg = b] U: TraitB,
+    {
+    }
+}
+
+fn foo<T>()
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+}