Skip to content

Commit 42991e5

Browse files
authored
Rollup merge of #102947 - compiler-errors:sort-elaborated-existentials, r=cjgillot
Sort elaborated existential predicates in `object_ty_for_trait` r? `@cjgillot` I think that #102845 caused #102933. Depending on the order that we elaborate these existential projection predicates, there's no guarantee that they'll be sorted by def id, which is what is failing the assertion in the issue. Fixes #102933 Fixes #102973
2 parents dbff6a9 + 4a8cfe9 commit 42991e5

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)