From 366815d81488244277db854d3b061c7c7b2e9e4d Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Fri, 4 Jan 2019 16:24:03 +0200 Subject: [PATCH] stop returning non-principal objects in issue #33140 relate mode Fixes #57162. --- src/librustc/ty/relate.rs | 55 +++++++++++++++---------------- src/test/ui/issues/issue-57162.rs | 7 ++++ 2 files changed, 34 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/issues/issue-57162.rs diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 84e15a751353e..fc467de186aec 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -18,6 +18,8 @@ use rustc_target::spec::abi; use hir as ast; use traits; +use rustc_data_structures::fx::FxHashSet; + pub type RelateResult<'tcx, T> = Result>; #[derive(Clone, Debug)] @@ -601,40 +603,37 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { use ty::ExistentialPredicate::*; let tcx = relation.tcx(); - let (a_buf, b_buf); - let (a_norm, b_norm): (&[_], &[_]) = match relation.trait_object_mode() { - TraitObjectMode::NoSquash => { - (a, b) - } - TraitObjectMode::SquashAutoTraitsIssue33140 => { - // Treat auto-trait "principal" components as equal - // to the non-principal components, to make - // `dyn Send+Sync = dyn Sync+Send`. - let normalize = |d: &[ty::ExistentialPredicate<'tcx>]| { - let mut result: Vec<_> = d.iter().map(|pi| match pi { - Trait(ref a) if tcx.trait_is_auto(a.def_id) => { - AutoTrait(a.def_id) - }, - other => *other - }).collect(); - - result.sort_by(|a, b| a.stable_cmp(tcx, b)); - result.dedup(); - result - }; - - a_buf = normalize(a); - b_buf = normalize(b); - - (&a_buf, &b_buf) + if let TraitObjectMode::SquashAutoTraitsIssue33140 = relation.trait_object_mode() { + // Treat auto-trait "principal" components as equal + // to the non-principal components, to make + // `dyn Send+Sync = dyn Sync+Send`. + // + // In that case,both types will be "fully resolved" (because + // auto-traits can't have type parameters or lifetimes), and we + // can just return either of them - we don't perform a full + // relation because that would "spread" the unnormalized types. + + let auto_traits = |d: &[ty::ExistentialPredicate<'tcx>]| { + d.iter().map(|pi| match pi { + Trait(ref a) if tcx.trait_is_auto(a.def_id) => { + Ok(a.def_id) + }, + AutoTrait(def_id) => Ok(*def_id), + _ => Err(()), + }).collect::, ()>>() + }; + + match (&auto_traits(a), &auto_traits(b)) { + (Ok(a_dids), Ok(b_dids)) if a_dids == b_dids => return Ok(a), + _ => {} } }; - if a_norm.len() != b_norm.len() { + if a.len() != b.len() { return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); } - let v = a_norm.iter().zip(b_norm.iter()).map(|(ep_a, ep_b)| { + let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| { use ty::ExistentialPredicate::*; match (*ep_a, *ep_b) { (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)), diff --git a/src/test/ui/issues/issue-57162.rs b/src/test/ui/issues/issue-57162.rs new file mode 100644 index 0000000000000..abe0887e927b5 --- /dev/null +++ b/src/test/ui/issues/issue-57162.rs @@ -0,0 +1,7 @@ +// compile-pass + +trait Foo {} +impl Foo for dyn Send {} + +impl Foo for T {} +fn main() {}