Use derive attributes for uninteresting traversals
This commit is contained in:
parent
e9ab7872fd
commit
3b510e88ef
7 changed files with 66 additions and 24 deletions
|
@ -124,8 +124,27 @@ decl_derive!([TyDecodable] => serialize::type_decodable_derive);
|
|||
decl_derive!([TyEncodable] => serialize::type_encodable_derive);
|
||||
decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive);
|
||||
decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
|
||||
decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
|
||||
decl_derive!([TypeVisitable, attributes(type_visitable)] => type_visitable::type_visitable_derive);
|
||||
decl_derive!(
|
||||
[TypeFoldable, attributes(type_foldable)] =>
|
||||
/// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported).
|
||||
///
|
||||
/// The fold will produce a value of the same struct or enum variant as the input, with
|
||||
/// each field respectively folded using the `TypeFoldable` implementation for its type.
|
||||
/// However, if a field of a struct or an enum variant is annotated with
|
||||
/// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its
|
||||
/// type is not required to implement `TypeFoldable`).
|
||||
type_foldable::type_foldable_derive
|
||||
);
|
||||
decl_derive!(
|
||||
[TypeVisitable, attributes(type_visitable)] =>
|
||||
/// Derives `TypeVisitable` for the annotated `struct` or `enum` (`union` is not supported).
|
||||
///
|
||||
/// Each field of the struct or enum variant will be visited in definition order, using the
|
||||
/// `TypeVisitable` implementation for its type. However, if a field of a struct or an enum
|
||||
/// variant is annotated with `#[type_visitable(ignore)]` then that field will not be
|
||||
/// visited (and its type is not required to implement `TypeVisitable`).
|
||||
type_visitable::type_visitable_derive
|
||||
);
|
||||
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
|
||||
decl_derive!(
|
||||
[Diagnostic, attributes(
|
||||
|
|
|
@ -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,8 +16,29 @@ 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::ir::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::ir::TypeFoldable::try_fold_with(#bind, __folder)?
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
|
@ -1,11 +1,28 @@
|
|||
use quote::quote;
|
||||
use syn::parse_quote;
|
||||
use syn::{parse_quote, Attribute, Meta, NestedMeta};
|
||||
|
||||
pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||
if let syn::Data::Union(_) = s.ast().data {
|
||||
panic!("cannot derive on union")
|
||||
}
|
||||
|
||||
// ignore fields with #[type_visitable(ignore)]
|
||||
s.filter(|bi| {
|
||||
!bi.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_visitable") => list.nested,
|
||||
_ => Default::default(),
|
||||
})
|
||||
.any(|nested| match nested {
|
||||
NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"),
|
||||
_ => false,
|
||||
})
|
||||
});
|
||||
|
||||
if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
|
||||
s.add_impl_generic(parse_quote! { 'tcx });
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue