diff options
| author | bors <bors@rust-lang.org> | 2023-04-12 08:39:19 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-04-12 08:39:19 +0000 |
| commit | 9be9b5e09ad834e2ba9f2571ca17059e18f89b71 (patch) | |
| tree | 8c56a32b9bdc1026a4d12a0ea5810252ae6fcdd7 /compiler/rustc_infer/src | |
| parent | 0d7ed3ba8445452013dd873dc9abcad41a3d82b2 (diff) | |
| parent | 7ec72efe10df28fcf5c6ec13c2a487572041be59 (diff) | |
| download | rust-9be9b5e09ad834e2ba9f2571ca17059e18f89b71.tar.gz rust-9be9b5e09ad834e2ba9f2571ca17059e18f89b71.zip | |
Auto merge of #107614 - compiler-errors:allow-elaborator-to-filter-only-super-traits, r=oli-obk
Split implied and super predicate queries, then allow elaborator to filter only supertraits Split the `super_predicates_of` query into a new `implied_predicates_of` query. The former now only returns the *real* supertraits of a trait alias, and the latter now returns the implied predicates (which include all of the `where` clauses of the trait alias). The behavior of these queries is identical for regular traits. Now that the two queries are split, we can add a new filter method to the elaborator, `filter_only_self()`, which can be used in instances that we need only the *supertrait* predicates, such as during the elaboration used in closure signature deduction. This toggles the usage of `super_predicates_of` instead of `implied_predicates_of` during elaboration of a trait predicate. This supersedes #104745, and fixes the four independent bugs identified in that PR. Fixes #104719 Fixes #106238 Fixes #110023 Fixes #109514 r? types
Diffstat (limited to 'compiler/rustc_infer/src')
| -rw-r--r-- | compiler/rustc_infer/src/traits/util.rs | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c7f7ed14940..ef01d5d513b 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -69,6 +69,7 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> { pub struct Elaborator<'tcx, O> { stack: Vec<O>, visited: PredicateSet<'tcx>, + only_self: bool, } /// Describes how to elaborate an obligation into a sub-obligation. @@ -170,7 +171,8 @@ pub fn elaborate<'tcx, O: Elaboratable<'tcx>>( tcx: TyCtxt<'tcx>, obligations: impl IntoIterator<Item = O>, ) -> Elaborator<'tcx, O> { - let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) }; + let mut elaborator = + Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx), only_self: false }; elaborator.extend_deduped(obligations); elaborator } @@ -185,14 +187,25 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate()))); } + /// Filter to only the supertraits of trait predicates, i.e. only the predicates + /// that have `Self` as their self type, instead of all implied predicates. + pub fn filter_only_self(mut self) -> Self { + self.only_self = true; + self + } + fn elaborate(&mut self, elaboratable: &O) { let tcx = self.visited.tcx; let bound_predicate = elaboratable.predicate().kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { - // Get predicates declared on the trait. - let predicates = tcx.super_predicates_of(data.def_id()); + // Get predicates implied by the trait, or only super predicates if we only care about self predicates. + let predicates = if self.only_self { + tcx.super_predicates_of(data.def_id()) + } else { + tcx.implied_predicates_of(data.def_id()) + }; let obligations = predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| { @@ -350,18 +363,16 @@ pub fn supertraits<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> { - let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx); - FilterToTraits::new(elaborate(tcx, [pred])) + elaborate(tcx, [trait_ref.to_predicate(tcx)]).filter_only_self().filter_to_traits() } pub fn transitive_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>, ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> { - FilterToTraits::new(elaborate( - tcx, - trait_refs.map(|trait_ref| -> ty::Predicate<'tcx> { trait_ref.to_predicate(tcx) }), - )) + elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx))) + .filter_only_self() + .filter_to_traits() } /// A specialized variant of `elaborate` that only elaborates trait references that may @@ -381,10 +392,8 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>( while let Some(trait_ref) = stack.pop() { let anon_trait_ref = tcx.anonymize_bound_vars(trait_ref); if visited.insert(anon_trait_ref) { - let super_predicates = tcx.super_predicates_that_define_assoc_type(( - trait_ref.def_id(), - Some(assoc_name), - )); + let super_predicates = + tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), assoc_name)); for (super_predicate, _) in super_predicates.predicates { let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() { @@ -404,18 +413,18 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>( // Other /////////////////////////////////////////////////////////////////////////// +impl<'tcx> Elaborator<'tcx, ty::Predicate<'tcx>> { + fn filter_to_traits(self) -> FilterToTraits<Self> { + FilterToTraits { base_iterator: self } + } +} + /// A filter around an iterator of predicates that makes it yield up /// just trait references. pub struct FilterToTraits<I> { base_iterator: I, } -impl<I> FilterToTraits<I> { - fn new(base: I) -> FilterToTraits<I> { - FilterToTraits { base_iterator: base } - } -} - impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> { type Item = ty::PolyTraitRef<'tcx>; |
