]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_macros/src/type_foldable.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_macros / src / type_foldable.rs
index 23e619221aab7e289f0decb098302e4e315df55d..388e254cd64530fe82b7cd9f043c7a59957fa360 100644 (file)
@@ -1,5 +1,5 @@
-use quote::quote;
-use syn::parse_quote;
+use quote::{quote, ToTokens};
+use syn::{parse_quote, Attribute, Meta, NestedMeta};
 
 pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
@@ -16,16 +16,37 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
         let bindings = vi.bindings();
         vi.construct(|_, index| {
             let bind = &bindings[index];
-            quote! {
-                ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)?
+
+            // retain value of fields with #[type_foldable(identity)]
+            let fixed = bind
+                .ast()
+                .attrs
+                .iter()
+                .map(Attribute::parse_meta)
+                .filter_map(Result::ok)
+                .flat_map(|attr| match attr {
+                    Meta::List(list) if list.path.is_ident("type_foldable") => list.nested,
+                    _ => Default::default(),
+                })
+                .any(|nested| match nested {
+                    NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"),
+                    _ => false,
+                });
+
+            if fixed {
+                bind.to_token_stream()
+            } else {
+                quote! {
+                    ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)?
+                }
             }
         })
     });
 
     s.bound_impl(
-        quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>),
+        quote!(::rustc_middle::ty::fold::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>),
         quote! {
-            fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<'tcx>>(
+            fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(
                 self,
                 __folder: &mut __F
             ) -> Result<Self, __F::Error> {