diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index fa44ffcd17dd0..d11a020329a5b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -521,7 +521,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // C-variadic fns also have a `VaList` input that's not listed in the signature // (as it's created inside the body itself, not passed in from outside). if let DefiningTy::FnDef(def_id, _) = defining_ty { - if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() { + if self.infcx.tcx.fn_sig(def_id).extract(ty::Binder::c_variadic) { let va_list_did = self.infcx.tcx.require_lang_item( LangItem::VaList, Some(self.infcx.tcx.def_span(self.mir_def)), diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 892ec3e95855e..77c4c8ca0abf6 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -433,7 +433,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( None }; - let extra_args = &args[fn_sig.inputs().skip_binder().len()..]; + let extra_args = &args[fn_sig.inputs().extract(|inputs| inputs.len())..]; let extra_args = fx.tcx.mk_type_list_from_iter( extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.node.ty(fx.mir, fx.tcx))), ); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index a5bd3adbcddc9..3b0f9d906d5ad 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -202,7 +202,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if !is_closure && let Some(fn_sig) = fn_sig() - && fn_sig.skip_binder().abi() != abi::Abi::Rust + && fn_sig.extract(ty::Binder::abi) != abi::Abi::Rust { struct_span_code_err!( tcx.dcx(), @@ -245,7 +245,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { sym::target_feature => { if !tcx.is_closure_like(did.to_def_id()) && let Some(fn_sig) = fn_sig() - && fn_sig.skip_binder().safety() == hir::Safety::Safe + && fn_sig.extract(ty::Binder::safety) == hir::Safety::Safe { if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { // The `#[target_feature]` attribute is allowed on diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index e3553dc03e106..6f22d86a1e4a9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -869,7 +869,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let sig = callee.layout.ty.fn_sig(bx.tcx()); let abi = sig.abi(); - let extra_args = &args[sig.inputs().skip_binder().len()..]; + let extra_args = &args[sig.inputs().extract(<[_]>::len)..]; let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| { let op_ty = op_arg.node.ty(self.mir, bx.tcx()); self.monomorphize(op_ty) diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index ca0993f05802c..0937876b412ad 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -1,7 +1,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::Symbol; use {rustc_attr as attr, rustc_hir as hir}; @@ -77,7 +77,7 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { if cfg!(debug_assertions) && stab.promotable { let sig = tcx.fn_sig(def_id); assert_eq!( - sig.skip_binder().safety(), + sig.extract(ty::Binder::safety), hir::Safety::Safe, "don't mark const unsafe fns as promotable", // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682 diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 97f3f1c8ef27b..7ac0c588fb472 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -650,7 +650,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { for &assoc_item in assoc_items.in_definition_order() { match assoc_item.kind { ty::AssocKind::Fn => { - let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi(); + let abi = tcx.fn_sig(assoc_item.def_id).extract(ty::Binder::abi); forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi); } ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 7a56b3784f8b3..ffcfc6761ee38 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1377,8 +1377,8 @@ fn compare_number_of_method_arguments<'tcx>( ) -> Result<(), ErrorGuaranteed> { let impl_m_fty = tcx.fn_sig(impl_m.def_id); let trait_m_fty = tcx.fn_sig(trait_m.def_id); - let trait_number_args = trait_m_fty.skip_binder().inputs().skip_binder().len(); - let impl_number_args = impl_m_fty.skip_binder().inputs().skip_binder().len(); + let trait_number_args = trait_m_fty.skip_binder().inputs().extract(<[_]>::len); + let impl_number_args = impl_m_fty.skip_binder().inputs().extract(<[_]>::len); if trait_number_args != impl_number_args { let trait_span = trait_m diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 06317a3b3049c..6d852f90ccbe3 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -80,7 +80,7 @@ fn equate_intrinsic_type<'tcx>( /// Returns the unsafety of the given intrinsic. pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety { let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) { - tcx.fn_sig(intrinsic_id).skip_binder().safety() + tcx.fn_sig(intrinsic_id).extract(ty::Binder::safety) } else { match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) { true => hir::Safety::Safe, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d70e8673c5203..34597db474f90 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -250,7 +250,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Impl(impl_) => { let header = tcx.impl_trait_header(def_id); let is_auto = header - .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id)); + .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.extract(|tr| tr.def_id))); crate::impl_wf_check::check_impl_wf(tcx, def_id)?; let mut res = Ok(()); diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 04770469132bb..ff9cae2a98765 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -296,7 +296,7 @@ fn orphan_check<'tcx>( debug!(trait_ref = ?trait_ref.skip_binder()); // If the *trait* is local to the crate, ok. - if let Some(def_id) = trait_ref.skip_binder().def_id.as_local() { + if let Some(def_id) = trait_ref.extract(|tr| tr.def_id).as_local() { debug!("trait {def_id:?} is local to current crate"); return Ok(()); } diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 1ccb7faaf3053..25fdc7eabba9b 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -492,7 +492,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>( let sig_id = tcx.hir().opt_delegation_sig_id(def_id).unwrap(); let caller_sig = tcx.fn_sig(sig_id); if let Err(err) = check_constraints(tcx, def_id, sig_id) { - let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1; + let sig_len = caller_sig.instantiate_identity().extract(|sig| sig.inputs().len()) + 1; let err_type = Ty::new_error(tcx, err); return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type)); } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 0355adfcb11e1..31f1eda45c009 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -94,7 +94,7 @@ pub(super) fn check_min_specialization( fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option { let trait_ref = tcx.impl_trait_ref(impl1_def_id)?; - let trait_def = tcx.trait_def(trait_ref.skip_binder().def_id); + let trait_def = tcx.trait_def(trait_ref.extract(|tr| tr.def_id)); let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?; diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index c2377b4781c28..dc0711e76cce9 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -81,7 +81,7 @@ pub(super) fn infer_predicates( // items. let item_predicates_len: usize = global_inferred_outlives .get(&item_did.to_def_id()) - .map_or(0, |p| p.as_ref().skip_binder().len()); + .map_or(0, |p| p.extract_ref(|p| p.len())); if item_required_predicates.len() > item_predicates_len { predicates_added = true; global_inferred_outlives @@ -181,7 +181,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( let args = ex_trait_ref.with_self_ty(tcx, tcx.types.usize).skip_binder().args; check_explicit_predicates( tcx, - ex_trait_ref.skip_binder().def_id, + ex_trait_ref.extract(|tr| tr.def_id), args, required_predicates, explicit_map, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index fd6ac7de14a7c..7b42d6ce0910e 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -688,7 +688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // expect. if expected_sig.sig.c_variadic() != decl.c_variadic { return self.sig_of_closure_no_expectation(expr_def_id, decl, closure_kind); - } else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 { + } else if expected_sig.sig.inputs().extract(<[_]>::len) != decl.inputs.len() { return self.sig_of_closure_with_mismatched_number_of_arguments( expr_def_id, decl, diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 3399a9fe88078..95638755744be 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1009,7 +1009,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match method.kind { ty::AssocKind::Fn => { method.fn_has_self_parameter - && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len() + && self.tcx.fn_sig(method.def_id).skip_binder().inputs().extract(<[_]>::len) == 1 } _ => false, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index da231acbb0f64..669440974fffd 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -745,7 +745,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // ``` // // to work in stable even if the Sized bound on `drop` is relaxed. - for i in 0..fn_sig.inputs().skip_binder().len() { + for i in 0..fn_sig.inputs().extract(<[_]>::len) { // We just want to check sizedness, so instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. @@ -2330,7 +2330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !self.can_eq(self.param_env, ret_ty, adt_ty) { return None; } - let input_len = fn_sig.inputs().skip_binder().len(); + let input_len = fn_sig.inputs().extract(<[_]>::len); let order = !item.name.as_str().starts_with("new"); Some((order, item.name, input_len)) }) diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 69b9be0027682..9da17e0456efc 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) .map(|pick| { let sig = self.tcx.fn_sig(pick.item.def_id); - sig.skip_binder().inputs().skip_binder().len().saturating_sub(1) + sig.skip_binder().inputs().extract(<[_]>::len).saturating_sub(1) }) .unwrap_or(0); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index eaf40a193a634..86ce957ba0209 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1987,7 +1987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the impl, if local to crate (item may be defaulted), else nothing. let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; - self.associated_value(impl_trait_ref.skip_binder().def_id, item_name) + self.associated_value(impl_trait_ref.extract(|tr| tr.def_id), item_name) }) else { continue; }; diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 88982661c8f7a..14686d41e22ba 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -387,10 +387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let num_args = args .as_coroutine_closure() .coroutine_closure_sig() - .skip_binder() - .tupled_inputs_ty - .tuple_fields() - .len(); + .extract(|sig| sig.tupled_inputs_ty.tuple_fields().len()); let typeck_results = self.typeck_results.borrow(); let tupled_upvars_ty_for_borrow = Ty::new_tup_from_iter( diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 1d3d32ef74979..cdc3d50c4a84e 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -15,8 +15,10 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::traverse::AlwaysTraversable; use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; +use rustc_type_ir::traverse::OptTryFoldWith; use tracing::{debug, instrument}; use crate::infer::canonical::instantiate::{CanonicalExt, instantiate_value}; @@ -60,7 +62,7 @@ impl<'tcx> InferCtxt<'tcx> { fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>, ) -> Result, NoSolution> where - T: Debug + TypeFoldable>, + T: OptTryFoldWith>, Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, { let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?; @@ -107,7 +109,7 @@ impl<'tcx> InferCtxt<'tcx> { fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>, ) -> Result, NoSolution> where - T: Debug + TypeFoldable>, + T: OptTryFoldWith>, { let tcx = self.tcx; @@ -243,7 +245,7 @@ impl<'tcx> InferCtxt<'tcx> { output_query_region_constraints: &mut QueryRegionConstraints<'tcx>, ) -> InferResult<'tcx, R> where - R: Debug + TypeFoldable>, + R: OptTryFoldWith>, { let InferOk { value: result_args, mut obligations } = self .query_response_instantiation_guess( @@ -326,8 +328,11 @@ impl<'tcx> InferCtxt<'tcx> { .map(|p_c| instantiate_value(self.tcx, &result_args, p_c.clone())), ); - let user_result: R = - query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone()); + let user_result: R = query_response + .instantiate_projected(self.tcx, &result_args, |q_r| { + AlwaysTraversable(q_r.value.clone()) + }) + .0; Ok(InferOk { value: user_result, obligations }) } @@ -396,7 +401,7 @@ impl<'tcx> InferCtxt<'tcx> { query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>, ) -> InferResult<'tcx, CanonicalVarValues<'tcx>> where - R: Debug + TypeFoldable>, + R: OptTryFoldWith>, { // For each new universe created in the query result that did // not appear in the original query, create a local diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index ac641ef565228..62e4d874b8e29 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -171,7 +171,7 @@ impl<'tcx, O> Obligation<'tcx, O> { impl<'tcx> PolyTraitObligation<'tcx> { pub fn polarity(&self) -> ty::PredicatePolarity { - self.predicate.skip_binder().polarity + self.predicate.extract(|p| p.polarity) } pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> { diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 31f585c0c9edd..e185feba26db9 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -4,6 +4,7 @@ use rustc_ast_ir::try_visit; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, TyCtxt}; +use rustc_type_ir::traverse::{ImportantTypeTraversal, TypeTraversable}; use crate::traits; use crate::traits::project::Normalized; @@ -55,6 +56,11 @@ impl<'tcx, O: TypeFoldable>> TypeFoldable> } } +impl<'tcx, O: TypeVisitable>> TypeTraversable> + for traits::Obligation<'tcx, O> +{ + type Kind = ImportantTypeTraversal; +} impl<'tcx, O: TypeVisitable>> TypeVisitable> for traits::Obligation<'tcx, O> { diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index f46c795b9565c..b3e491c651a93 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -17,6 +17,7 @@ mod diagnostics; mod extension; mod hash_stable; mod lift; +mod noop_type_traversable; mod query; mod serialize; mod symbols; @@ -81,27 +82,9 @@ 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)] => - /// 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!([NoopTypeTraversable] => noop_type_traversable::noop_type_traversable_derive); +decl_derive!([TypeVisitable] => type_visitable::type_visitable_derive); +decl_derive!([TypeFoldable] => type_foldable::type_foldable_derive); decl_derive!([Lift, attributes(lift)] => lift::lift_derive); decl_derive!( [Diagnostic, attributes( diff --git a/compiler/rustc_macros/src/noop_type_traversable.rs b/compiler/rustc_macros/src/noop_type_traversable.rs new file mode 100644 index 0000000000000..eeb4bd2bc5863 --- /dev/null +++ b/compiler/rustc_macros/src/noop_type_traversable.rs @@ -0,0 +1,39 @@ +use quote::quote; +use syn::parse_quote; + +pub(super) fn noop_type_traversable_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { + if let syn::Data::Union(_) = s.ast().data { + panic!("cannot derive on union") + } + + s.underscore_const(true); + + if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + s.add_impl_generic(parse_quote! { 'tcx }); + } + + s.add_bounds(synstructure::AddBounds::None); + let mut where_clauses = None; + s.add_trait_bounds( + &parse_quote!( + ::rustc_middle::ty::traverse::TypeTraversable< + ::rustc_middle::ty::TyCtxt<'tcx>, + Kind = ::rustc_middle::ty::traverse::NoopTypeTraversal, + > + ), + &mut where_clauses, + synstructure::AddBounds::Fields, + ); + for pred in where_clauses.into_iter().flat_map(|c| c.predicates) { + s.add_where_predicate(pred); + } + + s.bound_impl( + quote!(::rustc_middle::ty::traverse::TypeTraversable<::rustc_middle::ty::TyCtxt<'tcx>>), + quote! { + type Kind = ::rustc_middle::ty::traverse::NoopTypeTraversal; + }, + ) +} diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index bc3b82c2893fa..afea1089a9401 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -1,4 +1,4 @@ -use quote::{ToTokens, quote}; +use quote::quote; use syn::parse_quote; pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { @@ -12,34 +12,25 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m s.add_impl_generic(parse_quote! { 'tcx }); } - s.add_bounds(synstructure::AddBounds::Generics); + s.add_bounds(synstructure::AddBounds::None); + let mut where_clauses = None; + s.add_trait_bounds( + &parse_quote!(::rustc_type_ir::traverse::OptTryFoldWith<::rustc_middle::ty::TyCtxt<'tcx>>), + &mut where_clauses, + synstructure::AddBounds::Fields, + ); + s.add_where_predicate(parse_quote! { Self: std::fmt::Debug + Clone }); + for pred in where_clauses.into_iter().flat_map(|c| c.predicates) { + s.add_where_predicate(pred); + } + s.bind_with(|_| synstructure::BindStyle::Move); let body_fold = s.each_variant(|vi| { let bindings = vi.bindings(); vi.construct(|_, index| { let bind = &bindings[index]; - - let mut fixed = false; - - // retain value of fields with #[type_foldable(identity)] - bind.ast().attrs.iter().for_each(|x| { - if !x.path().is_ident("type_foldable") { - return; - } - let _ = x.parse_nested_meta(|nested| { - if nested.path.is_ident("identity") { - fixed = true; - } - Ok(()) - }); - }); - - if fixed { - bind.to_token_stream() - } else { - quote! { - ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)? - } + quote! { + ::rustc_middle::ty::traverse::OptTryFoldWith::mk_try_fold_with()(#bind, __folder)? } }) }); diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index 527ca26c0eb10..24850dbdb4071 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -10,34 +10,30 @@ pub(super) fn type_visitable_derive( s.underscore_const(true); - // ignore fields with #[type_visitable(ignore)] - s.filter(|bi| { - let mut ignored = false; - - bi.ast().attrs.iter().for_each(|attr| { - if !attr.path().is_ident("type_visitable") { - return; - } - let _ = attr.parse_nested_meta(|nested| { - if nested.path.is_ident("ignore") { - ignored = true; - } - Ok(()) - }); - }); - - !ignored - }); - if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { s.add_impl_generic(parse_quote! { 'tcx }); } - s.add_bounds(synstructure::AddBounds::Generics); + s.add_bounds(synstructure::AddBounds::None); + let mut where_clauses = None; + s.add_trait_bounds( + &parse_quote!( + ::rustc_middle::ty::traverse::OptVisitWith::<::rustc_middle::ty::TyCtxt<'tcx>> + ), + &mut where_clauses, + synstructure::AddBounds::Fields, + ); + s.add_where_predicate(parse_quote! { Self: std::fmt::Debug + Clone }); + for pred in where_clauses.into_iter().flat_map(|c| c.predicates) { + s.add_where_predicate(pred); + } + + let impl_traversable_s = s.clone(); + let body_visit = s.each(|bind| { quote! { match ::rustc_ast_ir::visit::VisitorResult::branch( - ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor) + ::rustc_middle::ty::traverse::OptVisitWith::mk_visit_with()(#bind, __visitor) ) { ::core::ops::ControlFlow::Continue(()) => {}, ::core::ops::ControlFlow::Break(r) => { @@ -48,7 +44,7 @@ pub(super) fn type_visitable_derive( }); s.bind_with(|_| synstructure::BindStyle::Move); - s.bound_impl( + let visitable_impl = s.bound_impl( quote!(::rustc_middle::ty::visit::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>), quote! { fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( @@ -59,5 +55,17 @@ pub(super) fn type_visitable_derive( <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output() } }, - ) + ); + + let traversable_impl = impl_traversable_s.bound_impl( + quote!(::rustc_middle::ty::traverse::TypeTraversable<::rustc_middle::ty::TyCtxt<'tcx>>), + quote! { + type Kind = ::rustc_middle::ty::traverse::ImportantTypeTraversal; + }, + ); + + quote! { + #visitable_impl + #traversable_impl + } } diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 4c7af0bc3726d..ceaa74156cd98 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -1,12 +1,14 @@ use rustc_hir::HirId; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{ + HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; use rustc_target::abi::{FieldIdx, VariantIdx}; use crate::ty; use crate::ty::Ty; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(NoopTypeTraversable)] pub enum PlaceBase { /// A temporary variable. Rvalue, @@ -19,7 +21,7 @@ pub enum PlaceBase { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(NoopTypeTraversable)] pub enum ProjectionKind { /// A dereference of a pointer, reference or `Box` of the given type. Deref, diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 39816c17b985f..8e3427e941dd1 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -73,32 +73,8 @@ macro_rules! TrivialLiftImpls { macro_rules! TrivialTypeTraversalImpls { ($($ty:ty),+ $(,)?) => { $( - impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty { - fn try_fold_with>>( - self, - _: &mut F, - ) -> ::std::result::Result { - Ok(self) - } - - #[inline] - fn fold_with>>( - self, - _: &mut F, - ) -> Self { - self - } - } - - impl<'tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty { - #[inline] - fn visit_with>>( - &self, - _: &mut F) - -> F::Result - { - ::output() - } + impl<'tcx> $crate::ty::traverse::TypeTraversable<$crate::ty::TyCtxt<'tcx>> for $ty { + type Kind = $crate::ty::traverse::NoopTypeTraversal; } )+ }; diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 4a876dc1228e5..d66d25a5af815 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -3,7 +3,7 @@ use std::fmt::{self, Debug, Formatter}; use rustc_index::IndexVec; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{HashStable, NoopTypeTraversable, TyDecodable, TyEncodable}; use rustc_span::{Span, Symbol}; rustc_index::newtype_index! { @@ -77,7 +77,7 @@ impl ConditionId { /// but the zero/counter/expression distinction is also useful for representing /// the value of code/gap mappings, and the true/false arms of branch mappings. #[derive(Copy, Clone, PartialEq, Eq)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub enum CovTerm { Zero, Counter(CounterId), @@ -94,7 +94,7 @@ impl Debug for CovTerm { } } -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub enum CoverageKind { /// Marks a span that might otherwise not be represented in MIR, so that /// coverage instrumentation can associate it with its enclosing block/BCB. @@ -155,8 +155,8 @@ impl Debug for CoverageKind { } } -#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] +#[derive(TyEncodable, TyDecodable, NoopTypeTraversable)] pub struct SourceRegion { pub file_name: Symbol, pub start_line: u32, @@ -176,7 +176,7 @@ impl Debug for SourceRegion { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] -#[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, NoopTypeTraversable)] pub enum Op { Subtract, Add, @@ -193,7 +193,7 @@ impl Op { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct Expression { pub lhs: CovTerm, pub op: Op, @@ -201,7 +201,7 @@ pub struct Expression { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub enum MappingKind { /// Associates a normal region of code with a counter/expression/zero. Code(CovTerm), @@ -233,7 +233,7 @@ impl MappingKind { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct Mapping { pub kind: MappingKind, pub source_region: SourceRegion, @@ -243,7 +243,7 @@ pub struct Mapping { /// to be used in conjunction with the individual coverage statements injected /// into the function's basic blocks. #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct FunctionCoverageInfo { pub function_source_hash: u64, pub num_counters: usize, @@ -262,7 +262,7 @@ pub struct FunctionCoverageInfo { /// ("Hi" indicates that this is "high-level" information collected at the /// THIR/MIR boundary, before the MIR-based coverage instrumentation pass.) #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct CoverageInfoHi { /// 1 more than the highest-numbered [`CoverageKind::BlockMarker`] that was /// injected into the MIR body. This makes it possible to allocate per-ID @@ -276,7 +276,7 @@ pub struct CoverageInfoHi { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct BranchSpan { pub span: Span, pub true_marker: BlockMarkerId, @@ -284,7 +284,7 @@ pub struct BranchSpan { } #[derive(Copy, Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct ConditionInfo { pub condition_id: ConditionId, pub true_next_id: Option, @@ -292,7 +292,7 @@ pub struct ConditionInfo { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct MCDCBranchSpan { pub span: Span, pub condition_info: ConditionInfo, @@ -301,14 +301,14 @@ pub struct MCDCBranchSpan { } #[derive(Copy, Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct DecisionInfo { pub bitmap_idx: u32, pub num_conditions: u16, } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, NoopTypeTraversable)] pub struct MCDCDecisionSpan { pub span: Span, pub end_markers: Vec, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index cd148aef29ba8..30bdf7a004e06 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -22,7 +22,9 @@ use rustc_hir::{ }; use rustc_index::bit_set::BitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{ + HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; @@ -1548,7 +1550,7 @@ pub struct SourceScopeLocalData { /// The first will lead to the constraint `w: &'1 str` (for some /// inferred region `'1`). The second will lead to the constraint `w: /// &'static str`. -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, NoopTypeTraversable)] pub struct UserTypeProjections { pub contents: Vec<(UserTypeProjection, Span)>, } @@ -1627,7 +1629,7 @@ impl<'tcx> UserTypeProjections { /// `field[0]` (aka `.0`), indicating that the type of `s` is /// determined by finding the type of the `.0` field from `T`. #[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(NoopTypeTraversable)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, pub projs: Vec, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 70331214ac5a8..3c7fa39c6694c 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -9,7 +9,9 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::BitMatrix; use rustc_index::{Idx, IndexVec}; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{ + HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; use rustc_span::Span; use rustc_span::symbol::Symbol; use rustc_target::abi::{FieldIdx, VariantIdx}; @@ -57,8 +59,6 @@ pub struct CoroutineLayout<'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, } @@ -278,7 +278,7 @@ pub enum ConstraintCategory<'tcx> { } #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] +#[derive(TyEncodable, TyDecodable, HashStable, NoopTypeTraversable)] pub enum ReturnConstraint { Normal, ClosureUpvar(FieldIdx), diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index c610fac80f68f..cdfc1effb4553 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -8,7 +8,9 @@ use rustc_data_structures::packed::Pu128; use rustc_hir::CoroutineKind; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{ + HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Spanned; @@ -581,8 +583,8 @@ pub struct CopyNonOverlapping<'tcx> { /// Represents how a [`TerminatorKind::Call`] was constructed. /// Used only for diagnostics. -#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable)] +#[derive(TyEncodable, TyDecodable, NoopTypeTraversable)] pub enum CallSource { /// This came from something such as `a > b` or `a + b`. In THIR, if `from_hir_call` /// is false then this is the desugaring. @@ -605,8 +607,8 @@ impl CallSource { } } -#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(Clone, Copy, Debug, Hash, HashStable, PartialEq)] +#[derive(TyEncodable, TyDecodable, NoopTypeTraversable)] /// The macro that an inline assembly block was created by pub enum InlineAsmMacro { /// The `asm!` macro @@ -951,8 +953,8 @@ pub struct SwitchTargets { } /// Action to be taken when a stack unwind happens. -#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(TyEncodable, TyDecodable, NoopTypeTraversable)] pub enum UnwindAction { /// No action is to be taken. Continue unwinding. /// @@ -970,8 +972,8 @@ pub enum UnwindAction { } /// The reason we are terminating the process during unwinding. -#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(TyEncodable, TyDecodable, NoopTypeTraversable)] pub enum UnwindTerminateReason { /// Unwinding is just not possible given the ABI of this function. Abi, @@ -1501,8 +1503,8 @@ pub enum NullOp<'tcx> { UbChecks, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(TyEncodable, TyDecodable, NoopTypeTraversable)] pub enum UnOp { /// The `!` operator for logical inversion Not, @@ -1519,8 +1521,8 @@ pub enum UnOp { PtrMetadata, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(TyEncodable, TyDecodable, NoopTypeTraversable)] pub enum BinOp { /// The `+` operator (addition) Add, diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index b798f0788007f..178b6767ce8ca 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -1,7 +1,5 @@ //! `TypeFoldable` implementations for MIR types - -use rustc_ast::InlineAsmTemplatePiece; -use rustc_hir::def_id::LocalDefId; +use rustc_index::bit_set::BitMatrix; use super::*; @@ -20,6 +18,7 @@ TrivialTypeTraversalImpls! { SwitchTargets, CoroutineKind, CoroutineSavedLocal, + BitMatrix, } TrivialTypeTraversalImpls! { @@ -27,33 +26,6 @@ TrivialTypeTraversalImpls! { NullOp<'tcx>, } -impl<'tcx> TypeFoldable> for &'tcx [InlineAsmTemplatePiece] { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeFoldable> for &'tcx [Span] { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeFoldable> for &'tcx ty::List { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - impl<'tcx> TypeFoldable> for &'tcx ty::List> { fn try_fold_with>>( self, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index fe865b8a51508..9173a7518a4b5 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -17,7 +17,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; use rustc_index::{IndexVec, newtype_index}; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable}; +use rustc_macros::{HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeVisitable}; use rustc_middle::middle::region; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; @@ -234,7 +234,8 @@ pub enum StmtKind<'tcx> { }, } -#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable)] +#[derive(NoopTypeTraversable, TyEncodable, TyDecodable)] pub struct LocalVarId(pub HirId); /// A THIR expression. @@ -739,9 +740,7 @@ pub enum PatKind<'tcx> { /// `x`, `ref x`, `x @ P`, etc. Binding { name: Symbol, - #[type_visitable(ignore)] mode: BindingMode, - #[type_visitable(ignore)] var: LocalVarId, ty: Ty<'tcx>, subpattern: Option>>, @@ -844,7 +843,6 @@ pub struct PatRange<'tcx> { pub lo: PatRangeBoundary<'tcx>, /// Must not be `NegInfinity`. pub hi: PatRangeBoundary<'tcx>, - #[type_visitable(ignore)] pub end: RangeEnd, pub ty: Ty<'tcx>, } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 8ee8b4c4823a8..9fcd6af334084 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -17,7 +17,8 @@ use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def_id::DefId; use rustc_macros::{ - Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, + Decodable, Encodable, HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeFoldable, + TypeVisitable, }; use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_span::symbol::Symbol; @@ -422,7 +423,7 @@ crate::TrivialTypeTraversalAndLiftImpls! { /// we can walk in order to obtain precise spans for any /// 'nested' types (e.g. `Foo` in `Option`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)] -#[derive(TypeVisitable, TypeFoldable)] +#[derive(NoopTypeTraversable)] pub enum WellFormedLoc { /// Use the type of the provided definition. Ty(LocalDefId), diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index f659bf8125a0e..e538c3839320a 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,8 +1,9 @@ use rustc_ast_ir::try_visit; use rustc_data_structures::intern::Interned; use rustc_macros::HashStable; -use rustc_type_ir as ir; pub use rustc_type_ir::solve::*; +use rustc_type_ir::traverse::{ImportantTypeTraversal, TypeTraversable}; +use rustc_type_ir::{self as ir}; use crate::ty::{ self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, @@ -72,6 +73,9 @@ impl<'tcx> TypeFoldable> for ExternalConstraints<'tcx> { } } +impl<'tcx> TypeTraversable> for ExternalConstraints<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for ExternalConstraints<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { try_visit!(self.region_constraints.visit_with(visitor)); @@ -106,6 +110,9 @@ impl<'tcx> TypeFoldable> for PredefinedOpaques<'tcx> { } } +impl<'tcx> TypeTraversable> for PredefinedOpaques<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for PredefinedOpaques<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { self.opaque_types.visit_with(visitor) diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 002d381962124..196a7b362ec68 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -1,7 +1,7 @@ //! A subset of a mir body used for const evaluability checking. use rustc_errors::ErrorGuaranteed; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable}; +use rustc_macros::{HashStable, NoopTypeTraversable, TyDecodable, TyEncodable}; use crate::ty::{ self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -9,7 +9,7 @@ use crate::ty::{ }; #[derive(Hash, Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq)] -#[derive(TyDecodable, TyEncodable, HashStable, TypeVisitable, TypeFoldable)] +#[derive(TyDecodable, TyEncodable, HashStable, NoopTypeTraversable)] pub enum CastKind { /// thir::ExprKind::As As, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 3322a2643d7d3..c32ba563816f4 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -13,7 +13,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem}; use rustc_index::{IndexSlice, IndexVec}; -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use rustc_macros::{HashStable, NoopTypeTraversable, TyDecodable, TyEncodable}; use rustc_query_system::ich::StableHashingContext; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; @@ -168,7 +168,7 @@ impl<'a> HashStable> for AdtDefData { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable, NoopTypeTraversable)] #[rustc_pass_by_value] pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>); diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 9ee8294291123..b50cbeccf6347 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -5,7 +5,9 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def_id::LocalDefId; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{ + HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; use rustc_span::def_id::LocalDefIdMap; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; @@ -23,7 +25,7 @@ use crate::{mir, ty}; pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::from_u32(1); #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(NoopTypeTraversable)] pub struct UpvarPath { pub hir_id: HirId, } @@ -32,7 +34,7 @@ pub struct UpvarPath { /// the original var ID (that is, the root variable that is referenced /// by the upvar) and the ID of the closure expression. #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(NoopTypeTraversable)] pub struct UpvarId { pub var_path: UpvarPath, pub closure_expr_id: LocalDefId, @@ -47,7 +49,7 @@ impl UpvarId { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. #[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable, Hash)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(NoopTypeTraversable)] pub enum UpvarCapture { /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases @@ -252,7 +254,7 @@ pub fn is_ancestor_or_same_capture( /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. #[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable, Hash)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive(NoopTypeTraversable)] pub struct CaptureInfo { /// Expr Id pointing to use that resulted in selecting the current capture kind /// diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 91b764ae1d451..8bd3f57ec2c26 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,6 +1,9 @@ use std::assert_matches::assert_matches; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, extension}; +use rustc_macros::{ + HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, + extension, +}; use super::Const; use crate::mir; @@ -42,7 +45,7 @@ impl<'tcx> ty::UnevaluatedConst<'tcx> { } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] +#[derive(HashStable, TyEncodable, TyDecodable, NoopTypeTraversable)] pub enum ExprKind { Binop(mir::BinOp), UnOp(mir::UnOp), diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 9f9bf41c3355a..e3bad806d153f 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -1,11 +1,11 @@ -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use rustc_macros::{HashStable, NoopTypeTraversable, TyDecodable, TyEncodable}; use super::ScalarInt; use crate::mir::interpret::Scalar; use crate::ty::{self, Ty, TyCtxt}; #[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq)] -#[derive(HashStable)] +#[derive(HashStable, NoopTypeTraversable)] /// This datastructure is used to represent the value of constants used in the type system. /// /// We explicitly choose a different datastructure from the way values are processed within diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index daf1362e25c1f..7f6edb0a61c76 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -14,6 +14,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, extension}; use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; +use rustc_type_ir::traverse::{ImportantTypeTraversal, TypeTraversable}; use smallvec::SmallVec; use crate::ty::codec::{TyDecoder, TyEncoder}; @@ -329,6 +330,9 @@ impl<'tcx> TypeFoldable> for GenericArg<'tcx> { } } +impl<'tcx> TypeTraversable> for GenericArg<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for GenericArg<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { match self.unpack() { @@ -642,6 +646,9 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { } } +impl<'tcx, T: TypeTraversable>> TypeTraversable> for &'tcx ty::List { + type Kind = T::Kind; +} impl<'tcx, T: TypeVisitable>> TypeVisitable> for &'tcx ty::List { #[inline] fn visit_with>>(&self, visitor: &mut V) -> V::Result { diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index b1c5ff50fdc86..ef4a092c4b4e6 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -656,7 +656,7 @@ impl<'tcx> Instance<'tcx> { ) -> Instance<'tcx> { debug!("resolve_for_vtable(def_id={:?}, args={:?})", def_id, args); let fn_sig = tcx.fn_sig(def_id).instantiate_identity(); - let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty() + let is_vtable_shim = !fn_sig.inputs().extract(<[_]>::is_empty) && fn_sig.input(0).skip_binder().is_param(0) && tcx.generics_of(def_id).has_self; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ed24fcc7eb88a..ca2876f29984b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -55,8 +55,10 @@ pub use rustc_type_ir::ConstKind::{ Placeholder as PlaceholderCt, Unevaluated, Value, }; pub use rustc_type_ir::relate::VarianceDiagInfo; +use rustc_type_ir::traverse::TypeTraversable; pub use rustc_type_ir::*; use tracing::{debug, instrument}; +use traverse::ImportantTypeTraversal; pub use vtable::*; use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; @@ -272,7 +274,6 @@ pub enum ImplSubject<'tcx> { } #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] -#[derive(TypeFoldable, TypeVisitable)] pub enum Asyncness { Yes, No, @@ -547,6 +548,9 @@ impl<'tcx> TypeFoldable> for Term<'tcx> { } } +impl<'tcx> TypeTraversable> for Term<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for Term<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { match self.unpack() { @@ -1031,15 +1035,18 @@ impl<'tcx> TypeFoldable> for ParamEnv<'tcx> { ) -> Result { Ok(ParamEnv::new( self.caller_bounds().try_fold_with(folder)?, - self.reveal().try_fold_with(folder)?, + self.reveal().noop_try_fold_with(folder)?, )) } } +impl<'tcx> TypeTraversable> for ParamEnv<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for ParamEnv<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { try_visit!(self.caller_bounds().visit_with(visitor)); - self.reveal().visit_with(visitor) + self.reveal().noop_visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 4872d8c89eb84..defadc7993c5f 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -11,6 +11,7 @@ use rustc_hir::def::Namespace; use rustc_span::source_map::Spanned; use rustc_target::abi::TyAndLayout; use rustc_type_ir::ConstKind; +use rustc_type_ir::traverse::{ImportantTypeTraversal, TypeTraversable}; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Pattern, Region}; @@ -18,7 +19,7 @@ use crate::mir::interpret; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; +use crate::ty::{self, Lift, Term, TermKind, Ty, TyCtxt}; impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -208,10 +209,11 @@ impl<'tcx> fmt::Debug for Region<'tcx> { // For things for which the type library provides traversal implementations // for all Interners, we only need to provide a Lift implementation: TrivialLiftImpls! { - (), - bool, - usize, - u64, + (), + bool, + usize, + u64, + crate::ty::ParamConst, } // For some things about which the type library does not know, or does not @@ -224,11 +226,13 @@ TrivialTypeTraversalImpls! { ::rustc_ast::InlineAsmOptions, ::rustc_ast::InlineAsmTemplatePiece, ::rustc_ast::NodeId, + ::rustc_ast::ast::BindingMode, ::rustc_span::symbol::Symbol, ::rustc_hir::def::Res, ::rustc_hir::def_id::LocalDefId, ::rustc_hir::ByRef, ::rustc_hir::HirId, + ::rustc_hir::RangeEnd, ::rustc_hir::MatchSource, ::rustc_target::asm::InlineAsmRegOrRegClass, crate::mir::coverage::BlockMarkerId, @@ -237,7 +241,6 @@ TrivialTypeTraversalImpls! { crate::mir::coverage::ConditionId, crate::mir::Local, crate::mir::Promoted, - crate::traits::Reveal, crate::ty::adjustment::AutoBorrowMutability, crate::ty::AdtKind, crate::ty::BoundRegion, @@ -255,8 +258,6 @@ TrivialTypeTraversalImpls! { crate::ty::adjustment::PointerCoercion, ::rustc_span::Span, ::rustc_span::symbol::Ident, - ty::BoundVar, - ty::ValTree<'tcx>, } // For some things about which the type library does not know, or does not // provide any traversal implementations, we need to provide a traversal @@ -264,8 +265,9 @@ 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, crate::ty::instance::ReifyReason, interpret::AllocId, @@ -274,11 +276,6 @@ TrivialTypeTraversalAndLiftImpls! { rustc_target::abi::Size, } -TrivialLiftImpls! { - ::rustc_hir::Safety, - ::rustc_target::spec::abi::Abi, -} - /////////////////////////////////////////////////////////////////////////// // Lift implementations @@ -305,12 +302,6 @@ impl<'a, 'tcx> Lift> for Term<'a> { /////////////////////////////////////////////////////////////////////////// // Traversal implementations. -impl<'tcx> TypeVisitable> for ty::AdtDef<'tcx> { - fn visit_with>>(&self, _visitor: &mut V) -> V::Result { - V::Result::output() - } -} - impl<'tcx> TypeFoldable> for &'tcx ty::List> { fn try_fold_with>>( self, @@ -339,6 +330,9 @@ impl<'tcx> TypeFoldable> for Pattern<'tcx> { } } +impl<'tcx> TypeTraversable> for Pattern<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for Pattern<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { (**self).visit_with(visitor) @@ -354,6 +348,9 @@ impl<'tcx> TypeFoldable> for Ty<'tcx> { } } +impl<'tcx> TypeTraversable> for Ty<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for Ty<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_ty(*self) @@ -470,6 +467,9 @@ impl<'tcx> TypeFoldable> for ty::Region<'tcx> { } } +impl<'tcx> TypeTraversable> for ty::Region<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for ty::Region<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_region(*self) @@ -495,12 +495,18 @@ impl<'tcx> TypeFoldable> for ty::Clause<'tcx> { } } +impl<'tcx> TypeTraversable> for ty::Predicate<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for ty::Predicate<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(*self) } } +impl<'tcx> TypeTraversable> for ty::Clause<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for ty::Clause<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(self.as_predicate()) @@ -523,6 +529,9 @@ impl<'tcx> TypeSuperVisitable> for ty::Predicate<'tcx> { } } +impl<'tcx> TypeTraversable> for ty::Clauses<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for ty::Clauses<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_clauses(self) @@ -553,6 +562,9 @@ impl<'tcx> TypeFoldable> for ty::Const<'tcx> { } } +impl<'tcx> TypeTraversable> for ty::Const<'tcx> { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for ty::Const<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_const(*self) @@ -565,15 +577,15 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { folder: &mut F, ) -> Result { let kind = match self.kind() { - ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?), - ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?), + ConstKind::Param(p) => ConstKind::Param(p.noop_try_fold_with(folder)?), + ConstKind::Infer(i) => ConstKind::Infer(i.noop_try_fold_with(folder)?), ConstKind::Bound(d, b) => { - ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?) + ConstKind::Bound(d.noop_try_fold_with(folder)?, b.noop_try_fold_with(folder)?) } - ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?), + ConstKind::Placeholder(p) => ConstKind::Placeholder(p.noop_try_fold_with(folder)?), ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), ConstKind::Value(t, v) => { - ConstKind::Value(t.try_fold_with(folder)?, v.try_fold_with(folder)?) + ConstKind::Value(t.try_fold_with(folder)?, v.noop_try_fold_with(folder)?) } ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), @@ -585,17 +597,17 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { match self.kind() { - ConstKind::Param(p) => p.visit_with(visitor), - ConstKind::Infer(i) => i.visit_with(visitor), + ConstKind::Param(p) => p.noop_visit_with(visitor), + ConstKind::Infer(i) => i.noop_visit_with(visitor), ConstKind::Bound(d, b) => { - try_visit!(d.visit_with(visitor)); - b.visit_with(visitor) + try_visit!(d.noop_visit_with(visitor)); + b.noop_visit_with(visitor) } - ConstKind::Placeholder(p) => p.visit_with(visitor), + ConstKind::Placeholder(p) => p.noop_visit_with(visitor), ConstKind::Unevaluated(uv) => uv.visit_with(visitor), ConstKind::Value(t, v) => { try_visit!(t.visit_with(visitor)); - v.visit_with(visitor) + v.noop_visit_with(visitor) } ConstKind::Error(e) => e.visit_with(visitor), ConstKind::Expr(e) => e.visit_with(visitor), @@ -603,6 +615,9 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { } } +impl<'tcx> TypeTraversable> for rustc_span::ErrorGuaranteed { + type Kind = ImportantTypeTraversal; +} impl<'tcx> TypeVisitable> for rustc_span::ErrorGuaranteed { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_error(*self) @@ -618,33 +633,26 @@ impl<'tcx> TypeFoldable> for rustc_span::ErrorGuaranteed { } } -impl<'tcx> TypeFoldable> for InferConst { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeVisitable> for InferConst { - fn visit_with>>(&self, _visitor: &mut V) -> V::Result { - V::Result::output() - } +impl<'tcx> TypeTraversable> for TyAndLayout<'tcx, Ty<'tcx>> { + type Kind = ImportantTypeTraversal; } - impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_ty(self.ty) } } +impl<'tcx, T: TypeVisitable> + Debug + Clone> TypeTraversable> + for Spanned +{ + type Kind = ImportantTypeTraversal; +} impl<'tcx, T: TypeVisitable> + Debug + Clone> TypeVisitable> for Spanned { fn visit_with>>(&self, visitor: &mut V) -> V::Result { try_visit!(self.node.visit_with(visitor)); - self.span.visit_with(visitor) + self.span.noop_visit_with(visitor) } } @@ -657,7 +665,7 @@ impl<'tcx, T: TypeFoldable> + Debug + Clone> TypeFoldable Result { Ok(Spanned { node: self.node.try_fold_with(folder)?, - span: self.span.try_fold_with(folder)?, + span: self.span.noop_try_fold_with(folder)?, }) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d8362ccc0a97c..b46716bcb29ea 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -13,7 +13,9 @@ use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension}; +use rustc_macros::{ + HashStable, NoopTypeTraversable, TyDecodable, TyEncodable, TypeFoldable, extension, +}; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{DUMMY_SP, Span}; use rustc_target::abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; @@ -323,7 +325,7 @@ impl<'tcx> ParamTy { } #[derive(Copy, Clone, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)] -#[derive(HashStable)] +#[derive(HashStable, NoopTypeTraversable)] pub struct ParamConst { pub index: u32, pub name: Symbol, diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index cb9a4e2604e25..8554fee68eb1b 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -73,7 +73,7 @@ pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { && drop_trait == trait_ref.instantiate_identity().def_id // avoid erroneous `Drop` impls from causing ICEs below && let sig = tcx.fn_sig(def_id).instantiate_identity() - && sig.inputs().skip_binder().len() == 1 + && sig.inputs().extract(<[_]>::len) == 1 { // It was. Now figure out for what type `Drop` is implemented and then // check for recursion. diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index e55aeeac6e069..be97749dcc68b 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -173,7 +173,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { let ty_params = fn_args.types().map(|ty| format!("{ty}")); let const_params = fn_args.consts().map(|c| format!("{c}")); let params = ty_params.chain(const_params).join(", "); - let num_args = fn_sig.inputs().map_bound(|inputs| inputs.len()).skip_binder(); + let num_args = fn_sig.inputs().extract(<[_]>::len); let variadic = if fn_sig.c_variadic() { ", ..." } else { "" }; let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" }; let sugg = format!( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index e2fd0dd2a25fa..021408bd21e8e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -15,6 +15,7 @@ use rustc_index::IndexVec; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::solver_relating::RelateExt; +use rustc_type_ir::traverse::OptTryFoldWith; use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner}; use tracing::{debug, instrument, trace}; @@ -426,7 +427,7 @@ pub(in crate::solve) fn make_canonical_state( where D: SolverDelegate, I: Interner, - T: TypeFoldable, + T: OptTryFoldWith, { let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) }; let state = inspect::State { var_values, data }; @@ -441,7 +442,7 @@ where // FIXME: needs to be pub to be accessed by downstream // `rustc_trait_selection::solve::inspect::analyse`. -pub fn instantiate_canonical_state>( +pub fn instantiate_canonical_state>( delegate: &D, span: D::Span, param_env: I::ParamEnv, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 250174e033e3a..6ed9fc70ebfbc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -11,7 +11,6 @@ use rustc_type_ir::relate::Relate; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner}; -use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::{instrument, trace}; use crate::coherence; @@ -91,7 +90,6 @@ where } #[derive_where(Clone, Debug, Default; I: Interner)] -#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] struct NestedGoals { /// These normalizes-to goals are treated specially during the evaluation diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index bacb3b1b1b861..ee7037f799454 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,5 +1,3 @@ -use std::fmt::Debug; - use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; pub use rustc_infer::infer::*; @@ -11,6 +9,7 @@ use rustc_middle::infer::canonical::{ use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast}; use rustc_span::DUMMY_SP; +use rustc_type_ir::traverse::OptTryFoldWith; use tracing::instrument; use crate::infer::at::ToTrace; @@ -139,7 +138,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { ) -> Result, NoSolution> where K: TypeFoldable>, - R: Debug + TypeFoldable>, + R: OptTryFoldWith>, Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, { let (infcx, key, canonical_inference_vars) = diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 5e270b62b0081..5b2115cb61d1a 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -1,5 +1,4 @@ use std::cell::RefCell; -use std::fmt::Debug; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::ErrorGuaranteed; @@ -15,6 +14,7 @@ use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::traverse::OptTryFoldWith; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast, Variance}; use rustc_type_ir::relate::Relate; @@ -259,7 +259,7 @@ impl<'tcx> ObligationCtxt<'_, 'tcx, ScrubbedTraitError<'tcx>> { answer: T, ) -> Result, NoSolution> where - T: Debug + TypeFoldable>, + T: OptTryFoldWith>, Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, { self.infcx.make_canonicalized_query_response( diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 18010603286d1..4c6d4fb8a161a 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -3,8 +3,10 @@ use std::fmt; use rustc_errors::ErrorGuaranteed; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_middle::traits::query::NoSolution; -use rustc_middle::ty::{TyCtxt, TypeFoldable}; +use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::traverse::AlwaysTraversable; use rustc_span::Span; +use rustc_type_ir::traverse::OptTryFoldWith; use tracing::info; use crate::infer::InferCtxt; @@ -29,7 +31,7 @@ impl CustomTypeOp { impl<'tcx, F, R> super::TypeOp<'tcx> for CustomTypeOp where F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result, - R: fmt::Debug + TypeFoldable>, + R: fmt::Debug + OptTryFoldWith>, { type Output = R; /// We can't do any custom error reporting for `CustomTypeOp`, so @@ -67,7 +69,7 @@ pub fn scrape_region_constraints<'tcx, Op, R>( span: Span, ) -> Result<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>), ErrorGuaranteed> where - R: TypeFoldable>, + R: OptTryFoldWith>, Op: super::TypeOp<'tcx, Output = R>, { // During NLL, we expect that nobody will register region @@ -97,7 +99,7 @@ where })?; // Next trait solver performs operations locally, and normalize goals should resolve vars. - let value = infcx.resolve_vars_if_possible(value); + let value = infcx.resolve_vars_if_possible(AlwaysTraversable(value)).0; let region_obligations = infcx.take_registered_region_obligations(); let region_constraint_data = infcx.take_and_reset_region_constraints(); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index a618d96ce9507..66d349ff51823 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -6,6 +6,7 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_span::Span; +use rustc_type_ir::traverse::OptTryFoldWith; use crate::infer::canonical::{ CanonicalQueryInput, CanonicalQueryResponse, Certainty, OriginalQueryValues, @@ -62,7 +63,7 @@ pub struct TypeOpOutput<'tcx, Op: TypeOp<'tcx>> { /// /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 'tcx { - type QueryResponse: TypeFoldable>; + type QueryResponse: OptTryFoldWith>; /// Give query the option for a simple fast path that never /// actually hits the tcx cache lookup etc. Return `Some(r)` with diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index c06a578d8ec70..76478c84f984a 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -14,6 +14,7 @@ use crate::data_structures::SsoHashSet; use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::inherent::*; use crate::lift::Lift; +use crate::traverse::{ImportantTypeTraversal, NoopTypeTraversal, OptVisitWith, TypeTraversable}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::{self as ty, Interner}; @@ -125,6 +126,9 @@ impl> TypeFoldable for Binder { } } +impl> TypeTraversable for Binder { + type Kind = ImportantTypeTraversal; +} impl> TypeVisitable for Binder { fn visit_with>(&self, visitor: &mut V) -> V::Result { visitor.visit_binder(self) @@ -182,6 +186,24 @@ impl Binder { Binder { value: &self.value, bound_vars: self.bound_vars } } + pub fn extract_ref(&self, f: F) -> U + where + F: FnOnce(&T) -> U, + U: TypeTraversable, + { + let Binder { value, bound_vars: _ } = self; + f(value) + } + + pub fn extract(self, f: F) -> U + where + F: FnOnce(T) -> U, + U: TypeTraversable, + { + let Binder { value, bound_vars: _ } = self; + f(value) + } + pub fn map_bound_ref>(&self, f: F) -> Binder where F: FnOnce(&T) -> U, @@ -197,7 +219,7 @@ impl Binder { let value = f(value); if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(bound_vars); - value.visit_with(&mut validator); + OptVisitWith::mk_visit_with()(&value, &mut validator); } Binder { value, bound_vars } } @@ -367,6 +389,24 @@ impl EarlyBinder { EarlyBinder { value: &self.value, _tcx: PhantomData } } + pub fn extract_ref(&self, f: F) -> U + where + F: FnOnce(&T) -> U, + U: TypeTraversable, + { + let EarlyBinder { value, _tcx } = self; + f(value) + } + + pub fn extract(self, f: F) -> U + where + F: FnOnce(T) -> U, + U: TypeTraversable, + { + let EarlyBinder { value, _tcx } = self; + f(value) + } + pub fn map_bound_ref(&self, f: F) -> EarlyBinder where F: FnOnce(&T) -> U, diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 07cb8b037ecf7..a18820a660ae9 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -5,7 +5,9 @@ use std::ops::Index; use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; -use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; +use rustc_type_ir_macros::{ + Lift_Generic, NoopTypeTraversable_Generic, TypeFoldable_Generic, TypeVisitable_Generic, +}; use crate::inherent::*; use crate::{self as ty, Interner, UniverseIndex}; @@ -141,7 +143,7 @@ impl CanonicalVarInfo { /// in the type-theory sense of the term -- i.e., a "meta" type system /// that analyzes type-like values. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] -#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[derive(NoopTypeTraversable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub enum CanonicalVarKind { /// Some kind of type inference variable. diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 7a8c612057fa2..29b2b67b632bb 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -5,7 +5,9 @@ use derive_where::derive_where; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; -use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; +use rustc_type_ir_macros::{ + Lift_Generic, NoopTypeTraversable_Generic, TypeFoldable_Generic, TypeVisitable_Generic, +}; use crate::{self as ty, DebruijnIndex, Interner}; @@ -77,6 +79,7 @@ impl UnevaluatedConst { rustc_index::newtype_index! { /// A **`const`** **v**ariable **ID**. + #[derive(NoopTypeTraversable_Generic)] #[encodable] #[orderable] #[debug_format = "?{}c"] @@ -92,6 +95,7 @@ rustc_index::newtype_index! { /// relate an effect variable with a normal one, we would ICE, which can catch bugs /// where we are not correctly using the effect var for an effect param. Fallback /// is also implemented on top of having separate effect and normal const variables. + #[derive(NoopTypeTraversable_Generic)] #[encodable] #[orderable] #[debug_format = "?{}e"] @@ -100,7 +104,7 @@ rustc_index::newtype_index! { } /// An inference variable for a const, for use in const generics. -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, NoopTypeTraversable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] pub enum InferConst { /// Infer the value of the const. diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index cdff77f742d0a..39672977c008f 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -27,9 +27,9 @@ impl ExpectedFound { #[cfg_attr(feature = "nightly", rustc_pass_by_value)] pub enum TypeError { Mismatch, - PolarityMismatch(#[type_visitable(ignore)] ExpectedFound), - SafetyMismatch(#[type_visitable(ignore)] ExpectedFound), - AbiMismatch(#[type_visitable(ignore)] ExpectedFound), + PolarityMismatch(ExpectedFound), + SafetyMismatch(ExpectedFound), + AbiMismatch(ExpectedFound), Mutability, ArgumentMutability(usize), TupleSize(ExpectedFound), diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 02ec29a7f3d52..90f85e1f2f20c 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -12,6 +12,7 @@ use crate::elaborate::Elaboratable; use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::relate::Relate; use crate::solve::Reveal; +use crate::traverse::{NoopTypeTraversal, TypeTraversable}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{self as ty, CollectAndApply, Interner, UpcastFrom}; @@ -208,14 +209,18 @@ pub trait Tys>: fn output(self) -> I::Ty; } -pub trait Abi>: Copy + Debug + Hash + Eq { +pub trait Abi>: + Copy + Hash + Eq + TypeTraversable +{ fn rust() -> Self; /// Whether this ABI is `extern "Rust"`. fn is_rust(self) -> bool; } -pub trait Safety>: Copy + Debug + Hash + Eq { +pub trait Safety>: + Copy + Hash + Eq + TypeTraversable +{ fn safe() -> Self; fn is_safe(self) -> bool; @@ -545,7 +550,9 @@ pub trait Features: Copy { fn associated_const_equality(self) -> bool; } -pub trait DefId: Copy + Debug + Hash + Eq + TypeFoldable { +pub trait DefId: + Copy + Debug + Hash + Eq + TypeTraversable +{ fn is_local(self) -> bool; fn as_local(self) -> Option; @@ -565,7 +572,9 @@ pub trait BoundExistentialPredicates: ) -> impl IntoIterator>>; } -pub trait Span: Copy + Debug + Hash + Eq + TypeFoldable { +pub trait Span: + Copy + Debug + Hash + Eq + TypeTraversable +{ fn dummy() -> Self; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 4184e9e313ff7..ceb50e196d28f 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -14,6 +14,7 @@ use crate::relate::Relate; use crate::solve::{ CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, SolverMode, }; +use crate::traverse::{NoopTypeTraversal, TypeTraversable}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{self as ty, search_graph}; @@ -33,7 +34,12 @@ pub trait Interner: + IrPrint> { type DefId: DefId; - type LocalDefId: Copy + Debug + Hash + Eq + Into + TypeFoldable; + type LocalDefId: Copy + + Debug + + Hash + + Eq + + Into + + TypeTraversable; type Span: Span; type GenericArgs: GenericArgs; @@ -60,7 +66,7 @@ pub trait Interner: + Hash + Default + Eq - + TypeVisitable + + TypeTraversable + SliceLike; type CanonicalVars: Copy diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 9e6d1f424ba49..81d4c74853792 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -19,14 +19,13 @@ use rustc_macros::{Decodable, Encodable, HashStable_NoContext}; // These modules are `pub` since they are not glob-imported. #[macro_use] -pub mod visit; +pub mod traverse; #[cfg(feature = "nightly")] pub mod codec; pub mod data_structures; pub mod elaborate; pub mod error; pub mod fast_reject; -pub mod fold; #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_inherent")] pub mod inherent; pub mod ir_print; @@ -76,6 +75,8 @@ pub use opaque_ty::*; pub use predicate::*; pub use predicate_kind::*; pub use region_kind::*; +use rustc_type_ir_macros::NoopTypeTraversable_Generic; +pub use traverse::{fold, visit}; pub use ty_info::*; pub use ty_kind::*; pub use upcast::*; @@ -379,6 +380,7 @@ impl Default for UniverseIndex { rustc_index::newtype_index! { #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] + #[derive(NoopTypeTraversable_Generic)] #[encodable] #[orderable] #[debug_format = "{}"] diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index aae5aeb5fb363..92cd9322a4252 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -3,32 +3,8 @@ macro_rules! TrivialTypeTraversalImpls { ($($ty:ty,)+) => { $( - impl $crate::fold::TypeFoldable for $ty { - fn try_fold_with>( - self, - _: &mut F, - ) -> ::std::result::Result { - Ok(self) - } - - #[inline] - fn fold_with>( - self, - _: &mut F, - ) -> Self { - self - } - } - - impl $crate::visit::TypeVisitable for $ty { - #[inline] - fn visit_with>( - &self, - _: &mut F) - -> F::Result - { - ::output() - } + impl $crate::traverse::TypeTraversable for $ty { + type Kind = $crate::traverse::NoopTypeTraversal; } )+ }; diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index b3f8390bbf062..a8a4475a19e5c 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -6,13 +6,15 @@ use std::hash::Hash; use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; -use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; +use rustc_type_ir_macros::{ + Lift_Generic, NoopTypeTraversable_Generic, TypeFoldable_Generic, TypeVisitable_Generic, +}; use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast}; /// Depending on the stage of compilation, we want projection to be /// more or less conservative. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, NoopTypeTraversable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub enum Reveal { /// At type-checking time, we refuse to project any associated diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/traverse/fold.rs similarity index 97% rename from compiler/rustc_type_ir/src/fold.rs rename to compiler/rustc_type_ir/src/traverse/fold.rs index 8209d6f5fe3b1..14da33dc34ebc 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/traverse/fold.rs @@ -51,6 +51,7 @@ use rustc_index::{Idx, IndexVec}; use thin_vec::ThinVec; use tracing::instrument; +use super::OptTryFoldWith; use crate::data_structures::Lrc; use crate::inherent::*; use crate::visit::{TypeVisitable, TypeVisitableExt as _}; @@ -234,9 +235,12 @@ where /////////////////////////////////////////////////////////////////////////// // Traversal implementations. -impl, U: TypeFoldable> TypeFoldable for (T, U) { +impl, U: OptTryFoldWith> TypeFoldable for (T, U) { fn try_fold_with>(self, folder: &mut F) -> Result<(T, U), F::Error> { - Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?)) + Ok(( + OptTryFoldWith::mk_try_fold_with()(self.0, folder)?, + OptTryFoldWith::mk_try_fold_with()(self.1, folder)?, + )) } } @@ -248,9 +252,9 @@ impl, B: TypeFoldable, C: TypeFoldable> Ty folder: &mut F, ) -> Result<(A, B, C), F::Error> { Ok(( - self.0.try_fold_with(folder)?, - self.1.try_fold_with(folder)?, - self.2.try_fold_with(folder)?, + OptTryFoldWith::mk_try_fold_with()(self.0, folder)?, + OptTryFoldWith::mk_try_fold_with()(self.1, folder)?, + OptTryFoldWith::mk_try_fold_with()(self.2, folder)?, )) } } diff --git a/compiler/rustc_type_ir/src/traverse/mod.rs b/compiler/rustc_type_ir/src/traverse/mod.rs new file mode 100644 index 0000000000000..b732bc11925fb --- /dev/null +++ b/compiler/rustc_type_ir/src/traverse/mod.rs @@ -0,0 +1,133 @@ +//! A visiting traversal mechanism for complex data structures that contain type +//! information. See the documentation of the [visit] and [fold] modules for more +//! details. + +#[macro_use] +pub mod visit; +pub mod fold; + +use std::fmt; + +use fold::{FallibleTypeFolder, TypeFoldable}; +use rustc_ast_ir::visit::VisitorResult; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; +use visit::{TypeVisitable, TypeVisitor}; + +use crate::Interner; + +#[derive(Debug, Clone, TypeVisitable_Generic, TypeFoldable_Generic)] +pub struct AlwaysTraversable(pub T); + +/// A trait which allows the compiler to reason about the disjointness +/// of `TypeVisitable` and `NoopTypeTraversable`. +/// +/// This trait has a blanket impls for everything that implements `TypeVisitable` +/// while requiring a manual impl for all types whose traversal is a noop. +pub trait TypeTraversable: fmt::Debug + Clone { + type Kind; + + #[inline(always)] + fn noop_visit_with>(&self, _: &mut V) -> V::Result + where + Self: TypeTraversable, + { + V::Result::output() + } + + #[inline(always)] + fn noop_try_fold_with>(self, _: &mut F) -> Result + where + Self: TypeTraversable, + { + Ok(self) + } +} +pub struct ImportantTypeTraversal; +pub struct NoopTypeTraversal; + +pub trait OptVisitWith: TypeTraversable { + fn mk_visit_with>() -> fn(&Self, &mut V) -> V::Result; +} + +impl OptVisitWith for T +where + I: Interner, + T: TypeTraversable + Clone + OptVisitWithHelper, +{ + #[inline(always)] + fn mk_visit_with>() -> fn(&Self, &mut V) -> V::Result { + Self::mk_visit_with_helper() + } +} + +trait OptVisitWithHelper { + fn mk_visit_with_helper>() -> fn(&Self, &mut V) -> V::Result; +} + +impl OptVisitWithHelper for T +where + I: Interner, + T: TypeVisitable, +{ + #[inline(always)] + fn mk_visit_with_helper>() -> fn(&Self, &mut V) -> V::Result { + Self::visit_with + } +} + +/// While this is implemented for all `T`, it is only useable via `OptVisitWith` if +/// `T` implements `TypeTraversable`. +impl OptVisitWithHelper for T +where + I: Interner, +{ + #[inline(always)] + fn mk_visit_with_helper>() -> fn(&Self, &mut V) -> V::Result { + |_, _| V::Result::output() + } +} + +pub trait OptTryFoldWith: OptVisitWith + Sized { + fn mk_try_fold_with>() -> fn(Self, &mut F) -> Result; +} + +impl OptTryFoldWith for T +where + I: Interner, + T: OptVisitWith + OptTryFoldWithHelper, +{ + #[inline(always)] + fn mk_try_fold_with>() -> fn(Self, &mut F) -> Result { + Self::mk_try_fold_with_helper() + } +} + +pub trait OptTryFoldWithHelper: Sized { + fn mk_try_fold_with_helper>() + -> fn(Self, &mut F) -> Result; +} + +impl OptTryFoldWithHelper for T +where + I: Interner, + T: TypeFoldable, +{ + #[inline(always)] + fn mk_try_fold_with_helper>() + -> fn(Self, &mut F) -> Result { + Self::try_fold_with + } +} + +/// While this is implemented for all `T`, it is only useable via `OptTryFoldWith` if +/// `T` implements `TypeTraversable`. +impl OptTryFoldWithHelper for T +where + I: Interner, +{ + #[inline(always)] + fn mk_try_fold_with_helper>() + -> fn(Self, &mut F) -> Result { + |this, _| Ok(this) + } +} diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/traverse/visit.rs similarity index 90% rename from compiler/rustc_type_ir/src/visit.rs rename to compiler/rustc_type_ir/src/traverse/visit.rs index 71c3646498b9f..5b9f31f679677 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/traverse/visit.rs @@ -41,7 +41,6 @@ //! - u.visit_with(visitor) //! ``` -use std::fmt; use std::ops::ControlFlow; use rustc_ast_ir::visit::VisitorResult; @@ -49,6 +48,7 @@ use rustc_ast_ir::{try_visit, walk_visitable_list}; use rustc_index::{Idx, IndexVec}; use thin_vec::ThinVec; +use super::{ImportantTypeTraversal, OptVisitWith, TypeTraversable}; use crate::data_structures::Lrc; use crate::inherent::*; use crate::{self as ty, Interner, TypeFlags}; @@ -58,7 +58,7 @@ use crate::{self as ty, Interner, TypeFlags}; /// /// To implement this conveniently, use the derive macro located in /// `rustc_macros`. -pub trait TypeVisitable: fmt::Debug + Clone { +pub trait TypeVisitable: TypeTraversable { /// The entry point for visiting. To visit a value `t` with a visitor `v` /// call: `t.visit_with(v)`. /// @@ -131,23 +131,34 @@ pub trait TypeVisitor: Sized { /////////////////////////////////////////////////////////////////////////// // Traversal implementations. -impl, U: TypeVisitable> TypeVisitable for (T, U) { +impl, U: OptVisitWith> TypeTraversable for (T, U) { + type Kind = ImportantTypeTraversal; +} +impl, U: OptVisitWith> TypeVisitable for (T, U) { fn visit_with>(&self, visitor: &mut V) -> V::Result { - try_visit!(self.0.visit_with(visitor)); - self.1.visit_with(visitor) + try_visit!(OptVisitWith::mk_visit_with()(&self.0, visitor)); + OptVisitWith::mk_visit_with()(&self.1, visitor) } } -impl, B: TypeVisitable, C: TypeVisitable> TypeVisitable +impl, B: OptVisitWith, C: OptVisitWith> TypeTraversable + for (A, B, C) +{ + type Kind = ImportantTypeTraversal; +} +impl, B: OptVisitWith, C: OptVisitWith> TypeVisitable for (A, B, C) { fn visit_with>(&self, visitor: &mut V) -> V::Result { - try_visit!(self.0.visit_with(visitor)); - try_visit!(self.1.visit_with(visitor)); - self.2.visit_with(visitor) + try_visit!(OptVisitWith::mk_visit_with()(&self.0, visitor)); + try_visit!(OptVisitWith::mk_visit_with()(&self.1, visitor)); + OptVisitWith::mk_visit_with()(&self.2, visitor) } } +impl> TypeTraversable for Option { + type Kind = T::Kind; +} impl> TypeVisitable for Option { fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { @@ -157,27 +168,38 @@ impl> TypeVisitable for Option { } } -impl, E: TypeVisitable> TypeVisitable for Result { +impl, E: OptVisitWith> TypeTraversable for Result { + type Kind = ImportantTypeTraversal; +} +impl, E: OptVisitWith> TypeVisitable for Result { fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { - Ok(v) => v.visit_with(visitor), - Err(e) => e.visit_with(visitor), + Ok(v) => OptVisitWith::mk_visit_with()(v, visitor), + Err(e) => OptVisitWith::mk_visit_with()(e, visitor), } } } +impl> TypeTraversable for Lrc { + type Kind = T::Kind; +} impl> TypeVisitable for Lrc { fn visit_with>(&self, visitor: &mut V) -> V::Result { - (**self).visit_with(visitor) + (&**self).visit_with(visitor) } } - +impl> TypeTraversable for Box { + type Kind = T::Kind; +} impl> TypeVisitable for Box { fn visit_with>(&self, visitor: &mut V) -> V::Result { - (**self).visit_with(visitor) + (&**self).visit_with(visitor) } } +impl> TypeTraversable for Vec { + type Kind = T::Kind; +} impl> TypeVisitable for Vec { fn visit_with>(&self, visitor: &mut V) -> V::Result { walk_visitable_list!(visitor, self.iter()); @@ -185,6 +207,9 @@ impl> TypeVisitable for Vec { } } +impl> TypeTraversable for ThinVec { + type Kind = T::Kind; +} impl> TypeVisitable for ThinVec { fn visit_with>(&self, visitor: &mut V) -> V::Result { walk_visitable_list!(visitor, self.iter()); @@ -192,9 +217,9 @@ impl> TypeVisitable for ThinVec { } } -// `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general -// case, because we can't return a new slice. But note that there are a couple -// of trivial impls of `TypeFoldable` for specific slice types elsewhere. +impl> TypeTraversable for &[T] { + type Kind = T::Kind; +} impl> TypeVisitable for &[T] { fn visit_with>(&self, visitor: &mut V) -> V::Result { walk_visitable_list!(visitor, self.iter()); @@ -202,6 +227,9 @@ impl> TypeVisitable for &[T] { } } +impl> TypeTraversable for Box<[T]> { + type Kind = T::Kind; +} impl> TypeVisitable for Box<[T]> { fn visit_with>(&self, visitor: &mut V) -> V::Result { walk_visitable_list!(visitor, self.iter()); @@ -209,6 +237,9 @@ impl> TypeVisitable for Box<[T]> { } } +impl, Ix: Idx> TypeTraversable for IndexVec { + type Kind = T::Kind; +} impl, Ix: Idx> TypeVisitable for IndexVec { fn visit_with>(&self, visitor: &mut V) -> V::Result { walk_visitable_list!(visitor, self.iter()); diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 499e6d3dd37d1..3f98417e4bb8e 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -8,7 +8,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; -use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; +use rustc_type_ir_macros::{ + Lift_Generic, NoopTypeTraversable_Generic, TypeFoldable_Generic, TypeVisitable_Generic, +}; use self::TyKind::*; pub use self::closure::*; @@ -861,11 +863,7 @@ pub struct TypeAndMut { pub struct FnSig { 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, } @@ -1016,7 +1014,7 @@ impl ty::Binder> { #[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] -#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[derive(NoopTypeTraversable_Generic, Lift_Generic)] pub struct FnHeader { pub c_variadic: bool, pub safety: I::Safety, diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index 10b164eae027b..09a43b1795516 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -372,12 +372,8 @@ pub struct CoroutineClosureSignature { /// 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 aaf69e2648d5c..74bb22bbbfe36 100644 --- a/compiler/rustc_type_ir_macros/src/lib.rs +++ b/compiler/rustc_type_ir_macros/src/lib.rs @@ -1,33 +1,37 @@ -use quote::{ToTokens, quote}; +use quote::quote; +use syn::parse_quote; use syn::visit_mut::VisitMut; -use syn::{Attribute, parse_quote}; use synstructure::decl_derive; -decl_derive!( - [TypeVisitable_Generic, attributes(type_visitable)] => type_visitable_derive -); -decl_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(()) - }); - }); +decl_derive!([NoopTypeTraversable_Generic] => noop_type_traversable_derive); +decl_derive!([TypeFoldable_Generic] => type_foldable_derive); +decl_derive!([TypeVisitable_Generic] => type_visitable_derive); +decl_derive!([Lift_Generic] => lift_derive); - ignored +fn noop_type_traversable_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_bounds(synstructure::AddBounds::None); + let mut where_clauses = None; + s.add_trait_bounds( + &parse_quote!(::rustc_type_ir::traverse::TypeTraversable), + &mut where_clauses, + synstructure::AddBounds::Fields, + ); + s.add_where_predicate(parse_quote! { I: Interner }); + for pred in where_clauses.into_iter().flat_map(|c| c.predicates) { + s.add_where_predicate(pred); + } + + s.bound_impl(quote!(::rustc_type_ir::traverse::TypeTraversable), quote! { + type Kind = ::rustc_type_ir::traverse::NoopTypeTraversal; + }) } fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { @@ -39,14 +43,24 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok s.add_impl_generic(parse_quote! { I }); } - s.filter(|bi| !has_ignore_attr(&bi.ast().attrs, "type_visitable", "ignore")); - + s.add_bounds(synstructure::AddBounds::None); + let mut where_clauses = None; + s.add_trait_bounds( + &parse_quote!(::rustc_type_ir::traverse::OptVisitWith), + &mut where_clauses, + synstructure::AddBounds::Fields, + ); s.add_where_predicate(parse_quote! { I: Interner }); - s.add_bounds(synstructure::AddBounds::Fields); + for pred in where_clauses.into_iter().flat_map(|c| c.predicates) { + s.add_where_predicate(pred); + } + + let impl_traversable_s = s.clone(); + let body_visit = s.each(|bind| { quote! { match ::rustc_ast_ir::visit::VisitorResult::branch( - ::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor) + ::rustc_type_ir::traverse::OptVisitWith::mk_visit_with()(#bind, __visitor) ) { ::core::ops::ControlFlow::Continue(()) => {}, ::core::ops::ControlFlow::Break(r) => { @@ -57,7 +71,7 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok }); s.bind_with(|_| synstructure::BindStyle::Move); - s.bound_impl(quote!(::rustc_type_ir::visit::TypeVisitable), quote! { + let visitable_impl = s.bound_impl(quote!(::rustc_type_ir::visit::TypeVisitable), quote! { fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor>( &self, __visitor: &mut __V @@ -65,7 +79,19 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok match *self { #body_visit } <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output() } - }) + }); + + let traversable_impl = impl_traversable_s.bound_impl( + quote!(::rustc_type_ir::traverse::TypeTraversable), + quote! { + type Kind = ::rustc_type_ir::traverse::ImportantTypeTraversal; + }, + ); + + quote! { + #visitable_impl + #traversable_impl + } } fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { @@ -77,30 +103,29 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke s.add_impl_generic(parse_quote! { I }); } + s.add_bounds(synstructure::AddBounds::None); + let mut where_clauses = None; + s.add_trait_bounds( + &parse_quote!(::rustc_type_ir::traverse::OptTryFoldWith), + &mut where_clauses, + synstructure::AddBounds::Fields, + ); s.add_where_predicate(parse_quote! { I: Interner }); - s.add_bounds(synstructure::AddBounds::Fields); + for pred in where_clauses.into_iter().flat_map(|c| c.predicates) { + s.add_where_predicate(pred); + } + s.bind_with(|_| synstructure::BindStyle::Move); let body_fold = s.each_variant(|vi| { let bindings = vi.bindings(); vi.construct(|_, index| { let bind = &bindings[index]; - - // 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)? - } + quote! { + ::rustc_type_ir::traverse::OptTryFoldWith::mk_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), quote! { fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder>( self,