From d693a98f4ef508299c7c6550d9fb79d81f818d84 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github35764891676564198441@oli-obk.de>
Date: Mon, 19 Jul 2021 16:38:14 +0000
Subject: [PATCH 1/7] Fix VecMap::iter_mut

It used to allow you to mutate the key, even though that can invalidate the map by creating duplicate keys.
---
 compiler/rustc_data_structures/src/lib.rs     |  1 +
 compiler/rustc_data_structures/src/vec_map.rs | 10 +++++-----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 16151e9dca5e0..4467980054f54 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -24,6 +24,7 @@
 #![feature(new_uninit)]
 #![feature(once_cell)]
 #![feature(maybe_uninit_uninit_array)]
+#![feature(min_type_alias_impl_trait)]
 #![allow(rustc::default_hash_types)]
 #![deny(unaligned_references)]
 
diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs
index 1786fa340cc8b..96e33184658a3 100644
--- a/compiler/rustc_data_structures/src/vec_map.rs
+++ b/compiler/rustc_data_structures/src/vec_map.rs
@@ -1,6 +1,6 @@
 use std::borrow::Borrow;
 use std::iter::FromIterator;
-use std::slice::{Iter, IterMut};
+use std::slice::Iter;
 use std::vec::IntoIter;
 
 use crate::stable_hasher::{HashStable, StableHasher};
@@ -67,7 +67,7 @@ where
         self.into_iter()
     }
 
-    pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
+    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
         self.into_iter()
     }
 }
@@ -108,12 +108,12 @@ impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
 }
 
 impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
-    type Item = &'a mut (K, V);
-    type IntoIter = IterMut<'a, (K, V)>;
+    type Item = (&'a K, &'a mut V);
+    type IntoIter = impl Iterator<Item = Self::Item>;
 
     #[inline]
     fn into_iter(self) -> Self::IntoIter {
-        self.0.iter_mut()
+        self.0.iter_mut().map(|(k, v)| (&*k, v))
     }
 }
 

From 6d76002baf9d03372b05c96c7cdd7e89c501bdb0 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github35764891676564198441@oli-obk.de>
Date: Mon, 19 Jul 2021 16:50:43 +0000
Subject: [PATCH 2/7] Make mir borrowck's use of opaque types independent of
 the typeck query's result

---
 compiler/rustc_data_structures/src/vec_map.rs |   4 +
 .../src/borrow_check/type_check/mod.rs        | 149 ++++++++----------
 .../assoc-type-eq-with-dyn-atb-fail.rs        |   1 -
 .../assoc-type-eq-with-dyn-atb-fail.stderr    |   8 +-
 src/test/ui/impl-trait/auto-trait-leak.rs     |   1 -
 src/test/ui/impl-trait/auto-trait-leak.stderr |  34 ++--
 ...does_not_live_long_enough.full_tait.stderr |  11 +-
 ..._does_not_live_long_enough.min_tait.stderr |  11 +-
 .../generic_type_does_not_live_long_enough.rs |   1 -
 .../issue-57611-trait-alias.full_tait.stderr  |  49 +-----
 .../issue-57611-trait-alias.min_tait.stderr   |  49 +-----
 .../issue-57611-trait-alias.rs                |   4 -
 .../ui/type-alias-impl-trait/issue-60371.rs   |   1 -
 .../type-alias-impl-trait/issue-60371.stderr  |  13 +-
 .../ui/type-alias-impl-trait/issue-74761-2.rs |  19 +++
 .../issue-74761-2.stderr                      |  34 ++++
 .../multiple-def-uses-in-one-fn2.rs           |   2 +-
 .../multiple-def-uses-in-one-fn2.stderr       |  14 +-
 .../multiple-def-uses-in-one-fn3.rs           |   1 +
 .../multiple-def-uses-in-one-fn3.stderr       |  17 +-
 20 files changed, 162 insertions(+), 261 deletions(-)
 create mode 100644 src/test/ui/type-alias-impl-trait/issue-74761-2.rs
 create mode 100644 src/test/ui/type-alias-impl-trait/issue-74761-2.stderr

diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs
index 96e33184658a3..e3fa587985df0 100644
--- a/compiler/rustc_data_structures/src/vec_map.rs
+++ b/compiler/rustc_data_structures/src/vec_map.rs
@@ -70,6 +70,10 @@ where
     pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
         self.into_iter()
     }
+
+    pub fn retain(&mut self, f: impl Fn(&(K, V)) -> bool) {
+        self.0.retain(f)
+    }
 }
 
 impl<K, V> Default for VecMap<K, V> {
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index aa3ff98f7ff9f..de327047a872a 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -26,7 +26,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts};
+use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
 use rustc_middle::ty::{
     self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid,
     ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness,
@@ -60,7 +60,6 @@ use crate::borrow_check::{
         LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
     },
     region_infer::{ClosureRegionRequirementsExt, TypeTest},
-    renumber,
     type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
     universal_regions::{DefiningTy, UniversalRegions},
     Upvar,
@@ -180,7 +179,66 @@ pub(crate) fn type_check<'mir, 'tcx>(
             liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
 
             translate_outlives_facts(&mut cx);
-            cx.opaque_type_values
+            let mut opaque_type_values = cx.opaque_type_values;
+
+            for (_, revealed_ty) in &mut opaque_type_values {
+                // FIXME(oli-obk): Instead of looping, implement a visitor like
+                // FullTypeResolver. We can't use FullTypeResolver here, as that will
+                // resolve lifetimes lexically, which it can't because we didn't do old
+                // borrowck stuff. We want to use MIR borrowck information instead.
+
+                while revealed_ty.has_infer_types_or_consts() {
+                    let prev = *revealed_ty;
+                    trace!(prev=?prev.kind());
+                    let type_resolved = infcx.shallow_resolve(prev);
+                    trace!(type_resolved=?type_resolved.kind());
+                    if prev == type_resolved {
+                        infcx.tcx.sess.delay_span_bug(
+                            body.span,
+                            &format!("could not resolve {:#?}", type_resolved.kind()),
+                        );
+                        *revealed_ty = infcx.tcx.ty_error();
+                        break;
+                    }
+                    *revealed_ty = type_resolved;
+                }
+            }
+
+            opaque_type_values.retain(|(opaque_type_key, resolved_ty)| {
+                let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
+                    *def_id == opaque_type_key.def_id
+                } else {
+                    false
+                };
+
+                if concrete_is_opaque {
+                    // We're using an opaque `impl Trait` type without
+                    // 'revealing' it. For example, code like this:
+                    //
+                    // type Foo = impl Debug;
+                    // fn foo1() -> Foo { ... }
+                    // fn foo2() -> Foo { foo1() }
+                    //
+                    // In `foo2`, we're not revealing the type of `Foo` - we're
+                    // just treating it as the opaque type.
+                    //
+                    // When this occurs, we do *not* want to try to equate
+                    // the concrete type with the underlying defining type
+                    // of the opaque type - this will always fail, since
+                    // the defining type of an opaque type is always
+                    // some other type (e.g. not itself)
+                    // Essentially, none of the normal obligations apply here -
+                    // we're just passing around some unknown opaque type,
+                    // without actually looking at the underlying type it
+                    // gets 'revealed' into
+                    debug!(
+                        "eq_opaque_type_and_type: non-defining use of {:?}",
+                        opaque_type_key.def_id,
+                    );
+                }
+                !concrete_is_opaque
+            });
+            opaque_type_values
         },
     );
 
@@ -1240,13 +1298,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
 
         let infcx = self.infcx;
-        let tcx = infcx.tcx;
         let param_env = self.param_env;
         let body = self.body;
         let mir_def_id = body.source.def_id().expect_local();
 
-        // the "concrete opaque types" maps
-        let concrete_opaque_types = &tcx.typeck(mir_def_id).concrete_opaque_types;
         let mut opaque_type_values = VecMap::new();
 
         debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id);
@@ -1296,88 +1351,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             .eq(output_ty, revealed_ty)?,
                     );
 
