about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/ty/error.rs3
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs22
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs7
-rw-r--r--compiler/rustc_type_ir/src/error.rs13
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs4
-rw-r--r--compiler/rustc_type_ir/src/relate.rs54
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs4
-rw-r--r--compiler/rustc_type_ir/src/ty_kind/closure.rs4
-rw-r--r--compiler/rustc_type_ir_macros/src/lib.rs114
9 files changed, 110 insertions, 115 deletions
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index b02eff3bfd6..c49824bb418 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -35,9 +35,6 @@ impl<'tcx> TypeError<'tcx> {
             TypeError::CyclicTy(_) => "cyclic type of infinite size".into(),
             TypeError::CyclicConst(_) => "encountered a self-referencing constant".into(),
             TypeError::Mismatch => "types differ".into(),
-            TypeError::ConstnessMismatch(values) => {
-                format!("expected {} bound, found {} bound", values.expected, values.found).into()
-            }
             TypeError::PolarityMismatch(values) => {
                 format!("expected {} polarity, found {} polarity", values.expected, values.found)
                     .into()
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 4c7bcb1bf2e..504a3c8a6d8 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -1,7 +1,5 @@
 use std::iter;
 
-use rustc_hir as hir;
-use rustc_target::spec::abi;
 pub use rustc_type_ir::relate::*;
 
 use crate::ty::error::{ExpectedFound, TypeError};
@@ -121,26 +119,6 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
     }
 }
 
-impl<'tcx> Relate<TyCtxt<'tcx>> for hir::Safety {
-    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
-        _relation: &mut R,
-        a: hir::Safety,
-        b: hir::Safety,
-    ) -> RelateResult<'tcx, hir::Safety> {
-        if a != b { Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a, b))) } else { Ok(a) }
-    }
-}
-
-impl<'tcx> Relate<TyCtxt<'tcx>> for abi::Abi {
-    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
-        _relation: &mut R,
-        a: abi::Abi,
-        b: abi::Abi,
-    ) -> RelateResult<'tcx, abi::Abi> {
-        if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(ExpectedFound::new(true, a, b))) }
-    }
-}
-
 impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
     fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index cd9ff9b60d8..4872d8c89eb 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -264,8 +264,6 @@ TrivialTypeTraversalImpls! {
 // interners).
 TrivialTypeTraversalAndLiftImpls! {
     ::rustc_hir::def_id::DefId,
-    ::rustc_hir::Safety,
-    ::rustc_target::spec::abi::Abi,
     crate::ty::ClosureKind,
     crate::ty::ParamConst,
     crate::ty::ParamTy,
@@ -276,6 +274,11 @@ TrivialTypeTraversalAndLiftImpls! {
     rustc_target::abi::Size,
 }
 
+TrivialLiftImpls! {
+    ::rustc_hir::Safety,
+    ::rustc_target::spec::abi::Abi,
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Lift implementations
 
diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs
index 8a6d37b7d23..cdff77f742d 100644
--- a/compiler/rustc_type_ir/src/error.rs
+++ b/compiler/rustc_type_ir/src/error.rs
@@ -27,10 +27,9 @@ impl<T> ExpectedFound<T> {
 #[cfg_attr(feature = "nightly", rustc_pass_by_value)]
 pub enum TypeError<I: Interner> {
     Mismatch,
-    ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
-    PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
-    SafetyMismatch(ExpectedFound<I::Safety>),
-    AbiMismatch(ExpectedFound<I::Abi>),
+    PolarityMismatch(#[type_visitable(ignore)] ExpectedFound<ty::PredicatePolarity>),
+    SafetyMismatch(#[type_visitable(ignore)] ExpectedFound<I::Safety>),
+    AbiMismatch(#[type_visitable(ignore)] ExpectedFound<I::Abi>),
     Mutability,
     ArgumentMutability(usize),
     TupleSize(ExpectedFound<usize>),
@@ -73,9 +72,9 @@ impl<I: Interner> TypeError<I> {
     pub fn must_include_note(self) -> bool {
         use self::TypeError::*;
         match self {
-            CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_)
-            | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
-            | ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
+            CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | PolarityMismatch(_) | Mismatch
+            | AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_)
+            | VariadicMismatch(_) | TargetFeatureCast(_) => false,
 
             Mutability
             | ArgumentMutability(_)
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index f7875bb5152..02ec29a7f3d 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -208,14 +208,14 @@ pub trait Tys<I: Interner<Tys = Self>>:
     fn output(self) -> I::Ty;
 }
 
-pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
+pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
     fn rust() -> Self;
 
     /// Whether this ABI is `extern "Rust"`.
     fn is_rust(self) -> bool;
 }
 
-pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
+pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
     fn safe() -> Self;
 
     fn is_safe(self) -> bool;
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index a0b93064694..ad17911830b 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -174,12 +174,17 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
                 ExpectedFound::new(true, a, b)
             }));
         }
-        let safety = relation.relate(a.safety, b.safety)?;
-        let abi = relation.relate(a.abi, b.abi)?;
+
+        if a.safety != b.safety {
+            return Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a.safety, b.safety)));
+        }
+
+        if a.abi != b.abi {
+            return Err(TypeError::AbiMismatch(ExpectedFound::new(true, a.abi, b.abi)));
+        };
 
         let a_inputs = a.inputs();
         let b_inputs = b.inputs();
