about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-02-14 18:24:43 +0100
committerGitHub <noreply@github.com>2023-02-14 18:24:43 +0100
commit9b39568e64442128318c981e74e4d4b11652c896 (patch)
tree2a084d08a511da266aec83a2a2cc7cb2ee6cf172
parent207d6e177ffb80c8f4bb4d49d6770be1e97177de (diff)
parent3b510e88efebb50c19776cfbaa7f43492cacf71d (diff)
downloadrust-9b39568e64442128318c981e74e4d4b11652c896.tar.gz
rust-9b39568e64442128318c981e74e4d4b11652c896.zip
Rollup merge of #108040 - eggyal:attributes_for_uninteresting_traversals, r=oli-obk
Use derive attributes for uninteresting traversals

It appears that visiting and folding was implemented on `BitMatrix` solely so that the derive macros could be used on `GeneratorLayout`, however such implementation would not necessarily be correct for other uses (if there were any).  Adding attributes to the derive macro is more correct and potentially more generally useful.

r? ``@oli-obk``
-rw-r--r--compiler/rustc_macros/src/lib.rs23
-rw-r--r--compiler/rustc_macros/src/type_foldable.rs29
-rw-r--r--compiler/rustc_macros/src/type_visitable.rs19
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/query.rs2
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs6
-rw-r--r--compiler/rustc_middle/src/mir/type_visitable.rs9
7 files changed, 66 insertions, 24 deletions
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 @@ 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(
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 @@ use polonius_engine::Atom;
 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 use terminator::*;
 
 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<GeneratorSavedLocal, GeneratorSavedLocal>,
 }
 
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 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
     }
 }
-
-impl<'tcx, R: Idx, C: Idx> TypeFoldable<TyCtxt<'tcx>> for BitMatrix<R, C> {
-    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
-        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<TyCtxt<'tcx>> for BitMatrix<R, C> {
-    fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
-        ControlFlow::Continue(())
-    }
-}