summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_macros/src/type_foldable.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_macros/src/type_foldable.rs')
-rw-r--r--compiler/rustc_macros/src/type_foldable.rs33
1 files changed, 27 insertions, 6 deletions
diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs
index 23e619221..388e254cd 100644
--- a/compiler/rustc_macros/src/type_foldable.rs
+++ b/compiler/rustc_macros/src/type_foldable.rs
@@ -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> {