-
         if a_inputs.len() != b_inputs.len() {
             return Err(TypeError::ArgCount);
         }
@@ -212,26 +217,12 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
         Ok(ty::FnSig {
             inputs_and_output: cx.mk_type_list_from_iter(inputs_and_output)?,
             c_variadic: a.c_variadic,
-            safety,
-            abi,
+            safety: a.safety,
+            abi: a.abi,
         })
     }
 }
 
-impl<I: Interner> Relate<I> for ty::BoundConstness {
-    fn relate<R: TypeRelation<I>>(
-        _relation: &mut R,
-        a: ty::BoundConstness,
-        b: ty::BoundConstness,
-    ) -> RelateResult<I, ty::BoundConstness> {
-        if a != b {
-            Err(TypeError::ConstnessMismatch(ExpectedFound::new(true, a, b)))
-        } else {
-            Ok(a)
-        }
-    }
-}
-
 impl<I: Interner> Relate<I> for ty::AliasTy<I> {
     fn relate<R: TypeRelation<I>>(
         relation: &mut R,
@@ -659,29 +650,18 @@ impl<I: Interner, T: Relate<I>> Relate<I> for ty::Binder<I, T> {
     }
 }
 
-impl<I: Interner> Relate<I> for ty::PredicatePolarity {
-    fn relate<R: TypeRelation<I>>(
-        _relation: &mut R,
-        a: ty::PredicatePolarity,
-        b: ty::PredicatePolarity,
-    ) -> RelateResult<I, ty::PredicatePolarity> {
-        if a != b {
-            Err(TypeError::PolarityMismatch(ExpectedFound::new(true, a, b)))
-        } else {
-            Ok(a)
-        }
-    }
-}
-
 impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
     fn relate<R: TypeRelation<I>>(
         relation: &mut R,
         a: ty::TraitPredicate<I>,
         b: ty::TraitPredicate<I>,
     ) -> RelateResult<I, ty::TraitPredicate<I>> {
-        Ok(ty::TraitPredicate {
-            trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
-            polarity: relation.relate(a.polarity, b.polarity)?,
-        })
+        let trait_ref = relation.relate(a.trait_ref, b.trait_ref)?;
+        if a.polarity != b.polarity {
+            return Err(TypeError::PolarityMismatch(ExpectedFound::new(
+                true, a.polarity, b.polarity,
+            )));
+        }
+        Ok(ty::TraitPredicate { trait_ref, polarity: a.polarity })
     }
 }
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index b7f6ef4ffbb..499e6d3dd37 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -861,7 +861,11 @@ pub struct TypeAndMut<I: Interner> {
 pub struct FnSig<I: Interner> {
     pub inputs_and_output: I::Tys,
     pub c_variadic: bool,
+    #[type_visitable(ignore)]
+    #[type_foldable(identity)]
     pub safety: I::Safety,
+    #[type_visitable(ignore)]
+    #[type_foldable(identity)]
     pub abi: I::Abi,
 }
 
diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs
index 09a43b17955..10b164eae02 100644
--- a/compiler/rustc_type_ir/src/ty_kind/closure.rs
+++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs
@@ -372,8 +372,12 @@ pub struct CoroutineClosureSignature<I: Interner> {
     /// Always false
     pub c_variadic: bool,
     /// Always `Normal` (safe)
+    #[type_visitable(ignore)]
+    #[type_foldable(identity)]
     pub safety: I::Safety,
     /// Always `RustCall`
+    #[type_visitable(ignore)]
+    #[type_foldable(identity)]
     pub abi: I::Abi,
 }
 
diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs
index 1a0a2479f6f..aaf69e2648d 100644
--- a/compiler/rustc_type_ir_macros/src/lib.rs
+++ b/compiler/rustc_type_ir_macros/src/lib.rs
@@ -1,18 +1,73 @@
-use quote::quote;
-use syn::parse_quote;
+use quote::{ToTokens, quote};
 use syn::visit_mut::VisitMut;
+use syn::{Attribute, parse_quote};
 use synstructure::decl_derive;
 
 decl_derive!(
-    [TypeFoldable_Generic] => type_foldable_derive
+    [TypeVisitable_Generic, attributes(type_visitable)] => type_visitable_derive
 );
 decl_derive!(
-    [TypeVisitable_Generic] => type_visitable_derive
+    [TypeFoldable_Generic, attributes(type_foldable)] => type_foldable_derive
 );
 decl_derive!(
     [Lift_Generic] => lift_derive
 );
 
+fn has_ignore_attr(attrs: &[Attribute], name: &'static str, meta: &'static str) -> bool {
+    let mut ignored = false;
+    attrs.iter().for_each(|attr| {
+        if !attr.path().is_ident(name) {
+            return;
+        }
+        let _ = attr.parse_nested_meta(|nested| {
+            if nested.path.is_ident(meta) {
+                ignored = true;
+            }
+            Ok(())
+        });
+    });
+
+    ignored
+}
+
+fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    if let syn::Data::Union(_) = s.ast().data {
+        panic!("cannot derive on union")
+    }
+
+    if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
+        s.add_impl_generic(parse_quote! { I });
+    }
+
+    s.filter(|bi| !has_ignore_attr(&bi.ast().attrs, "type_visitable", "ignore"));
+
+    s.add_where_predicate(parse_quote! { I: Interner });
+    s.add_bounds(synstructure::AddBounds::Fields);
+    let body_visit = s.each(|bind| {
+        quote! {
+            match ::rustc_ast_ir::visit::VisitorResult::branch(
+                ::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
+            ) {
+                ::core::ops::ControlFlow::Continue(()) => {},
+                ::core::ops::ControlFlow::Break(r) => {
+                    return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
+                },
+            }
+        }
+    });
+    s.bind_with(|_| synstructure::BindStyle::Move);
+
+    s.bound_impl(quote!(::rustc_type_ir::visit::TypeVisitable<I>), quote! {
+        fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor<I>>(
+            &self,
+            __visitor: &mut __V
+        ) -> __V::Result {
+            match *self { #body_visit }
+            <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
+        }
+    })
+}
+
 fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
         panic!("cannot derive on union")
