diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 44d6f076f5d..6eeb28e32f1 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -753,17 +753,27 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); let impl_ty = impl_ty.subst(self.tcx, impl_substs); + debug!("impl_ty: {:?}", impl_ty); + // Determine the receiver type that the method itself expects. - let xform_tys = self.xform_self_ty(&item, impl_ty, impl_substs); + let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(&item, impl_ty, impl_substs); + debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty); // We can't use normalize_associated_types_in as it will pollute the // fcx's fulfillment context after this probe is over. + // Note: we only normalize `xform_self_ty` here since the normalization + // of the return type can lead to inference results that prohibit + // valid canidates from being found, see issue #85671 + // FIXME Postponing the normalization of the return type likely only hides a deeper bug, + // which might be caused by the `param_env` itself. The clauses of the `param_env` + // maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized, + // see isssue #89650 let cause = traits::ObligationCause::misc(self.span, self.body_id); let selcx = &mut traits::SelectionContext::new(self.fcx); - let traits::Normalized { value: (xform_self_ty, xform_ret_ty), obligations } = - traits::normalize(selcx, self.param_env, cause, xform_tys); + let traits::Normalized { value: xform_self_ty, obligations } = + traits::normalize(selcx, self.param_env, cause, xform_self_ty); debug!( - "assemble_inherent_impl_probe: xform_self_ty = {:?}/{:?}", + "assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}", xform_self_ty, xform_ret_ty ); @@ -1420,6 +1430,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }; let mut result = ProbeResult::Match; + let mut xform_ret_ty = probe.xform_ret_ty; + debug!(?xform_ret_ty); + let selcx = &mut traits::SelectionContext::new(self); let cause = traits::ObligationCause::misc(self.span, self.body_id); @@ -1428,7 +1441,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // match as well (or at least may match, sometimes we // don't have enough information to fully evaluate). match probe.kind { - InherentImplCandidate(substs, ref ref_obligations) => { + 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 traits::Normalized { + value: normalized_xform_ret_ty, + obligations: normalization_obligations, + } = traits::normalize(selcx, self.param_env, cause.clone(), probe.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(); let impl_bounds = self.tcx.predicates_of(impl_def_id); @@ -1442,7 +1465,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { 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 { let o = self.resolve_vars_if_possible(o); @@ -1527,9 +1552,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } if let ProbeResult::Match = result { - if let (Some(return_ty), Some(xform_ret_ty)) = - (self.return_type, probe.xform_ret_ty) - { + if let (Some(return_ty), Some(xform_ret_ty)) = (self.return_type, xform_ret_ty) { let xform_ret_ty = self.resolve_vars_if_possible(xform_ret_ty); debug!( "comparing return_ty {:?} with xform ret ty {:?}", @@ -1669,6 +1692,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.static_candidates.push(source); } + #[instrument(level = "debug", skip(self))] fn xform_self_ty( &self, item: &ty::AssocItem, @@ -1683,9 +1707,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn xform_method_sig(&self, method: DefId, substs: SubstsRef<'tcx>) -> ty::FnSig<'tcx> { let fn_sig = self.tcx.fn_sig(method); - debug!("xform_self_ty(fn_sig={:?}, substs={:?})", fn_sig, substs); + debug!(?fn_sig); assert!(!substs.has_escaping_bound_vars());