From 4a8cfe9d14f479ebc2e156f08ac33e8b4ed0d08a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 12 Oct 2022 05:10:29 +0000 Subject: [PATCH] Sort elaborated existential predicates in object_ty_for_trait --- .../src/traits/object_safety.rs | 29 ++++++++++++------- src/test/ui/object-safety/issue-102933.rs | 25 ++++++++++++++++ 2 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/object-safety/issue-102933.rs diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 1afa04007b8..545524f63a7 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -581,17 +581,24 @@ fn object_ty_for_trait<'tcx>( }); debug!(?trait_predicate); - let elaborated_predicates = elaborate_trait_ref(tcx, trait_ref).filter_map(|obligation| { - debug!(?obligation); - let pred = obligation.predicate.to_opt_poly_projection_pred()?; - Some(pred.map_bound(|p| { - ty::ExistentialPredicate::Projection(ty::ExistentialProjection { - item_def_id: p.projection_ty.item_def_id, - substs: p.projection_ty.substs, - term: p.term, - }) - })) - }); + let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref) + .filter_map(|obligation| { + debug!(?obligation); + let pred = obligation.predicate.to_opt_poly_projection_pred()?; + Some(pred.map_bound(|p| { + ty::ExistentialPredicate::Projection(ty::ExistentialProjection { + item_def_id: p.projection_ty.item_def_id, + 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 .mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates)); diff --git a/src/test/ui/object-safety/issue-102933.rs b/src/test/ui/object-safety/issue-102933.rs new file mode 100644 index 00000000000..843391cffb2 --- /dev/null +++ b/src/test/ui/object-safety/issue-102933.rs @@ -0,0 +1,25 @@ +// check-pass + +use std::future::Future; + +pub trait Service { + type Response; + type Future: Future; +} + +pub trait A1: Service {} + +pub trait A2: Service>> + A1 { + fn foo(&self) {} +} + +pub trait B1: Service>> {} + +pub trait B2: Service + B1 { + fn foo(&self) {} +} + +fn main() { + let x: &dyn A2 = todo!(); + let x: &dyn B2 = todo!(); +}