From 89821b71ff21a9b6b7502f7db291c6134fe832a4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 14 Mar 2023 16:07:14 +0000 Subject: [PATCH] use adt_const_params to make simplify_type faster --- .../src/coherence/inherent_impls.rs | 22 +++++----- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 37 ++++++++--------- compiler/rustc_metadata/src/rmeta/encoder.rs | 10 ++--- compiler/rustc_middle/src/lib.rs | 2 + compiler/rustc_middle/src/ty/fast_reject.rs | 12 +++--- compiler/rustc_middle/src/ty/trait_def.rs | 41 +++++++++---------- compiler/rustc_middle/src/ty/util.rs | 5 +-- .../src/solve/assembly.rs | 3 +- .../src/solve/trait_goals.rs | 13 +++--- .../src/traits/error_reporting/mod.rs | 6 +-- .../src/traits/select/candidate_assembly.rs | 12 +++--- .../traits/specialize/specialization_graph.rs | 32 +++++++-------- .../passes/collect_intra_doc_links.rs | 2 +- 14 files changed, 95 insertions(+), 104 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 07a33bcbb509b..f7a4bb87862d2 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -99,12 +99,11 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type( - self.tcx, - self_ty, - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(simp) = simplify_type::< + { TreatParams::AsCandidateKey }, + { TreatProjections::AsCandidateKey }, + >(self.tcx, self_ty) + { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected self type: {:?}", self_ty); @@ -164,12 +163,11 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type( - self.tcx, - ty, - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(simp) = simplify_type::< + { TreatParams::AsCandidateKey }, + { TreatProjections::AsCandidateKey }, + >(self.tcx, ty) + { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected primitive type: {:?}", ty); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 3254a93034236..13011708ed613 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -700,7 +700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { - let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) else { + let Some(simp) = simplify_type::<{TreatParams::AsCandidateKey}, {TreatProjections::AsCandidateKey}>(self.tcx, self_ty) else { bug!("unexpected incoherent type: {:?}", self_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7055d9257ec90..0ba97bc71db47 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1517,13 +1517,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .any(|info| self.associated_value(info.def_id, item_name).is_some()); let found_assoc = |ty: Ty<'tcx>| { - simplify_type(tcx, ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) - .and_then(|simp| { - tcx.incoherent_impls(simp) - .iter() - .find_map(|&id| self.associated_value(id, item_name)) - }) - .is_some() + simplify_type::<{ TreatParams::AsCandidateKey }, { TreatProjections::AsCandidateKey }>( + tcx, ty, + ) + .and_then(|simp| { + tcx.incoherent_impls(simp) + .iter() + .find_map(|&id| self.associated_value(id, item_name)) + }) + .is_some() }; let found_candidate = found_candidate || found_assoc(tcx.types.i8) @@ -2646,12 +2648,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Even though negative bounds are not implemented, we could maybe handle // cases where a positive bound implies a negative impl. (candidates, Vec::new()) - } else if let Some(simp_rcvr_ty) = simplify_type( - self.tcx, - rcvr_ty, - TreatParams::ForLookup, - TreatProjections::ForLookup, - ) { + } else if let Some(simp_rcvr_ty) = simplify_type::< + { TreatParams::ForLookup }, + { TreatProjections::ForLookup }, + >(self.tcx, rcvr_ty) + { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); for candidate in candidates { @@ -2664,12 +2665,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .any(|imp_did| { let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity(); - let imp_simp = simplify_type( - self.tcx, - imp.self_ty(), - TreatParams::ForLookup, - TreatProjections::ForLookup, - ); + let imp_simp = simplify_type::< + { TreatParams::ForLookup }, + { TreatProjections::ForLookup }, + >(self.tcx, imp.self_ty()); imp_simp.map_or(false, |s| s == simp_rcvr_ty) }) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index bbab8a62a2bce..e3fafcb4f8c04 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1855,12 +1855,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) { let trait_ref = trait_ref.subst_identity(); - let simplified_self_ty = fast_reject::simplify_type( - self.tcx, - trait_ref.self_ty(), - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ); + let simplified_self_ty = fast_reject::simplify_type::< + { TreatParams::AsCandidateKey }, + { TreatProjections::AsCandidateKey }, + >(self.tcx, trait_ref.self_ty()); fx_hash_map .entry(trait_ref.def_id) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 45c4a1057d2df..1fcaccb72bd15 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -23,6 +23,8 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![allow(incomplete_features)] +#![feature(adt_const_params)] #![feature(allocator_api)] #![feature(array_windows)] #![feature(assert_matches)] diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index ee505742be9a0..bbde781a71417 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -103,11 +103,13 @@ pub enum TreatProjections { /// is only correct if they are fully normalized. /// /// ยน meaning that if the outermost layers are different, then the whole types are also different. -pub fn simplify_type<'tcx>( +pub fn simplify_type< + 'tcx, + const TREAT_PARAMS: TreatParams, + const TREAT_PROJECTIONS: TreatProjections, +>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, - treat_params: TreatParams, - treat_projections: TreatProjections, ) -> Option { match *ty.kind() { ty::Bool => Some(BoolSimplifiedType), @@ -135,11 +137,11 @@ pub fn simplify_type<'tcx>( ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())), ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::Placeholder(..) => Some(PlaceholderSimplifiedType), - ty::Param(_) => match treat_params { + ty::Param(_) => match TREAT_PARAMS { TreatParams::ForLookup => Some(PlaceholderSimplifiedType), TreatParams::AsCandidateKey => None, }, - ty::Alias(..) => match treat_projections { + ty::Alias(..) => match TREAT_PROJECTIONS { TreatProjections::ForLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType), TreatProjections::NextSolverLookup => Some(PlaceholderSimplifiedType), TreatProjections::AsCandidateKey | TreatProjections::ForLookup => None, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index bf2b121f704af..02abc21b9dd8d 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -124,23 +124,23 @@ impl<'tcx> TyCtxt<'tcx> { self_ty: Ty<'tcx>, f: impl FnMut(DefId), ) { - self.for_each_relevant_impl_treating_projections( + self.for_each_relevant_impl_treating_projections::<{ TreatProjections::ForLookup }>( trait_def_id, self_ty, - TreatProjections::ForLookup, f, ) } - pub fn for_each_relevant_impl_treating_projections( + pub fn for_each_relevant_impl_treating_projections< + const TREAT_PROJECTIONS: TreatProjections, + >( self, trait_def_id: DefId, self_ty: Ty<'tcx>, - treat_projections: TreatProjections, mut f: impl FnMut(DefId), ) { let _: Option<()> = - self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| { + self.find_map_relevant_impl::<_, TREAT_PROJECTIONS>(trait_def_id, self_ty, |did| { f(did); None }); @@ -153,12 +153,11 @@ impl<'tcx> TyCtxt<'tcx> { self_ty: Ty<'tcx>, ) -> impl Iterator + 'tcx { let impls = self.trait_impls_of(trait_def_id); - if let Some(simp) = fast_reject::simplify_type( - self, - self_ty, - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(simp) = fast_reject::simplify_type::< + { TreatParams::AsCandidateKey }, + { TreatProjections::AsCandidateKey }, + >(self, self_ty) + { if let Some(impls) = impls.non_blanket_impls.get(&simp) { return impls.iter().copied(); } @@ -171,11 +170,10 @@ impl<'tcx> TyCtxt<'tcx> { /// the first non-none value. /// /// `trait_def_id` MUST BE the `DefId` of a trait. - pub fn find_map_relevant_impl( + pub fn find_map_relevant_impl( self, trait_def_id: DefId, self_ty: Ty<'tcx>, - treat_projections: TreatProjections, mut f: impl FnMut(DefId) -> Option, ) -> Option { // FIXME: This depends on the set of all impls for the trait. That is @@ -195,8 +193,10 @@ impl<'tcx> TyCtxt<'tcx> { // whose outer level is not a parameter or projection. Especially for things like // `T: Clone` this is incredibly useful as we would otherwise look at all the impls // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. - if let Some(simp) = - fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup, treat_projections) + if let Some(simp) = fast_reject::simplify_type::< + { TreatParams::ForLookup }, + TREAT_PROJECTIONS, + >(self, self_ty) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { @@ -258,12 +258,11 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait continue; } - if let Some(simplified_self_ty) = fast_reject::simplify_type( - tcx, - impl_self_ty, - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(simplified_self_ty) = fast_reject::simplify_type::< + { TreatParams::AsCandidateKey }, + { TreatProjections::AsCandidateKey }, + >(tcx, impl_self_ty) + { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { impls.blanket_impls.push(impl_def_id); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b0f6127baa5d4..0e15e79b4b2ea 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -364,11 +364,10 @@ impl<'tcx> TyCtxt<'tcx> { self.ensure().coherent_trait(drop_trait); let ty = self.type_of(adt_did).subst_identity(); - let (did, constness) = self.find_map_relevant_impl( + // FIXME: This could also be some other mode, like "unexpected" + let (did, constness) = self.find_map_relevant_impl::<_, { TreatProjections::ForLookup }>( drop_trait, ty, - // FIXME: This could also be some other mode, like "unexpected" - TreatProjections::ForLookup, |impl_did| { if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { if validate(self, impl_did).is_ok() { diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 891ea0cdebe50..072182f5c73cd 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -300,10 +300,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec>, ) { let tcx = self.tcx(); - tcx.for_each_relevant_impl_treating_projections( + tcx.for_each_relevant_impl_treating_projections::<{ TreatProjections::NextSolverLookup }>( goal.predicate.trait_def_id(tcx), goal.predicate.self_ty(), - TreatProjections::NextSolverLookup, |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) { Ok(result) => candidates .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }), diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 7878539817cfb..3760786b2a128 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -140,12 +140,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // `instantiate_constituent_tys_for_auto_trait` returns nothing for // projection types anyways. So it doesn't really matter what we do // here, and this is faster. - if let Some(def_id) = ecx.tcx().find_map_relevant_impl( - goal.predicate.def_id(), - goal.predicate.self_ty(), - TreatProjections::NextSolverLookup, - Some, - ) { + if let Some(def_id) = + ecx.tcx().find_map_relevant_impl::<_, { TreatProjections::NextSolverLookup }>( + goal.predicate.def_id(), + goal.predicate.self_ty(), + Some, + ) + { debug!(?def_id, ?goal, "disqualified auto-trait implementation"); return Err(NoSolution); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 41ffaeeac1c11..ee8a0ba1dc958 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1800,10 +1800,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }) .and_then(|(trait_assoc_item, id)| { let trait_assoc_ident = trait_assoc_item.ident(self.tcx); - self.tcx.find_map_relevant_impl( + self.tcx.find_map_relevant_impl::<_, { TreatProjections::ForLookup }>( id, proj.projection_ty.self_ty(), - TreatProjections::ForLookup, |did| { self.tcx .associated_items(did) @@ -2182,10 +2181,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_ref: &ty::PolyTraitRef<'tcx>, ) -> bool { let get_trait_impl = |trait_def_id| { - self.tcx.find_map_relevant_impl( + self.tcx.find_map_relevant_impl::<_, { TreatProjections::ForLookup }>( trait_def_id, trait_ref.skip_binder().self_ty(), - TreatProjections::ForLookup, Some, ) }; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3182af989f05a..28f27e3e96936 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -781,12 +781,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Adt(..) => { // Find a custom `impl Drop` impl, if it exists - let relevant_impl = self.tcx().find_map_relevant_impl( - self.tcx().require_lang_item(LangItem::Drop, None), - obligation.predicate.skip_binder().trait_ref.self_ty(), - TreatProjections::ForLookup, - Some, - ); + let relevant_impl = + self.tcx().find_map_relevant_impl::<_, { TreatProjections::ForLookup }>( + self.tcx().require_lang_item(LangItem::Drop, None), + obligation.predicate.skip_binder().trait_ref.self_ty(), + Some, + ); if let Some(impl_def_id) = relevant_impl { // Check that `impl Drop` is actually const, if there is a custom impl diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index cd665d9471db2..88dfb40c354be 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -49,12 +49,11 @@ impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); - if let Some(st) = fast_reject::simplify_type( - tcx, - trait_ref.self_ty(), - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(st) = fast_reject::simplify_type::< + { TreatParams::AsCandidateKey }, + { TreatProjections::AsCandidateKey }, + >(tcx, trait_ref.self_ty()) + { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) } else { @@ -69,12 +68,11 @@ impl<'tcx> ChildrenExt<'tcx> for Children { fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let vec: &mut Vec; - if let Some(st) = fast_reject::simplify_type( - tcx, - trait_ref.self_ty(), - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(st) = fast_reject::simplify_type::< + { TreatParams::AsCandidateKey }, + { TreatProjections::AsCandidateKey }, + >(tcx, trait_ref.self_ty()) + { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); } else { @@ -310,12 +308,10 @@ impl<'tcx> GraphExt<'tcx> for Graph { let mut parent = trait_def_id; let mut last_lint = None; - let simplified = fast_reject::simplify_type( - tcx, - trait_ref.self_ty(), - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ); + let simplified = fast_reject::simplify_type::< + { TreatParams::AsCandidateKey }, + { TreatProjections::AsCandidateKey }, + >(tcx, trait_ref.self_ty()); // Descend the specialization tree, where `parent` is the current parent node. loop { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 358f6ad566c25..24f0f092e185b 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -735,7 +735,7 @@ fn trait_impls_for<'a>( trace!("considering explicit impl for trait {:?}", trait_); // Look at each trait implementation to see if it's an impl for `did` - tcx.find_map_relevant_impl(trait_, ty, TreatProjections::ForLookup, |impl_| { + tcx.find_map_relevant_impl::<_, { TreatProjections::ForLookup }>(trait_, ty, |impl_| { let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); // Check if these are the same type. let impl_type = trait_ref.skip_binder().self_ty();