diff options
| author | Michael Goulet <michael@errs.io> | 2023-06-14 18:08:47 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-06-27 18:28:07 +0000 |
| commit | 858a861fff3c054f5eccb74c22d061f1765e9cbd (patch) | |
| tree | addf805fb386c058c8755a0938f1b41fe972069f /compiler | |
| parent | 3c554f5cb4965a08f2a2b45ab4bba321a5f249fa (diff) | |
| download | rust-858a861fff3c054f5eccb74c22d061f1765e9cbd.tar.gz rust-858a861fff3c054f5eccb74c22d061f1765e9cbd.zip | |
Make associated type bounds in supertrait position implied
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect/predicates_of.rs | 104 |
1 files changed, 54 insertions, 50 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index edb6a4cace3..5605901fbcb 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -532,15 +532,20 @@ pub(super) fn explicit_predicates_of<'tcx>( #[derive(Copy, Clone, Debug)] pub enum PredicateFilter { - /// All predicates may be implied by the trait + /// All predicates may be implied by the trait. All, - /// Only traits that reference `Self: ..` are implied by the trait + /// Only traits that reference `Self: ..` are implied by the trait. SelfOnly, /// Only traits that reference `Self: ..` and define an associated type - /// with the given ident are implied by the trait + /// with the given ident are implied by the trait. SelfThatDefines(Ident), + + /// Only traits that reference `Self: ..` and their associated type bounds. + /// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr` + /// and `<Self as Tr>::A: B`. + SelfAndAssociatedTypeBounds, } /// Ensures that the super-predicates of the trait with a `DefId` @@ -564,11 +569,15 @@ pub(super) fn implied_predicates_of( tcx: TyCtxt<'_>, trait_def_id: LocalDefId, ) -> ty::GenericPredicates<'_> { - if tcx.is_trait_alias(trait_def_id.to_def_id()) { - implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All) - } else { - tcx.super_predicates_of(trait_def_id) - } + implied_predicates_with_filter( + tcx, + trait_def_id.to_def_id(), + if tcx.is_trait_alias(trait_def_id.to_def_id()) { + PredicateFilter::All + } else { + PredicateFilter::SelfAndAssociatedTypeBounds + }, + ) } /// Ensures that the super-predicates of the trait with a `DefId` @@ -601,45 +610,28 @@ pub(super) fn implied_predicates_with_filter( let icx = ItemCtxt::new(tcx, trait_def_id); let self_param_ty = tcx.types.self_param; - let (superbounds, where_bounds_that_match) = match filter { - PredicateFilter::All => ( - // Convert the bounds that follow the colon (or equal in trait aliases) - icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)), - // Also include all where clause bounds - icx.type_parameter_bounds_in_generics( - generics, - item.owner_id.def_id, - self_param_ty, - OnlySelfBounds(false), - None, - ), - ), - PredicateFilter::SelfOnly => ( - // Convert the bounds that follow the colon (or equal in trait aliases) - icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)), - // Include where clause bounds for `Self` - icx.type_parameter_bounds_in_generics( - generics, - item.owner_id.def_id, - self_param_ty, - OnlySelfBounds(true), - None, - ), - ), - PredicateFilter::SelfThatDefines(assoc_name) => ( - // Convert the bounds that follow the colon (or equal) that reference the associated name - icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name), - // Include where clause bounds for `Self` that reference the associated name - icx.type_parameter_bounds_in_generics( - generics, - item.owner_id.def_id, - self_param_ty, - OnlySelfBounds(true), - Some(assoc_name), - ), - ), + let superbounds = match filter { + // Should imply both "real" supertraits, and also associated type bounds + // from the supertraits position. + PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => { + icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)) + } + // Should only imply "real" supertraits, i.e. predicates with the self type `Self`. + PredicateFilter::SelfOnly => { + icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)) + } + PredicateFilter::SelfThatDefines(assoc_name) => { + icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name) + } }; + let where_bounds_that_match = icx.type_parameter_bounds_in_generics( + generics, + item.owner_id.def_id, + self_param_ty, + filter, + ); + // Combine the two lists to form the complete set of superbounds: let implied_bounds = &*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match)); @@ -743,8 +735,7 @@ pub(super) fn type_param_predicates( ast_generics, def_id, ty, - OnlySelfBounds(true), - Some(assoc_name), + PredicateFilter::SelfThatDefines(assoc_name), ) .into_iter() .filter(|(predicate, _)| match predicate.kind().skip_binder() { @@ -768,8 +759,7 @@ impl<'tcx> ItemCtxt<'tcx> { ast_generics: &'tcx hir::Generics<'tcx>, param_def_id: LocalDefId, ty: Ty<'tcx>, - only_self_bounds: OnlySelfBounds, - assoc_name: Option<Ident>, + filter: PredicateFilter, ) -> Vec<(ty::Clause<'tcx>, Span)> { let mut bounds = Bounds::default(); @@ -778,9 +768,23 @@ impl<'tcx> ItemCtxt<'tcx> { continue; }; + let (only_self_bounds, assoc_name) = match filter { + PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => { + (OnlySelfBounds(false), None) + } + PredicateFilter::SelfOnly => (OnlySelfBounds(true), None), + PredicateFilter::SelfThatDefines(assoc_name) => { + (OnlySelfBounds(true), Some(assoc_name)) + } + }; + + // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we + // want to only consider predicates with `Self: ...`, but we don't want + // `OnlySelfBounds(true)` since we want to collect the nested associated + // type bound as well. let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) { ty - } else if !only_self_bounds.0 { + } else if matches!(filter, PredicateFilter::All) { self.to_ty(predicate.bounded_ty) } else { continue; |