@@ -29,12 +84,23 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke
         let bindings = vi.bindings();
         vi.construct(|_, index| {
             let bind = &bindings[index];
-            quote! {
-                ::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)?
+
+            // retain value of fields with #[type_foldable(identity)]
+            if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") {
+                bind.to_token_stream()
+            } else {
+                quote! {
+                    ::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)?
+                }
             }
         })
     });
 
+    // We filter fields which get ignored and don't require them to implement
+    // `TypeFoldable`. We do so after generating `body_fold` as we still need
+    // to generate code for them.
+    s.filter(|bi| !has_ignore_attr(&bi.ast().attrs, "type_foldable", "identity"));
+    s.add_bounds(synstructure::AddBounds::Fields);
     s.bound_impl(quote!(::rustc_type_ir::fold::TypeFoldable<I>), quote! {
         fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder<I>>(
             self,
@@ -113,39 +179,3 @@ fn lift(mut ty: syn::Type) -> syn::Type {
 
     ty
 }
-
-fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
-    if let syn::Data::Union(_) = s.ast().data {
-        panic!("cannot derive on union")
-    }
-
-    if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
-        s.add_impl_generic(parse_quote! { I });
-    }
-
-    s.add_where_predicate(parse_quote! { I: Interner });
-    s.add_bounds(synstructure::AddBounds::Fields);
-    let body_visit = s.each(|bind| {
-        quote! {
-            match ::rustc_ast_ir::visit::VisitorResult::branch(
-                ::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
-            ) {
-                ::core::ops::ControlFlow::Continue(()) => {},
-                ::core::ops::ControlFlow::Break(r) => {
-                    return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
-                },
-            }
-        }
-    });
-    s.bind_with(|_| synstructure::BindStyle::Move);
-
-    s.bound_impl(quote!(::rustc_type_ir::visit::TypeVisitable<I>), quote! {
-        fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor<I>>(
-            &self,
-            __visitor: &mut __V
-        ) -> __V::Result {
-            match *self { #body_visit }
-            <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
-        }
-    })
-}