about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2023-06-30 12:15:45 +0200
committerlcnr <rust@lcnr.de>2023-07-03 09:12:14 +0200
commitd2c74491890aed653b27dfd02fcd853603d83527 (patch)
tree0807ae2d7dbfd0d405ca94e253257f2a963dd196
parent42067596c2c307e869052c91e1631e0f395a56b6 (diff)
downloadrust-d2c74491890aed653b27dfd02fcd853603d83527.tar.gz
rust-d2c74491890aed653b27dfd02fcd853603d83527.zip
add a `try_structurally_resolve_type` in coerce
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs35
2 files changed, 23 insertions, 14 deletions
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 5f98bacaf2a..9a037f7110e 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1005,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         allow_two_phase: AllowTwoPhase,
         cause: Option<ObligationCause<'tcx>>,
     ) -> RelateResult<'tcx, Ty<'tcx>> {
-        let source = self.resolve_vars_with_obligations(expr_ty);
+        let source = self.try_structurally_resolve_type(expr.span, expr_ty);
         debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
 
         let cause =
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index b1c480e0ded..d21e78e70cf 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1465,16 +1465,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    /// Resolves `typ` by a single level if `typ` is a type variable.
+    /// Try to resolve `ty` to a structural type, normalizing aliases.
     ///
-    /// When the new solver is enabled, this will also attempt to normalize
-    /// the type if it's a projection (note that it will not deeply normalize
-    /// projections within the type, just the outermost layer of the type).
-    ///
-    /// If no resolution is possible, then an error is reported.
-    /// Numeric inference variables may be left unresolved.
-    pub fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let mut ty = self.resolve_vars_with_obligations(ty);
+    /// In case there is still ambiguity, the returned type may be an inference
+    /// variable. This is different from `structurally_resolve_type` which errors
+    /// in this case.
+    pub fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
+        let ty = self.resolve_vars_with_obligations(ty);
 
         if self.next_trait_solver()
             && let ty::Alias(ty::Projection, _) = ty.kind()
@@ -1483,15 +1480,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .at(&self.misc(sp), self.param_env)
                 .structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut())
             {
-                Ok(normalized_ty) => {
-                    ty = normalized_ty;
-                },
+                Ok(normalized_ty) => normalized_ty,
                 Err(errors) => {
                     let guar = self.err_ctxt().report_fulfillment_errors(&errors);
                     return self.tcx.ty_error(guar);
                 }
             }
-        }
+        } else {
+            ty
+       }
+    }
+
+    /// Resolves `ty` by a single level if `ty` is a type variable.
+    ///
+    /// When the new solver is enabled, this will also attempt to normalize
+    /// the type if it's a projection (note that it will not deeply normalize
+    /// projections within the type, just the outermost layer of the type).
+    ///
+    /// If no resolution is possible, then an error is reported.
+    /// Numeric inference variables may be left unresolved.
+    pub fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
+        let ty = self.try_structurally_resolve_type(sp, ty);
 
         if !ty.is_ty_var() {
             ty