From 88b10c1162004e8f3bf4f5a9c386dde5fc11fc2e Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sat, 20 Apr 2024 16:42:18 +0200 Subject: [PATCH 1/4] include ParamEnv in projection cache key --- compiler/rustc_infer/src/traits/project.rs | 5 +++-- .../rustc_trait_selection/src/traits/fulfill.rs | 4 ++-- .../rustc_trait_selection/src/traits/project.rs | 13 +++++++------ .../rustc_trait_selection/src/traits/select/mod.rs | 10 +++++++--- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 31ceb234332..c6ffba59638 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -78,11 +78,12 @@ pub struct ProjectionCacheStorage<'tcx> { #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ProjectionCacheKey<'tcx> { ty: ty::AliasTy<'tcx>, + param_env: ty::ParamEnv<'tcx>, } impl<'tcx> ProjectionCacheKey<'tcx> { - pub fn new(ty: ty::AliasTy<'tcx>) -> Self { - Self { ty } + pub fn new(ty: ty::AliasTy<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { + Self { ty, param_env } } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index fbff78304ac..8cd9f39d5d8 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -758,9 +758,9 @@ fn process_projection_obligation( // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) { - if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate( + if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation( &mut self.selcx, - project_obligation.predicate, + &project_obligation, ) { // If `predicate_must_hold_considering_regions` succeeds, then we've // evaluated all sub-obligations. We can therefore mark the 'root' diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 67865bfcaa3..ca0b50864a8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -344,7 +344,7 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>( let use_cache = !selcx.is_intercrate(); let projection_ty = infcx.resolve_vars_if_possible(projection_ty); - let cache_key = ProjectionCacheKey::new(projection_ty); + let cache_key = ProjectionCacheKey::new(projection_ty, param_env); // FIXME(#20304) For now, I am caching here, which is good, but it // means we don't capture the type variables that are created in @@ -2105,27 +2105,28 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( } pub(crate) trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized { - fn from_poly_projection_predicate( + fn from_poly_projection_obligation( selcx: &mut SelectionContext<'cx, 'tcx>, - predicate: ty::PolyProjectionPredicate<'tcx>, + obligation: &PolyProjectionObligation<'tcx>, ) -> Option; } impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> { - fn from_poly_projection_predicate( + fn from_poly_projection_obligation( selcx: &mut SelectionContext<'cx, 'tcx>, - predicate: ty::PolyProjectionPredicate<'tcx>, + obligation: &PolyProjectionObligation<'tcx>, ) -> Option { let infcx = selcx.infcx; // We don't do cross-snapshot caching of obligations with escaping regions, // so there's no cache key to use - predicate.no_bound_vars().map(|predicate| { + obligation.predicate.no_bound_vars().map(|predicate| { ProjectionCacheKey::new( // We don't attempt to match up with a specific type-variable state // from a specific call to `opt_normalize_projection_type` - if // there's no precise match, the original cache entry is "stranded" // anyway. infcx.resolve_vars_if_possible(predicate.projection_ty), + obligation.param_env, ) }) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 10370c7898b..fc12fed3537 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -815,7 +815,10 @@ fn evaluate_predicate_recursively<'o>( // `EvaluatedToOkModuloRegions`), and skip re-evaluating the // sub-obligations. if let Some(key) = - ProjectionCacheKey::from_poly_projection_predicate(self, data) + ProjectionCacheKey::from_poly_projection_obligation( + self, + &project_obligation, + ) { if let Some(cached_res) = self .infcx @@ -844,8 +847,9 @@ fn evaluate_predicate_recursively<'o>( && (eval_rslt == EvaluatedToOk || eval_rslt == EvaluatedToOkModuloRegions) && let Some(key) = - ProjectionCacheKey::from_poly_projection_predicate( - self, data, + ProjectionCacheKey::from_poly_projection_obligation( + self, + &project_obligation, ) { // If the result is something that we can cache, then mark this From f9ba863c4dc2c36bd39d954ee135122cd646d914 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sat, 20 Apr 2024 16:43:00 +0200 Subject: [PATCH 2/4] remove `InferCtxt::clear_caches` --- compiler/rustc_infer/src/infer/mod.rs | 9 --------- compiler/rustc_trait_selection/src/traits/auto_trait.rs | 3 --- 2 files changed, 12 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 355fcf59495..81130d69151 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1521,15 +1521,6 @@ pub fn closure_kind(&self, closure_ty: Ty<'tcx>) -> Option { closure_kind_ty.to_opt_closure_kind() } - /// Clears the selection, evaluation, and projection caches. This is useful when - /// repeatedly attempting to select an `Obligation` while changing only - /// its `ParamEnv`, since `FulfillmentContext` doesn't use probing. - pub fn clear_caches(&self) { - self.selection_cache.clear(); - self.evaluation_cache.clear(); - self.inner.borrow_mut().projection_cache().clear(); - } - pub fn universe(&self) -> ty::UniverseIndex { self.universe.get() } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 73e94da165f..c450d104e5c 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -152,7 +152,6 @@ pub fn find_auto_trait_generics( with {:?}", trait_ref, full_env ); - infcx.clear_caches(); // At this point, we already have all of the bounds we need. FulfillmentContext is used // to store all of the necessary region/lifetime bounds in the InferContext, as well as @@ -255,8 +254,6 @@ fn evaluate_predicates( let dummy_cause = ObligationCause::dummy(); while let Some(pred) = predicates.pop_front() { - infcx.clear_caches(); - if !already_visited.insert(pred) { continue; } From 31a05a227afb9aa2b2ad02a04593f86aea7641e4 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sat, 20 Apr 2024 18:24:54 +0200 Subject: [PATCH 3/4] merge two impl blocks --- compiler/rustc_trait_selection/src/traits/auto_trait.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c450d104e5c..f9e7ed9dcbb 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -175,9 +175,7 @@ pub fn find_auto_trait_generics( AutoTraitResult::PositiveImpl(auto_trait_callback(info)) } -} -impl<'tcx> AutoTraitFinder<'tcx> { /// The core logic responsible for computing the bounds for our synthesized impl. /// /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like From 5a2b335e498202e4470ccccd6cc32b0b4133738e Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 21 Apr 2024 18:04:50 +0200 Subject: [PATCH 4/4] also remap RPITITs nested in other types back to their opaques --- compiler/rustc_hir_analysis/src/collect/item_bounds.rs | 4 ++-- tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index c2205815ba6..02291cc603e 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::GenericArgs; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; @@ -214,7 +214,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { { self.tcx.type_of(projection_ty.def_id).instantiate(self.tcx, projection_ty.args) } else { - ty + ty.super_fold_with(self) } } } diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs b/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs index 3a173efb32d..10c2a811243 100644 --- a/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs +++ b/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs @@ -6,6 +6,10 @@ trait Foo { fn foo() -> impl Deref> { &&() } + + fn bar() -> impl Deref> { + &Some(()) + } } fn main() {}