From 79228526bfa37f2f0ee9b91671a4342064e85f73 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Aug 2024 13:33:32 -0400 Subject: [PATCH] Cache supertrait outlives of impl header for soundness check --- compiler/rustc_hir_analysis/src/collect.rs | 1 + .../src/collect/item_bounds.rs | 21 ++++++++++ compiler/rustc_middle/src/query/mod.rs | 4 ++ .../src/traits/select/mod.rs | 42 +++++++------------ 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 47ff748547a..8c1e5e78b75 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -67,6 +67,7 @@ pub fn provide(providers: &mut Providers) { item_super_predicates: item_bounds::item_super_predicates, explicit_item_super_predicates: item_bounds::explicit_item_super_predicates, item_non_self_assumptions: item_bounds::item_non_self_assumptions, + impl_super_outlives: item_bounds::impl_super_outlives, generics_of: generics_of::generics_of, predicates_of: predicates_of::predicates_of, predicates_defined_on, diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 6bff99ea65f..ec48c781c0e 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -212,6 +212,8 @@ pub(super) fn item_super_predicates( }) } +/// This exists as an optimization to compute only the item bounds of the item +/// that are not `Self` bounds. pub(super) fn item_non_self_assumptions( tcx: TyCtxt<'_>, def_id: DefId, @@ -226,6 +228,25 @@ pub(super) fn item_non_self_assumptions( } } +/// This exists as an optimization to compute only the supertraits of this impl's +/// trait that are outlives bounds. +pub(super) fn impl_super_outlives( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { + tcx.impl_trait_header(def_id).expect("expected an impl of trait").trait_ref.map_bound( + |trait_ref| { + let clause: ty::Clause<'_> = trait_ref.upcast(tcx); + tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| { + matches!( + clause.kind().skip_binder(), + ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_) + ) + })) + }, + ) +} + struct AssocTyToOpaque<'tcx> { tcx: TyCtxt<'tcx>, fn_def_id: DefId, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c22c2e985ab..f69f78d4f0f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -407,6 +407,10 @@ rustc_queries! { desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } } + query impl_super_outlives(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating supertrait outlives for trait of `{}`", tcx.def_path_str(key) } + } + /// Look up all native libraries this crate depends on. /// These are assembled from the following places: /// - `extern` blocks (depending on their `link` attributes) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1d9a90f0300..1b2767a6a62 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -17,7 +17,6 @@ use rustc_hir::LangItem; use rustc_infer::infer::relate::TypeRelation; use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::traits::util::elaborate; use rustc_infer::traits::TraitObligation; use rustc_middle::bug; use rustc_middle::dep_graph::{dep_kinds, DepNodeIndex}; @@ -2801,31 +2800,22 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } // Register any outlives obligations from the trait here, cc #124336. - if matches!(self.tcx().def_kind(def_id), DefKind::Impl { of_trait: true }) - && let Some(header) = self.tcx().impl_trait_header(def_id) - { - let trait_clause: ty::Clause<'tcx> = - header.trait_ref.instantiate(self.tcx(), args).upcast(self.tcx()); - for clause in elaborate(self.tcx(), [trait_clause]) { - if matches!( - clause.kind().skip_binder(), - ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..) - ) { - let clause = normalize_with_depth_to( - self, - param_env, - cause.clone(), - recursion_depth, - clause, - &mut obligations, - ); - obligations.push(Obligation { - cause: cause.clone(), - recursion_depth, - param_env, - predicate: clause.as_predicate(), - }); - } + if matches!(tcx.def_kind(def_id), DefKind::Impl { of_trait: true }) { + for clause in tcx.impl_super_outlives(def_id).iter_instantiated(tcx, args) { + let clause = normalize_with_depth_to( + self, + param_env, + cause.clone(), + recursion_depth, + clause, + &mut obligations, + ); + obligations.push(Obligation { + cause: cause.clone(), + recursion_depth, + param_env, + predicate: clause.as_predicate(), + }); } }