From 1db284ecb0039798a09e53a519219c5c556c9b38 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 7 Sep 2020 09:38:09 +0100 Subject: [PATCH] Avoid creating useless projection predicate --- .../rustc_typeck/src/check/compare_method.rs | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 817b4070754..4acc7451a21 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1205,16 +1205,27 @@ pub fn check_type_bounds<'tcx>( // ParamEnv for normalization specifically. let normalize_param_env = { let mut predicates = param_env.caller_bounds().iter().collect::>(); - predicates.push( - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - item_def_id: trait_ty.def_id, - substs: rebased_substs, - }, - ty: impl_ty_value, - }) - .to_predicate(tcx), - ); + match impl_ty_value.kind() { + ty::Projection(proj) + if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs => + { + // Don't include this predicate if the projected type is + // exactly the same as the projection. This can occur in + // (somewhat dubious) code like this: + // + // impl X for T where T: X { type Y = ::Y; } + } + _ => predicates.push( + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + item_def_id: trait_ty.def_id, + substs: rebased_substs, + }, + ty: impl_ty_value, + }) + .to_predicate(tcx), + ), + }; ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing) };