Skip to content

Commit 4a8cfe9

Browse files
Sort elaborated existential predicates in object_ty_for_trait
1 parent 0938e16 commit 4a8cfe9

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

compiler/rustc_trait_selection/src/traits/object_safety.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -581,17 +581,24 @@ fn object_ty_for_trait<'tcx>(
581581
});
582582
debug!(?trait_predicate);
583583

584-
let elaborated_predicates = elaborate_trait_ref(tcx, trait_ref).filter_map(|obligation| {
585-
debug!(?obligation);
586-
let pred = obligation.predicate.to_opt_poly_projection_pred()?;
587-
Some(pred.map_bound(|p| {
588-
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
589-
item_def_id: p.projection_ty.item_def_id,
590-
substs: p.projection_ty.substs,
591-
term: p.term,
592-
})
593-
}))
594-
});
584+
let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
585+
.filter_map(|obligation| {
586+
debug!(?obligation);
587+
let pred = obligation.predicate.to_opt_poly_projection_pred()?;
588+
Some(pred.map_bound(|p| {
589+
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
590+
item_def_id: p.projection_ty.item_def_id,
591+
substs: p.projection_ty.substs,
592+
term: p.term,
593+
})
594+
}))
595+
})
596+
.collect();
597+
// NOTE: Since #37965, the existential predicates list has depended on the
598+
// list of predicates to be sorted. This is mostly to enforce that the primary
599+
// predicate comes first.
600+
elaborated_predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
601+
elaborated_predicates.dedup();
595602

596603
let existential_predicates = tcx
597604
.mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates));
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// check-pass
2+
3+
use std::future::Future;
4+
5+
pub trait Service {
6+
type Response;
7+
type Future: Future<Output = Self::Response>;
8+
}
9+
10+
pub trait A1: Service<Response = i32> {}
11+
12+
pub trait A2: Service<Future = Box<dyn Future<Output = i32>>> + A1 {
13+
fn foo(&self) {}
14+
}
15+
16+
pub trait B1: Service<Future = Box<dyn Future<Output = i32>>> {}
17+
18+
pub trait B2: Service<Response = i32> + B1 {
19+
fn foo(&self) {}
20+
}
21+
22+
fn main() {
23+
let x: &dyn A2 = todo!();
24+
let x: &dyn B2 = todo!();
25+
}

0 commit comments

Comments
 (0)