about summary refs log tree commit diff
path: root/compiler/rustc_macros
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-04-14 15:10:43 +0000
committerMichael Goulet <michael@errs.io>2025-04-15 18:30:35 +0000
commitc774adcbb535e69bffe5be329af006959f897fbd (patch)
treec84fe987b44fccc409f3e81d7f78be851dec0ebe /compiler/rustc_macros
parent13b4734e3102b4fd5ad99b98a8cc46744faf5d68 (diff)
downloadrust-c774adcbb535e69bffe5be329af006959f897fbd.tar.gz
rust-c774adcbb535e69bffe5be329af006959f897fbd.zip
Split TypeFolder and FallibleTypeFolder
Diffstat (limited to 'compiler/rustc_macros')
-rw-r--r--compiler/rustc_macros/src/type_foldable.rs60
1 files changed, 43 insertions, 17 deletions
diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs
index c4f584dca43..85051311bee 100644
--- a/compiler/rustc_macros/src/type_foldable.rs
+++ b/compiler/rustc_macros/src/type_foldable.rs
@@ -14,27 +14,13 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m
 
     s.add_bounds(synstructure::AddBounds::Generics);
     s.bind_with(|_| synstructure::BindStyle::Move);
-    let body_fold = s.each_variant(|vi| {
+    let try_body_fold = s.each_variant(|vi| {
         let bindings = vi.bindings();
         vi.construct(|_, index| {
             let bind = &bindings[index];
 
-            let mut fixed = false;
-
             // retain value of fields with #[type_foldable(identity)]
-            bind.ast().attrs.iter().for_each(|x| {
-                if !x.path().is_ident("type_foldable") {
-                    return;
-                }
-                let _ = x.parse_nested_meta(|nested| {
-                    if nested.path.is_ident("identity") {
-                        fixed = true;
-                    }
-                    Ok(())
-                });
-            });
-
-            if fixed {
+            if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") {
                 bind.to_token_stream()
             } else {
                 quote! {
@@ -44,6 +30,22 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m
         })
     });
 
+    let body_fold = s.each_variant(|vi| {
+        let bindings = vi.bindings();
+        vi.construct(|_, index| {
+            let bind = &bindings[index];
+
+            // retain value of fields with #[type_foldable(identity)]
+            if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") {
+                bind.to_token_stream()
+            } else {
+                quote! {
+                    ::rustc_middle::ty::TypeFoldable::fold_with(#bind, __folder)
+                }
+            }
+        })
+    });
+
     s.bound_impl(
         quote!(::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>),
         quote! {
@@ -51,8 +53,32 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m
                 self,
                 __folder: &mut __F
             ) -> Result<Self, __F::Error> {
-                Ok(match self { #body_fold })
+                Ok(match self { #try_body_fold })
+            }
+
+            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(
+                self,
+                __folder: &mut __F
+            ) -> Self {
+                match self { #body_fold }
             }
         },
     )
 }
+
+fn has_ignore_attr(attrs: &[syn::Attribute], name: &'static str, meta: &'static str) -> bool {
+    let mut ignored = false;
+    attrs.iter().for_each(|attr| {
+        if !attr.path().is_ident(name) {
+            return;
+        }
+        let _ = attr.parse_nested_meta(|nested| {
+            if nested.path.is_ident(meta) {
+                ignored = true;
+            }
+            Ok(())
+        });
+    });
+
+    ignored
+}