diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index bb3722fe156..d2cb6ee9f71 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -124,8 +124,27 @@ pub fn fluent_messages(input: TokenStream) -> TokenStream { 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( diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 95bb27ef4f4..51729a377d9 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,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)? + } } }) }); diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index 67057e1a97c..0a16a371fdc 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -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 }); } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 6f42b69633c..13cf996303d 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -27,7 +27,6 @@ pub use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::Dominators; -use rustc_index::bit_set::BitMatrix; use rustc_index::vec::{Idx, IndexVec}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::symbol::Symbol; @@ -62,7 +61,6 @@ pub mod traversal; mod type_foldable; -mod type_visitable; pub mod visit; pub use self::generic_graph::graphviz_safe_def_name; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 6155f2bb56c..e2ab3fd35b3 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -161,6 +161,8 @@ pub struct GeneratorLayout<'tcx> { /// Which saved locals are storage-live at the same time. Locals that do not /// have conflicts with each other are allowed to overlap in the computed /// layout. + #[type_foldable(identity)] + #[type_visitable(ignore)] pub storage_conflicts: BitMatrix, } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 006085c0ef5..ce06a0ef060 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -47,9 +47,3 @@ fn try_fold_with>(self, folder: &mut F) -> Result TypeFoldable> for BitMatrix { - fn try_fold_with>(self, _: &mut F) -> Result { - Ok(self) - } -} diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs deleted file mode 100644 index e7c5d44b22e..00000000000 --- a/compiler/rustc_middle/src/mir/type_visitable.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! `TypeVisitable` implementations for MIR types - -use super::*; - -impl<'tcx, R: Idx, C: Idx> ir::TypeVisitable> for BitMatrix { - fn visit_with>(&self, _: &mut V) -> ControlFlow { - ControlFlow::Continue(()) - } -}