@@ -125,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
125
125
// on a trait we need to add in the supertrait bounds and bounds found on
126
126
// associated types.
127
127
if let Some(_trait_ref) = is_trait {
128
- predicates.extend(tcx.super_predicates_of (def_id).predicates.iter().cloned());
128
+ predicates.extend(tcx.implied_predicates_of (def_id).predicates.iter().cloned());
129
129
}
130
130
131
131
// In default impls, we can assume that the self type implements
@@ -534,31 +534,62 @@ pub(super) fn explicit_predicates_of<'tcx>(
534
534
}
535
535
}
536
536
537
+ #[derive(Copy, Clone, Debug)]
538
+ pub enum PredicateFilter {
539
+ /// All predicates may be implied by the trait
540
+ All,
541
+
542
+ /// Only traits that reference `Self: ..` are implied by the trait
543
+ SelfOnly,
544
+
545
+ /// Only traits that reference `Self: ..` and define an associated type
546
+ /// with the given ident are implied by the trait
547
+ SelfThatDefines(Ident),
548
+ }
549
+
537
550
/// Ensures that the super-predicates of the trait with a `DefId`
538
551
/// of `trait_def_id` are converted and stored. This also ensures that
539
552
/// the transitive super-predicates are converted.
540
553
pub(super) fn super_predicates_of(
541
554
tcx: TyCtxt<'_>,
542
555
trait_def_id: LocalDefId,
543
556
) -> ty::GenericPredicates<'_> {
544
- tcx.super_predicates_that_define_assoc_type((trait_def_id.to_def_id(), None))
557
+ implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
558
+ }
559
+
560
+ pub(super) fn super_predicates_that_define_assoc_type(
561
+ tcx: TyCtxt<'_>,
562
+ (trait_def_id, assoc_name): (DefId, Ident),
563
+ ) -> ty::GenericPredicates<'_> {
564
+ implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name))
565
+ }
566
+
567
+ pub(super) fn implied_predicates_of(
568
+ tcx: TyCtxt<'_>,
569
+ trait_def_id: LocalDefId,
570
+ ) -> ty::GenericPredicates<'_> {
571
+ if tcx.is_trait_alias(trait_def_id.to_def_id()) {
572
+ implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
573
+ } else {
574
+ tcx.super_predicates_of(trait_def_id)
575
+ }
545
576
}
546
577
547
578
/// Ensures that the super-predicates of the trait with a `DefId`
548
579
/// of `trait_def_id` are converted and stored. This also ensures that
549
580
/// the transitive super-predicates are converted.
550
- pub(super) fn super_predicates_that_define_assoc_type (
581
+ pub(super) fn implied_predicates_with_filter (
551
582
tcx: TyCtxt<'_>,
552
- (trait_def_id, assoc_name): (DefId, Option<Ident>),
583
+ trait_def_id: DefId,
584
+ filter: PredicateFilter,
553
585
) -> ty::GenericPredicates<'_> {
554
586
let Some(trait_def_id) = trait_def_id.as_local() else {
555
587
// if `assoc_name` is None, then the query should've been redirected to an
556
588
// external provider
557
- assert!(assoc_name.is_some( ));
589
+ assert!(matches!(filter, PredicateFilter::SelfThatDefines(_) ));
558
590
return tcx.super_predicates_of(trait_def_id);
559
591
};
560
592
561
- debug!("local trait");
562
593
let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id);
563
594
564
595
let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
@@ -573,48 +604,66 @@ pub(super) fn super_predicates_that_define_assoc_type(
573
604
574
605
let icx = ItemCtxt::new(tcx, trait_def_id);
575
606
576
- // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
577
607
let self_param_ty = tcx.types.self_param;
578
- let superbounds1 = if let Some(assoc_name) = assoc_name {
579
- icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
580
- } else {
581
- icx.astconv().compute_bounds(self_param_ty, bounds)
608
+ let (superbounds, where_bounds_that_match) = match filter {
609
+ PredicateFilter::All => (
610
+ // Convert the bounds that follow the colon (or equal in trait aliases)
611
+ icx.astconv().compute_bounds(self_param_ty, bounds),
612
+ // Also include all where clause bounds
613
+ icx.type_parameter_bounds_in_generics(
614
+ generics,
615
+ item.owner_id.def_id,
616
+ self_param_ty,
617
+ OnlySelfBounds(false),
618
+ None,
619
+ ),
620
+ ),
621
+ PredicateFilter::SelfOnly => (
622
+ // Convert the bounds that follow the colon (or equal in trait aliases)
623
+ icx.astconv().compute_bounds(self_param_ty, bounds),
624
+ // Include where clause bounds for `Self`
625
+ icx.type_parameter_bounds_in_generics(
626
+ generics,
627
+ item.owner_id.def_id,
628
+ self_param_ty,
629
+ OnlySelfBounds(true),
630
+ None,
631
+ ),
632
+ ),
633
+ PredicateFilter::SelfThatDefines(assoc_name) => (
634
+ // Convert the bounds that follow the colon (or equal) that reference the associated name
635
+ icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name),
636
+ // Include where clause bounds for `Self` that reference the associated name
637
+ icx.type_parameter_bounds_in_generics(
638
+ generics,
639
+ item.owner_id.def_id,
640
+ self_param_ty,
641
+ OnlySelfBounds(true),
642
+ Some(assoc_name),
643
+ ),
644
+ ),
582
645
};
583
646
584
- let superbounds1 = superbounds1.predicates();
585
-
586
- // Convert any explicit superbounds in the where-clause,
587
- // e.g., `trait Foo where Self: Bar`.
588
- // In the case of trait aliases, however, we include all bounds in the where-clause,
589
- // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
590
- // as one of its "superpredicates".
591
- let is_trait_alias = tcx.is_trait_alias(trait_def_id.to_def_id());
592
- let superbounds2 = icx.type_parameter_bounds_in_generics(
593
- generics,
594
- item.owner_id.def_id,
595
- self_param_ty,
596
- OnlySelfBounds(!is_trait_alias),
597
- assoc_name,
598
- );
599
-
600
647
// Combine the two lists to form the complete set of superbounds:
601
- let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
602
- debug!(?superbounds);
648
+ let implied_bounds = &*tcx
649
+ .arena
650
+ .alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match));
651
+ debug!(?implied_bounds);
603
652
604
653
// Now require that immediate supertraits are converted,
605
654
// which will, in turn, reach indirect supertraits.
606
- if assoc_name.is_none( ) {
655
+ if matches!(filter, PredicateFilter::SelfOnly ) {
607
656
// Now require that immediate supertraits are converted,
608
657
// which will, in turn, reach indirect supertraits.
609
- for &(pred, span) in superbounds {
658
+ for &(pred, span) in implied_bounds {
610
659
debug!("superbound: {:?}", pred);
611
660
if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() {
612
661
tcx.at(span).super_predicates_of(bound.def_id());
613
662
}
614
663
}
615
664
}
616
665
617
- ty::GenericPredicates { parent: None, predicates: superbounds }
666
+ ty::GenericPredicates { parent: None, predicates: implied_bounds }
618
667
}
619
668
620
669
/// Returns the predicates defined on `item_def_id` of the form
0 commit comments