Skip to content

Commit 858a861

Browse files
Make associated type bounds in supertrait position implied
1 parent 3c554f5 commit 858a861

File tree

4 files changed

+112
-50
lines changed

4 files changed

+112
-50
lines changed

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+54-50
Original file line numberDiff line numberDiff line change
@@ -532,15 +532,20 @@ pub(super) fn explicit_predicates_of<'tcx>(
532532

533533
#[derive(Copy, Clone, Debug)]
534534
pub enum PredicateFilter {
535-
/// All predicates may be implied by the trait
535+
/// All predicates may be implied by the trait.
536536
All,
537537

538-
/// Only traits that reference `Self: ..` are implied by the trait
538+
/// Only traits that reference `Self: ..` are implied by the trait.
539539
SelfOnly,
540540

541541
/// Only traits that reference `Self: ..` and define an associated type
542-
/// with the given ident are implied by the trait
542+
/// with the given ident are implied by the trait.
543543
SelfThatDefines(Ident),
544+
545+
/// Only traits that reference `Self: ..` and their associated type bounds.
546+
/// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr`
547+
/// and `<Self as Tr>::A: B`.
548+
SelfAndAssociatedTypeBounds,
544549
}
545550

546551
/// Ensures that the super-predicates of the trait with a `DefId`
@@ -564,11 +569,15 @@ pub(super) fn implied_predicates_of(
564569
tcx: TyCtxt<'_>,
565570
trait_def_id: LocalDefId,
566571
) -> ty::GenericPredicates<'_> {
567-
if tcx.is_trait_alias(trait_def_id.to_def_id()) {
568-
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
569-
} else {
570-
tcx.super_predicates_of(trait_def_id)
571-
}
572+
implied_predicates_with_filter(
573+
tcx,
574+
trait_def_id.to_def_id(),
575+
if tcx.is_trait_alias(trait_def_id.to_def_id()) {
576+
PredicateFilter::All
577+
} else {
578+
PredicateFilter::SelfAndAssociatedTypeBounds
579+
},
580+
)
572581
}
573582

574583
/// Ensures that the super-predicates of the trait with a `DefId`
@@ -601,45 +610,28 @@ pub(super) fn implied_predicates_with_filter(
601610
let icx = ItemCtxt::new(tcx, trait_def_id);
602611

603612
let self_param_ty = tcx.types.self_param;
604-
let (superbounds, where_bounds_that_match) = match filter {
605-
PredicateFilter::All => (
606-
// Convert the bounds that follow the colon (or equal in trait aliases)
607-
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)),
608-
// Also include all where clause bounds
609-
icx.type_parameter_bounds_in_generics(
610-
generics,
611-
item.owner_id.def_id,
612-
self_param_ty,
613-
OnlySelfBounds(false),
614-
None,
615-
),
616-
),
617-
PredicateFilter::SelfOnly => (
618-
// Convert the bounds that follow the colon (or equal in trait aliases)
619-
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)),
620-
// Include where clause bounds for `Self`
621-
icx.type_parameter_bounds_in_generics(
622-
generics,
623-
item.owner_id.def_id,
624-
self_param_ty,
625-
OnlySelfBounds(true),
626-
None,
627-
),
628-
),
629-
PredicateFilter::SelfThatDefines(assoc_name) => (
630-
// Convert the bounds that follow the colon (or equal) that reference the associated name
631-
icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name),
632-
// Include where clause bounds for `Self` that reference the associated name
633-
icx.type_parameter_bounds_in_generics(
634-
generics,
635-
item.owner_id.def_id,
636-
self_param_ty,
637-
OnlySelfBounds(true),
638-
Some(assoc_name),
639-
),
640-
),
613+
let superbounds = match filter {
614+
// Should imply both "real" supertraits, and also associated type bounds
615+
// from the supertraits position.
616+
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
617+
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false))
618+
}
619+
// Should only imply "real" supertraits, i.e. predicates with the self type `Self`.
620+
PredicateFilter::SelfOnly => {
621+
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true))
622+
}
623+
PredicateFilter::SelfThatDefines(assoc_name) => {
624+
icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name)
625+
}
641626
};
642627

628+
let where_bounds_that_match = icx.type_parameter_bounds_in_generics(
629+
generics,
630+
item.owner_id.def_id,
631+
self_param_ty,
632+
filter,
633+
);
634+
643635
// Combine the two lists to form the complete set of superbounds:
644636
let implied_bounds =
645637
&*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match));
@@ -743,8 +735,7 @@ pub(super) fn type_param_predicates(
743735
ast_generics,
744736
def_id,
745737
ty,
746-
OnlySelfBounds(true),
747-
Some(assoc_name),
738+
PredicateFilter::SelfThatDefines(assoc_name),
748739
)
749740
.into_iter()
750741
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
@@ -768,8 +759,7 @@ impl<'tcx> ItemCtxt<'tcx> {
768759
ast_generics: &'tcx hir::Generics<'tcx>,
769760
param_def_id: LocalDefId,
770761
ty: Ty<'tcx>,
771-
only_self_bounds: OnlySelfBounds,
772-
assoc_name: Option<Ident>,
762+
filter: PredicateFilter,
773763
) -> Vec<(ty::Clause<'tcx>, Span)> {
774764
let mut bounds = Bounds::default();
775765

@@ -778,9 +768,23 @@ impl<'tcx> ItemCtxt<'tcx> {
778768
continue;
779769
};
780770

771+
let (only_self_bounds, assoc_name) = match filter {
772+
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
773+
(OnlySelfBounds(false), None)
774+
}
775+
PredicateFilter::SelfOnly => (OnlySelfBounds(true), None),
776+
PredicateFilter::SelfThatDefines(assoc_name) => {
777+
(OnlySelfBounds(true), Some(assoc_name))
778+
}
779+
};
780+
781+
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
782+
// want to only consider predicates with `Self: ...`, but we don't want
783+
// `OnlySelfBounds(true)` since we want to collect the nested associated
784+
// type bound as well.
781785
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
782786
ty
783-
} else if !only_self_bounds.0 {
787+
} else if matches!(filter, PredicateFilter::All) {
784788
self.to_ty(predicate.bounded_ty)
785789
} else {
786790
continue;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
3+
#![feature(associated_type_bounds)]
4+
5+
trait Trait: Super<Assoc: Bound> {}
6+
7+
trait Super {
8+
type Assoc;
9+
}
10+
11+
trait Bound {}
12+
13+
fn foo<T>(x: T)
14+
where
15+
T: Trait,
16+
{
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// edition:2021
2+
// check-pass
3+
4+
#![feature(async_fn_in_trait, return_position_impl_trait_in_trait, return_type_notation)]
5+
//~^ WARN the feature `return_type_notation` is incomplete
6+
7+
use std::future::Future;
8+
9+
struct JoinHandle<T>(fn() -> T);
10+
11+
fn spawn<T>(_: impl Future<Output = T>) -> JoinHandle<T> {
12+
todo!()
13+
}
14+
15+
trait Foo {
16+
async fn bar(&self) -> i32;
17+
}
18+
19+
trait SendFoo: Foo<bar(): Send> + Send {}
20+
21+
fn foobar(foo: impl SendFoo) -> JoinHandle<i32> {
22+
spawn(async move {
23+
let future = foo.bar();
24+
future.await
25+
})
26+
}
27+
28+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/rtn-implied-in-supertrait.rs:4:68
3+
|
4+
LL | #![feature(async_fn_in_trait, return_position_impl_trait_in_trait, return_type_notation)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: 1 warning emitted
11+

0 commit comments

Comments
 (0)