about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs18
2 files changed, 22 insertions, 10 deletions
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index a1c7b70bd9c..e579afbf389 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -40,15 +40,17 @@ pub struct OpaqueTypeDecl<'tcx> {
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn replace_opaque_types_with_inference_vars(
+    /// This is a backwards compatibility hack to prevent breaking changes from
+    /// lazy TAIT around RPIT handling.
+    pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<'tcx>>(
         &self,
-        ty: Ty<'tcx>,
+        value: T,
         body_id: HirId,
         span: Span,
         param_env: ty::ParamEnv<'tcx>,
-    ) -> InferOk<'tcx, Ty<'tcx>> {
-        if !ty.has_opaque_types() {
-            return InferOk { value: ty, obligations: vec![] };
+    ) -> InferOk<'tcx, T> {
+        if !value.has_opaque_types() {
+            return InferOk { value, obligations: vec![] };
         }
         let mut obligations = vec![];
         let replace_opaque_type = |def_id: DefId| {
@@ -56,7 +58,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 .as_local()
                 .map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some())
         };
-        let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
+        let value = value.fold_with(&mut ty::fold::BottomUpFolder {
             tcx: self.tcx,
             lt_op: |lt| lt,
             ct_op: |ct| ct,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 74625cc7bb7..715b9749268 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -252,10 +252,20 @@ fn project_and_unify_type<'cx, 'tcx>(
         Err(InProgress) => return ProjectAndUnifyResult::Recursive,
     };
     debug!(?normalized, ?obligations, "project_and_unify_type result");
-    match infcx
-        .at(&obligation.cause, obligation.param_env)
-        .eq(normalized, obligation.predicate.term)
-    {
+    let actual = obligation.predicate.term;
+    // For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs
+    // This allows users to omit re-mentioning all bounds on an associated type and just use an
+    // `impl Trait` for the assoc type to add more bounds.
+    let InferOk { value: actual, obligations: new } =
+        selcx.infcx().replace_opaque_types_with_inference_vars(
+            actual,
+            obligation.cause.body_id,
+            obligation.cause.span,
+            obligation.param_env,
+        );
+    obligations.extend(new);
+
+    match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
         Ok(InferOk { obligations: inferred_obligations, value: () }) => {
             obligations.extend(inferred_obligations);
             ProjectAndUnifyResult::Holds(obligations)