-                    // For each opaque type `Foo<T>` inferred by this value, we want to equate
-                    // the inference variable `?T` with the revealed type that was computed
-                    // earlier by type check.
                     for &(opaque_type_key, opaque_decl) in &opaque_type_map {
-                        let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
-                        let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
-                            *def_id == opaque_type_key.def_id
-                        } else {
-                            false
-                        };
-
-                        // The revealed type computed by the earlier phase of type check.
-                        // In our example, this would be `(U, u32)`. Note that this references
-                        // the type parameter `U` from the definition of `Foo`.
-                        let concrete_ty = match concrete_opaque_types
-                            .get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
-                        {
-                            None => {
-                                if !concrete_is_opaque {
-                                    tcx.sess.delay_span_bug(
-                                        body.span,
-                                        &format!(
-                                            "Non-defining use of {:?} with revealed type",
-                                            opaque_type_key.def_id,
-                                        ),
-                                    );
-                                }
-                                continue;
-                            }
-                            Some(concrete_ty) => concrete_ty,
-                        };
-                        debug!("concrete_ty = {:?}", concrete_ty);
-
-                        // Apply the substitution, in this case `[U -> T]`, so that the
-                        // concrete type becomes `Foo<(T, u32)>`
-                        let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs);
-
-                        // "Renumber" this, meaning that we replace all the regions
-                        // with fresh inference variables. Not relevant to our example.
-                        let renumbered_opaque_defn_ty =
-                            renumber::renumber_regions(infcx, subst_opaque_defn_ty);
-
-                        debug!(
-                            "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
-                            concrete_ty, resolved_ty, renumbered_opaque_defn_ty,
-                        );
-
-                        if !concrete_is_opaque {
-                            // Equate the instantiated opaque type `opaque_decl.concrete_ty` (`?T`,
-                            // in our example) with the renumbered version that we took from
-                            // the type check results (`Foo<(T, u32)>`).
-                            obligations.add(
-                                infcx
-                                    .at(&ObligationCause::dummy(), param_env)
-                                    .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
-                            );
-                            opaque_type_values.insert(opaque_type_key, renumbered_opaque_defn_ty);
-                        } else {
-                            // We're using an opaque `impl Trait` type without
-                            // 'revealing' it. For example, code like this:
-                            //
-                            // type Foo = impl Debug;
-                            // fn foo1() -> Foo { ... }
-                            // fn foo2() -> Foo { foo1() }
-                            //
-                            // In `foo2`, we're not revealing the type of `Foo` - we're
-                            // just treating it as the opaque type.
-                            //
-                            // When this occurs, we do *not* want to try to equate
-                            // the concrete type with the underlying defining type
-                            // of the opaque type - this will always fail, since
-                            // the defining type of an opaque type is always
-                            // some other type (e.g. not itself)
-                            // Essentially, none of the normal obligations apply here -
-                            // we're just passing around some unknown opaque type,
-                            // without actually looking at the underlying type it
-                            // gets 'revealed' into
-                            debug!(
-                                "eq_opaque_type_and_type: non-defining use of {:?}",
-                                opaque_type_key.def_id,
-                            );
-                        }
+                        opaque_type_values.insert(opaque_type_key, opaque_decl.concrete_ty);
                     }
 
                     debug!("eq_opaque_type_and_type: equated");
diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
index 73b23da5bcb66..7950dd3e99e29 100644
--- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
+++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
@@ -29,7 +29,6 @@ impl Bar for AssocNoCopy {
 impl Thing for AssocNoCopy {
     type Out = Box<dyn Bar<Assoc: Copy>>;
     //~^ ERROR the trait bound `String: Copy` is not satisfied
-    //~| ERROR the trait bound `String: Copy` is not satisfied
 
     fn func() -> Self::Out {
         Box::new(AssocNoCopy)
diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
index 414d74d4786d9..0f1d35be0eb7a 100644
--- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
+++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
@@ -4,12 +4,6 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
 LL |     type Out = Box<dyn Bar<Assoc: Copy>>;
    |                            ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
 
-error[E0277]: the trait bound `String: Copy` is not satisfied
-  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
-   |
-LL |     type Out = Box<dyn Bar<Assoc: Copy>>;
-   |                            ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
index 087f4582b21c3..c2fbbf94fd666 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -12,7 +12,6 @@ fn main() {
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
     send(cycle2().clone());
-    //~^ ERROR cannot be sent between threads safely
 
     Rc::new(Cell::new(5))
 }
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index e578c4b4f819e..3eb141cc2bb55 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -36,37 +36,37 @@ LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires computing type of `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:20:16
+  --> $DIR/auto-trait-leak.rs:19:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,22 +84,6 @@ LL | |     Rc::new(String::from("foo"))
 LL | | }
    | |_^
 
-error[E0277]: `Rc<String>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak.rs:14:5
-   |
-LL | fn send<T: Send>(_: T) {}
-   |            ---- required by this bound in `send`
-...
-LL |     send(cycle2().clone());
-   |     ^^^^ `Rc<String>` cannot be sent between threads safely
-...
-LL | fn cycle2() -> impl Clone {
-   |                ---------- within this `impl Clone`
-   |
-   = help: within `impl Clone`, the trait `Send` is not implemented for `Rc<String>`
-   = note: required because it appears within the type `impl Clone`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0277, E0391.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr
index 6394a1f8e8509..90a753b5a6de1 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr
@@ -36,16 +36,7 @@ LL | type WrongGeneric<T> = impl 'static;
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
 
-error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:24
-   |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0308, E0310.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr
index 49ead8b094c19..e50282201074e 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr
@@ -27,16 +27,7 @@ LL | type WrongGeneric<T> = impl 'static;
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
 
-error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:24
-   |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0308, E0310.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
index 3dda34ff668ce..9f647d9e737fe 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
@@ -11,7 +11,6 @@ fn main() {
 
 type WrongGeneric<T> = impl 'static;
 //~^ ERROR the parameter type `T` may not live long enough
-//~| ERROR the parameter type `T` may not live long enough
 //~| ERROR: at least one trait must be specified
 
 fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr
index d90f328708a7b..61e8da91bbaa9 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr
@@ -16,52 +16,5 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to previous error; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr
index d019f40757eed..f65e91e52c713 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr
@@ -7,52 +7,5 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
index ccc727e0bf01b..508ecdd88a482 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
@@ -19,10 +19,6 @@ struct X;
 impl Foo for X {
     type Bar = impl Baz<Self, Self>;
     //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR mismatched types
-    //~| ERROR mismatched types
 
     fn bar(&self) -> Self::Bar {
         |x| x
diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs
index b7c8a58a65629..cee5e5a01cc2a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60371.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs
@@ -9,7 +9,6 @@ trait Bug {
 impl Bug for &() {
     type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable
     //~^ ERROR the trait bound `(): Bug` is not satisfied
-    //~^^ ERROR the trait bound `(): Bug` is not satisfied
 
     const FUN: fn() -> Self::Item = || ();
     //~^ ERROR type alias impl trait is not permitted here
diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
index 4906ea9c2e261..a9df74689df29 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
@@ -8,7 +8,7 @@ LL |     type Item = impl Bug;
    = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/issue-60371.rs:14:40
+  --> $DIR/issue-60371.rs:13:40
    |
 LL |     const FUN: fn() -> Self::Item = || ();
    |                                        ^
@@ -25,16 +25,7 @@ LL |     type Item = impl Bug;
    = help: the following implementations were found:
              <&() as Bug>
 
-error[E0277]: the trait bound `(): Bug` is not satisfied
-  --> $DIR/issue-60371.rs:10:17
-   |
-LL |     type Item = impl Bug;
-   |                 ^^^^^^^^ the trait `Bug` is not implemented for `()`
-   |
-   = help: the following implementations were found:
-             <&() as Bug>
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0277, E0658.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.rs b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs
new file mode 100644
index 0000000000000..4b0f2afee5484
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs
@@ -0,0 +1,19 @@
+#![feature(member_constraints)]
+#![feature(type_alias_impl_trait)]
+//~^ WARN incomplete
+
+pub trait A {
+    type B;
+    fn f(&self) -> Self::B;
+}
+impl<'a, 'b> A for () {
+    //~^ ERROR the lifetime parameter `'a` is not constrained
+    //~| ERROR the lifetime parameter `'b` is not constrained
+    type B = impl core::fmt::Debug;
+    //~^ ERROR is unstable
+
+
+    fn f(&self) -> Self::B {}
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr
new file mode 100644
index 0000000000000..4506a6e23d5c0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr
@@ -0,0 +1,34 @@
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/issue-74761-2.rs:12:14
+   |
+LL |     type B = impl core::fmt::Debug;
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable
+
+warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-74761-2.rs:2:12
+   |
+LL | #![feature(type_alias_impl_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-74761-2.rs:9:6
+   |
+LL | impl<'a, 'b> A for () {
+   |      ^^ unconstrained lifetime parameter
+
+error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-74761-2.rs:9:10
+   |
+LL | impl<'a, 'b> A for () {
+   |          ^^ unconstrained lifetime parameter
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0207, E0658.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
index 38aa18fe40ee7..11756017ad846 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
@@ -5,9 +5,9 @@
 #![feature(min_type_alias_impl_trait)]
 
 type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
-//~^ ERROR could not find defining uses
 
 fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+    //~^ ERROR concrete type differs from previous defining opaque type
     (a.clone(), a)
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
index c00973c0761b0..52b0462de988c 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
@@ -1,8 +1,14 @@
-error: could not find defining uses
-  --> $DIR/multiple-def-uses-in-one-fn2.rs:7:52
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
    |
-LL | type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
-   |                                                    ^^^^^^^^^^^^^
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `B`
+   |
+note: previous use here
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
+   |
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
index 17e900058113d..5f25365666c7f 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
@@ -11,6 +11,7 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>)
 }
 
 fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+    //~^ ERROR concrete type differs from previous defining opaque type
     (a, b)
     //~^ ERROR mismatched types
 }
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
index bbe709dccab4e..3d943b77af57d 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
@@ -1,10 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:15:9
    |
 LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
    |      -                    - found type parameter
    |      |
    |      expected type parameter
+LL |
 LL |     (a, b)
    |         ^ expected type parameter `A`, found type parameter `B`
    |
@@ -13,6 +14,18 @@ LL |     (a, b)
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:13:1
+   |
+LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `[type error]`
+   |
+note: previous use here
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:9:1
+   |
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.

From bdc20e372b09edfaa4c28cd5e5dbb5e2a3c3de62 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github35764891676564198441@oli-obk.de>
Date: Tue, 20 Jul 2021 10:48:56 +0000
Subject: [PATCH 3/7] Use instrument debugging for more readable logs

---
 .../rustc_trait_selection/src/opaque_types.rs | 22 ++++++++-----------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index 39013a317fd9c..95c81c5c729be 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -83,6 +83,7 @@ pub struct OpaqueTypeDecl<'tcx> {
 }
 
 /// Whether member constraints should be generated for all opaque types
+#[derive(Debug)]
 pub enum GenerateMemberConstraints {
     /// The default, used by typeck
     WhenRequired,
@@ -354,8 +355,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         opaque_types: &OpaqueTypeMap<'tcx>,
         free_region_relations: &FRR,
     ) {
-        debug!("constrain_opaque_types()");
-
         for &(opaque_type_key, opaque_defn) in opaque_types {
             self.constrain_opaque_type(
                 opaque_type_key,
@@ -367,6 +366,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     }
 
     /// See `constrain_opaque_types` for documentation.
+    #[instrument(level = "debug", skip(self, free_region_relations))]
     fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
@@ -376,15 +376,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     ) {
         let def_id = opaque_type_key.def_id;
 
-        debug!("constrain_opaque_type()");
-        debug!("constrain_opaque_type: def_id={:?}", def_id);
-        debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn);
-
         let tcx = self.tcx;
 
         let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
 
-        debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
+        debug!(?concrete_ty);
 
         let first_own_region = match opaque_defn.origin {
             hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
@@ -397,7 +393,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 // type foo::<'p0..'pn>::Foo<'q0..'qm>
                 // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
                 //
-                // For these types we onlt iterate over `'l0..lm` below.
+                // For these types we only iterate over `'l0..lm` below.
                 tcx.generics_of(def_id).parent_count
             }
             // These opaque type inherit all lifetime parameters from their
@@ -410,10 +406,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         // If there are required region bounds, we can use them.
         if opaque_defn.has_required_region_bounds {
             let bounds = tcx.explicit_item_bounds(def_id);
-            debug!("constrain_opaque_type: predicates: {:#?}", bounds);
+            debug!("{:#?}", bounds);
             let bounds: Vec<_> =
                 bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect();
-            debug!("constrain_opaque_type: bounds={:#?}", bounds);
+            debug!("{:#?}", bounds);
             let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs);
 
             let required_region_bounds =
@@ -452,8 +448,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             };
 
             // Compute the least upper bound of it with the other regions.
-            debug!("constrain_opaque_types: least_region={:?}", least_region);
-            debug!("constrain_opaque_types: subst_region={:?}", subst_region);
+            debug!(?least_region);
+            debug!(?subst_region);
             match least_region {
                 None => least_region = Some(subst_region),
                 Some(lr) => {
@@ -484,7 +480,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         }
 
         let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
-        debug!("constrain_opaque_types: least_region={:?}", least_region);
+        debug!(?least_region);
 
         if let GenerateMemberConstraints::IfNoStaticBound = mode {
             if least_region != tcx.lifetimes.re_static {

From a8551abd4787e6746d515a656b1e7ab00cf67d4a Mon Sep 17 00:00:00 2001
From: Oli Scherer <github35764891676564198441@oli-obk.de>
Date: Tue, 20 Jul 2021 10:53:23 +0000
Subject: [PATCH 4/7] Remove an unnecessary variable

---
 compiler/rustc_mir/src/borrow_check/type_check/mod.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index de327047a872a..03ffad4a814cb 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -1297,7 +1297,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             return Ok(());
         }
 
-        let infcx = self.infcx;
         let param_env = self.param_env;
         let body = self.body;
         let mir_def_id = body.source.def_id().expect_local();
@@ -1380,7 +1379,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     locations,
                     ConstraintCategory::OpaqueType,
                     CustomTypeOp::new(
-                        |_cx| {
+                        |infcx| {
                             infcx.constrain_opaque_type(
                                 opaque_type_key,
                                 &opaque_decl,

From 9f09a5eb8b9b59360528f24f0c73fdaf6bf3300a Mon Sep 17 00:00:00 2001
From: Oli Scherer <github35764891676564198441@oli-obk.de>
Date: Tue, 20 Jul 2021 15:10:55 +0000
Subject: [PATCH 5/7] Resolve nested inference variables.

I attempted that with the previous code, but I misunderstdood how
`shallow_resolve` works.
---
 .../src/borrow_check/type_check/mod.rs        | 26 +++++--------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index 03ffad4a814cb..3fb06cd2f5f44 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -182,25 +182,13 @@ pub(crate) fn type_check<'mir, 'tcx>(
             let mut opaque_type_values = cx.opaque_type_values;
 
             for (_, revealed_ty) in &mut opaque_type_values {
-                // FIXME(oli-obk): Instead of looping, implement a visitor like
-                // FullTypeResolver. We can't use FullTypeResolver here, as that will
-                // resolve lifetimes lexically, which it can't because we didn't do old
-                // borrowck stuff. We want to use MIR borrowck information instead.
-
-                while revealed_ty.has_infer_types_or_consts() {
-                    let prev = *revealed_ty;
-                    trace!(prev=?prev.kind());
-                    let type_resolved = infcx.shallow_resolve(prev);
-                    trace!(type_resolved=?type_resolved.kind());
-                    if prev == type_resolved {
-                        infcx.tcx.sess.delay_span_bug(
-                            body.span,
-                            &format!("could not resolve {:#?}", type_resolved.kind()),
-                        );
-                        *revealed_ty = infcx.tcx.ty_error();
-                        break;
-                    }
-                    *revealed_ty = type_resolved;
+                *revealed_ty = infcx.resolve_vars_if_possible(*revealed_ty);
+                if revealed_ty.has_infer_types_or_consts() {
+                    infcx.tcx.sess.delay_span_bug(
+                        body.span,
+                        &format!("could not resolve {:#?}", revealed_ty.kind()),
+                    );
+                    *revealed_ty = infcx.tcx.ty_error();
                 }
             }
 

From f2d2fd38ebcd66e69408871568f236d304096ee4 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github35764891676564198441@oli-obk.de>
Date: Tue, 20 Jul 2021 15:16:41 +0000
Subject: [PATCH 6/7] Add a regression test

---
 src/test/ui/impl-trait/issue-86465.rs     | 10 ++++++++++
 src/test/ui/impl-trait/issue-86465.stderr | 14 ++++++++++++++
 2 files changed, 24 insertions(+)
 create mode 100644 src/test/ui/impl-trait/issue-86465.rs
 create mode 100644 src/test/ui/impl-trait/issue-86465.stderr

diff --git a/src/test/ui/impl-trait/issue-86465.rs b/src/test/ui/impl-trait/issue-86465.rs
new file mode 100644
index 0000000000000..23a3748c12c6a
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-86465.rs
@@ -0,0 +1,10 @@
+#![feature(min_type_alias_impl_trait)]
+
+type X<'a, 'b> = impl std::fmt::Debug;
+
+fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+    //~^ ERROR concrete type differs from previous defining opaque type use
+    (a, a)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-86465.stderr b/src/test/ui/impl-trait/issue-86465.stderr
new file mode 100644
index 0000000000000..595b16aa68554
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-86465.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/issue-86465.rs:5:1
+   |
+LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a u32`, got `&'b u32`
+   |
+note: previous use here
+  --> $DIR/issue-86465.rs:5:1
+   |
+LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+

From d10385242d750288bcbd9e1ab06586217cb2fe2b Mon Sep 17 00:00:00 2001
From: Oli Scherer <github35764891676564198441@oli-obk.de>
Date: Thu, 22 Jul 2021 11:26:42 +0000
Subject: [PATCH 7/7] bless nll tests

---
 .../ret-impl-trait-one.nll.stderr                | 16 ++++++----------
 ...ypes_pin_lifetime_impl_trait-async.nll.stderr |  4 ++--
 ...oes_not_live_long_enough.full_tait.nll.stderr |  2 +-
 ...does_not_live_long_enough.min_tait.nll.stderr |  2 +-
 .../issue-57611-trait-alias.full_tait.nll.stderr |  6 +++---
 .../issue-57611-trait-alias.min_tait.nll.stderr  |  6 +++---
 6 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
index eed90772d29e3..b6841da1f0ba9 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
@@ -1,15 +1,11 @@
 error: lifetime may not live long enough
-  --> $DIR/ret-impl-trait-one.rs:10:80
+  --> $DIR/ret-impl-trait-one.rs:10:65
    |
-LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
-   |  ________________________________--__--__________________________________________^
-   | |                                |   |
-   | |                                |   lifetime `'b` defined here
-   | |                                lifetime `'a` defined here
-LL | |
-LL | |     (a, b)
-LL | | }
-   | |_^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |                                --  --                           ^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
+   |                                |   |
+   |                                |   lifetime `'b` defined here
+   |                                lifetime `'a` defined here
    |
    = help: consider adding the following bound: `'b: 'a`
 
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
index a678731934f6e..e25c6363515be 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
@@ -1,8 +1,8 @@
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                          -                     ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+   |                          -          ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
    |                          |
    |                          let's call the lifetime of this reference `'1`
    |
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr
index d0f3be336dccb..28ac61a6b984a 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr
@@ -28,7 +28,7 @@ LL | type WrongGeneric<T> = impl 'static;
            found opaque type `impl Sized`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:17:30
+  --> $DIR/generic_type_does_not_live_long_enough.rs:16:30
    |
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                              ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr
index 7496d96fa2136..b8ca8e46079aa 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr
@@ -19,7 +19,7 @@ LL | type WrongGeneric<T> = impl 'static;
            found opaque type `impl Sized`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:17:30
+  --> $DIR/generic_type_does_not_live_long_enough.rs:16:30
    |
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                              ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr
index 481d66dd8110f..e2b8b19aeba1b 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr
@@ -8,13 +8,13 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
@@ -28,7 +28,7 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'static X,)>`
 note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr
index 0343a769564af..3a4d1d90c0397 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr
@@ -1,11 +1,11 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
@@ -19,7 +19,7 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'static X,)>`
 note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^