From 4f15034b55f6c9e134f7644c4571faa5ddb5facb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 9 Jan 2023 06:53:11 +0000 Subject: [PATCH] hack: don't normalize xform_ret_ty for trait/object candidates unless needed --- compiler/rustc_hir_typeck/src/method/probe.rs | 67 ++++++++++++------- ...impl-derived-implicit-sized-bound-2.stderr | 7 -- .../impl-derived-implicit-sized-bound.stderr | 7 -- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 47c072831e3..02b4d5bb2fb 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1523,30 +1523,11 @@ fn consider_probe( }; let mut result = ProbeResult::Match; + let mut xform_ret_ty = probe.xform_ret_ty; + debug!(?xform_ret_ty); + let cause = traits::ObligationCause::misc(self.span, self.body_id); - let xform_ret_ty = if let Some(xform_ret_ty) = probe.xform_ret_ty { - // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`, - // see the reasons mentioned in the comments in `assemble_inherent_impl_probe` - // for why this is necessary - let InferOk { - value: normalized_xform_ret_ty, - obligations: normalization_obligations, - } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); - debug!("xform_ret_ty after normalization: {:?}", normalized_xform_ret_ty); - - for o in normalization_obligations { - if !self.predicate_may_hold(&o) { - possibly_unsatisfied_predicates.push((o.predicate, None, Some(o.cause))); - result = ProbeResult::NoMatch; - } - } - - Some(normalized_xform_ret_ty) - } else { - None - }; - let mut parent_pred = None; // If so, impls may carry other conditions (e.g., where @@ -1555,6 +1536,16 @@ fn consider_probe( // don't have enough information to fully evaluate). match probe.kind { InherentImplCandidate(ref substs, ref ref_obligations) => { + // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`, + // see the reasons mentioned in the comments in `assemble_inherent_impl_probe` + // for why this is necessary + let InferOk { + value: normalized_xform_ret_ty, + obligations: normalization_obligations, + } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); + xform_ret_ty = normalized_xform_ret_ty; + debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); + // Check whether the impl imposes obligations we have to worry about. let impl_def_id = probe.item.container_id(self.tcx); let impl_bounds = self.tcx.predicates_of(impl_def_id); @@ -1572,7 +1563,8 @@ fn consider_probe( let candidate_obligations = impl_obligations .chain(norm_obligations.into_iter()) - .chain(ref_obligations.iter().cloned()); + .chain(ref_obligations.iter().cloned()) + .chain(normalization_obligations.into_iter()); // Evaluate those obligations to see if they might possibly hold. for o in candidate_obligations { @@ -1668,8 +1660,33 @@ fn consider_probe( if let ProbeResult::Match = result && let Some(return_ty) = self.return_type - && let Some(xform_ret_ty) = xform_ret_ty + && let Some(mut xform_ret_ty) = xform_ret_ty { + // `xform_ret_ty` has only been normalized for `InherentImplCandidate`. + // We don't normalize the other candidates for perf/backwards-compat reasons... + // but `self.return_type` is only set on the diagnostic-path, so we + // should be okay doing it here. + if !matches!(probe.kind, InherentImplCandidate(..)) { + let InferOk { + value: normalized_xform_ret_ty, + obligations: normalization_obligations, + } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); + xform_ret_ty = normalized_xform_ret_ty; + debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); + // Evaluate those obligations to see if they might possibly hold. + for o in normalization_obligations { + let o = self.resolve_vars_if_possible(o); + if !self.predicate_may_hold(&o) { + result = ProbeResult::NoMatch; + possibly_unsatisfied_predicates.push(( + o.predicate, + None, + Some(o.cause), + )); + } + } + } + debug!( "comparing return_ty {:?} with xform ret ty {:?}", return_ty, xform_ret_ty @@ -1681,7 +1698,7 @@ fn consider_probe( .sup(return_ty, xform_ret_ty) .is_err() { - return ProbeResult::BadReturnType; + result = ProbeResult::BadReturnType; } } diff --git a/src/test/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr b/src/test/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr index 7cd9788a7d3..543ceac8e91 100644 --- a/src/test/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr +++ b/src/test/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr @@ -17,13 +17,6 @@ LL | impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { | ^ ----------- ------------- | | | unsatisfied trait bound introduced here - = note: the following trait bounds were not satisfied: - `&Victim<'_, Self>: VictimTrait` - `&mut Victim<'_, Self>: VictimTrait` -help: consider relaxing the type parameter's implicit `Sized` bound - | -LL | impl<'a, T: ?Sized + Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { - | ++++++++ help: consider relaxing the type parameter's implicit `Sized` bound | LL | impl<'a, T: ?Sized + Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { diff --git a/src/test/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr b/src/test/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr index 96345df73b4..f08d685836e 100644 --- a/src/test/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr +++ b/src/test/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr @@ -17,13 +17,6 @@ LL | impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { | ^ ----------- ------------- | | | unsatisfied trait bound introduced here - = note: the following trait bounds were not satisfied: - `&Victim<'_, Self>: VictimTrait` - `&mut Victim<'_, Self>: VictimTrait` -help: consider relaxing the type parameter's implicit `Sized` bound - | -LL | impl<'a, T: ?Sized + Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { - | ++++++++ help: consider relaxing the type parameter's implicit `Sized` bound | LL | impl<'a, T: ?Sized + Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> {