Skip to content

Commit 04c208b

Browse files
estebankMark-Simulacrum
authored andcommitted
Perform obligation deduplication to avoid buggy ExistentialMismatch
Fix rust-lang#59326.
1 parent 5ceb946 commit 04c208b

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

src/librustc_middle/ty/relate.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -617,12 +617,22 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
617617
a: &Self,
618618
b: &Self,
619619
) -> RelateResult<'tcx, Self> {
620-
if a.len() != b.len() {
620+
let tcx = relation.tcx();
621+
622+
// FIXME: this is wasteful, but want to do a perf run to see how slow it is.
623+
// We need to perform this deduplication as we sometimes generate duplicate projections
624+
// in `a`.
625+
let mut a_v: Vec<_> = a.into_iter().collect();
626+
let mut b_v: Vec<_> = b.into_iter().collect();
627+
a_v.sort_by(|a, b| a.stable_cmp(tcx, b));
628+
a_v.dedup();
629+
b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
630+
b_v.dedup();
631+
if a_v.len() != b_v.len() {
621632
return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
622633
}
623634

624-
let tcx = relation.tcx();
625-
let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
635+
let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
626636
use crate::ty::ExistentialPredicate::*;
627637
match (ep_a, ep_b) {
628638
(Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),

src/test/ui/issues/issue-59326.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// check-pass
2+
trait Service {
3+
type S;
4+
}
5+
6+
trait Framing {
7+
type F;
8+
}
9+
10+
impl Framing for () {
11+
type F = ();
12+
}
13+
14+
trait HttpService<F: Framing>: Service<S = F::F> {}
15+
16+
type BoxService = Box<dyn HttpService<(), S = ()>>;
17+
18+
fn build_server<F: FnOnce() -> BoxService>(_: F) {}
19+
20+
fn make_server<F: Framing>() -> Box<dyn HttpService<F, S = F::F>> {
21+
unimplemented!()
22+
}
23+
24+
fn main() {
25+
build_server(|| make_server())
26+
}

0 commit comments

Comments
 (0)