about summary refs log tree commit diff
diff options
context:
space:
mode:
authorb-naber <bn263@gmx.de>2021-10-08 01:32:03 +0200
committerb-naber <bn263@gmx.de>2021-10-08 10:55:44 +0200
commitcbf91532a7bfb2f2ce23067b13cc44659f7883d2 (patch)
tree77463330536d1b6f4ae0c2a70e3a9585bfb0202c
parent5641481ad735c742cc669bb1e47f10116b789ee7 (diff)
downloadrust-cbf91532a7bfb2f2ce23067b13cc44659f7883d2.tar.gz
rust-cbf91532a7bfb2f2ce23067b13cc44659f7883d2.zip
dont normalize return type during candidate assembly in method probing
-rw-r--r--compiler/rustc_typeck/src/check/method/probe.rs45
1 files changed, 35 insertions, 10 deletions
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());