Sort elaborated existential predicates in object_ty_for_trait

This commit is contained in:
Michael Goulet 2022-10-12 05:10:29 +00:00
parent 0938e1680d
commit 4a8cfe9d14
2 changed files with 43 additions and 11 deletions

View File

@ -581,17 +581,24 @@ fn object_ty_for_trait<'tcx>(
}); });
debug!(?trait_predicate); debug!(?trait_predicate);
let elaborated_predicates = elaborate_trait_ref(tcx, trait_ref).filter_map(|obligation| { let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
debug!(?obligation); .filter_map(|obligation| {
let pred = obligation.predicate.to_opt_poly_projection_pred()?; debug!(?obligation);
Some(pred.map_bound(|p| { let pred = obligation.predicate.to_opt_poly_projection_pred()?;
ty::ExistentialPredicate::Projection(ty::ExistentialProjection { Some(pred.map_bound(|p| {
item_def_id: p.projection_ty.item_def_id, ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
substs: p.projection_ty.substs, item_def_id: p.projection_ty.item_def_id,
term: p.term, substs: p.projection_ty.substs,
}) term: p.term,
})) })
}); }))
})
.collect();
// NOTE: Since #37965, the existential predicates list has depended on the
// list of predicates to be sorted. This is mostly to enforce that the primary
// predicate comes first.
elaborated_predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
elaborated_predicates.dedup();
let existential_predicates = tcx let existential_predicates = tcx
.mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates)); .mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates));

View File

@ -0,0 +1,25 @@
// check-pass
use std::future::Future;
pub trait Service {
type Response;
type Future: Future<Output = Self::Response>;
}
pub trait A1: Service<Response = i32> {}
pub trait A2: Service<Future = Box<dyn Future<Output = i32>>> + A1 {
fn foo(&self) {}
}
pub trait B1: Service<Future = Box<dyn Future<Output = i32>>> {}
pub trait B2: Service<Response = i32> + B1 {
fn foo(&self) {}
}
fn main() {
let x: &dyn A2 = todo!();
let x: &dyn B2 = todo!();
}