diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 9736c8b89204e..93222c1868651 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return;
             };
 
-            let pick = self.confirm_method(
+            let pick = self.confirm_method_for_diagnostic(
                 call_expr.span,
                 callee_expr,
                 call_expr,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 94e879ae9c3ed..9531c002829ea 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1418,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
             let self_ty = self.normalize(span, self_ty);
             match self.at(&self.misc(span), self.param_env).eq(
-                DefineOpaqueTypes::No,
+                DefineOpaqueTypes::Yes,
                 impl_ty,
                 self_ty,
             ) {
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 3c9a49e91a3f9..120e3239d1f1b 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -497,7 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 args,
             })),
         );
-        match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
+        match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
             }
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index e842bba34bf82..3986374a343f0 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -634,8 +634,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
-        debug!("assemble_probe: self_ty={:?}", self_ty);
         let raw_self_ty = self_ty.value.value;
         match *raw_self_ty.kind() {
             ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
@@ -713,13 +713,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
         if !self.impl_dups.insert(impl_def_id) {
             return; // already visited
         }
 
-        debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
-
         for item in self.impl_or_trait_item(impl_def_id) {
             if !self.has_applicable_self(&item) {
                 // No receiver declared. Not a candidate.
@@ -737,9 +736,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
-        debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty);
-
         let principal = match self_ty.kind() {
             ty::Dynamic(ref data, ..) => Some(data),
             _ => None,
@@ -768,9 +766,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         });
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
         // FIXME: do we want to commit to this behavior for param bounds?
-        debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
 
         let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
             let bound_predicate = predicate.kind();
@@ -826,6 +824,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
         let mut duplicates = FxHashSet::default();
         let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
@@ -842,6 +841,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_all_traits(&mut self) {
         let mut duplicates = FxHashSet::default();
         for trait_info in suggest::all_traits(self.tcx) {
@@ -863,12 +863,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_trait(
         &mut self,
         import_ids: &SmallVec<[LocalDefId; 1]>,
         trait_def_id: DefId,
     ) {
-        debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
         let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
         let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
 
@@ -958,6 +958,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ///////////////////////////////////////////////////////////////////////////
     // THE ACTUAL SEARCH
 
+    #[instrument(level = "debug", skip(self))]
     fn pick(mut self) -> PickResult<'tcx> {
         assert!(self.method_name.is_some());
 
@@ -1386,6 +1387,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
     fn consider_probe(
         &self,
         self_ty: Ty<'tcx>,
@@ -1415,15 +1417,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, impl_ty, impl_args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
+                    match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
                         Err(err) => {
                             debug!("--> cannot relate self-types {:?}", err);
                             return ProbeResult::NoMatch;
@@ -1484,19 +1479,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
-                        Err(err) => {
-                            debug!("--> cannot relate self-types {:?}", err);
+                    match self_ty.kind() {
+                        // HACK: opaque types will match anything for which their bounds hold.
+                        // Thus we need to prevent them from trying to match the `&_` autoref
+                        // candidates that get created for `&self` trait methods.
+                        ty::Alias(ty::Opaque, alias_ty)
+                            if self.infcx.can_define_opaque_ty(alias_ty.def_id)
+                                && !xform_self_ty.is_ty_var() =>
+                        {
                             return ProbeResult::NoMatch;
                         }
+                        _ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                            Ok(()) => {}
+                            Err(err) => {
+                                debug!("--> cannot relate self-types {:?}", err);
+                                return ProbeResult::NoMatch;
+                            }
+                        },
                     }
                     let obligation = traits::Obligation::new(
                         self.tcx,
@@ -1536,15 +1535,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
+                    match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
                         Err(err) => {
                             debug!("--> cannot relate self-types {:?}", err);
                             return ProbeResult::NoMatch;
@@ -1665,6 +1657,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     /// Similarly to `probe_for_return_type`, this method attempts to find the best matching
     /// candidate method where the method name may have been misspelled. Similarly to other
     /// edit distance based suggestions, we provide at most one such suggestion.
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn probe_for_similar_candidate(
         &mut self,
     ) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 50b6c77e1b29d..4fad721ce9847 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> {
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct MethodAutoderefStepsResult<'tcx> {
-    /// The valid autoderef steps that could be find.
+    /// The valid autoderef steps that could be found.
     pub steps: &'tcx [CandidateStep<'tcx>],
     /// If Some(T), a type autoderef reported an error on.
     pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
diff --git a/tests/ui/impl-trait/call_method_ambiguous.next.stderr b/tests/ui/impl-trait/call_method_ambiguous.next.stderr
new file mode 100644
index 0000000000000..cd222aa7ae9fc
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_ambiguous.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_ambiguous.rs:29:13
+   |
+LL |         let mut iter = foo(n - 1, m);
+   |             ^^^^^^^^
+LL |
+LL |         assert_eq!(iter.get(), 1);
+   |                    ---- type must be known at this point
+   |
+help: consider giving `iter` an explicit type
+   |
+LL |         let mut iter: /* Type */ = foo(n - 1, m);
+   |                     ++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_ambiguous.rs b/tests/ui/impl-trait/call_method_ambiguous.rs
new file mode 100644
index 0000000000000..c26c01e002d85
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_ambiguous.rs
@@ -0,0 +1,39 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] run-pass
+
+#![feature(precise_capturing)]
+#![allow(incomplete_features)]
+
+trait Get {
+    fn get(&mut self) -> u32;
+}
+
+impl Get for () {
+    fn get(&mut self) -> u32 {
+        0
+    }
+}
+
+impl<T> Get for &mut T
+where
+    T: Get,
+{
+    fn get(&mut self) -> u32 {
+        T::get(self) + 1
+    }
+}
+
+fn foo(n: usize, m: &mut ()) -> impl use<'_> Get {
+    if n > 0 {
+        let mut iter = foo(n - 1, m);
+        //[next]~^ type annotations needed
+        assert_eq!(iter.get(), 1);
+    }
+    m
+}
+
+fn main() {
+    let g = foo(1, &mut ()).get();
+    assert_eq!(g, 1);
+}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
new file mode 100644
index 0000000000000..271051f120abc
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_on_inherent_impl.rs:18:13
+   |
+LL |         let x = my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |         - type must be known at this point
+   |
+help: consider giving `x` an explicit type
+   |
+LL |         let x: /* Type */ = my_foo();
+   |              ++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.rs b/tests/ui/impl-trait/call_method_on_inherent_impl.rs
new file mode 100644
index 0000000000000..17f7cad660db1
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl.rs
@@ -0,0 +1,25 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] check-pass
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl<T> MyDebug for T
+where
+    T: std::fmt::Debug,
+{
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    if false {
+        let x = my_foo();
+        //[next]~^ type annotations needed
+        x.my_debug();
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr
new file mode 100644
index 0000000000000..6ecb2b05fc56b
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `my_debug` found for reference `&impl Debug` in the current scope
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:16:11
+   |
+LL |         x.my_debug();
+   |           ^^^^^^^^ method not found in `&impl Debug`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:4:1
+   |
+LL | trait MyDebug {
+   | ^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr
new file mode 100644
index 0000000000000..5fb0b8f1d14b2
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed for `&_`
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:14:13
+   |
+LL |         let x = &my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |           -------- type must be known at this point
+   |
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
+   |
+LL |         let x: &_ = &my_foo();
+   |              ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs
new file mode 100644
index 0000000000000..7fb2ff3b2bcc6
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs
@@ -0,0 +1,22 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl MyDebug for &() {
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    if false {
+        let x = &my_foo();
+        //[next]~^ ERROR: type annotations needed
+        x.my_debug();
+        //[current]~^ ERROR: no method named `my_debug`
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
new file mode 100644
index 0000000000000..fe6e166cb4fa1
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
@@ -0,0 +1,40 @@
+error[E0599]: no method named `my_debug` found for opaque type `impl Debug` in the current scope
+  --> $DIR/call_method_on_inherent_impl_ref.rs:20:11
+   |
+LL |     fn my_debug(&self);
+   |        -------- the method is available for `&impl Debug` here
+...
+LL |         x.my_debug();
+   |           ^^^^^^^^ method not found in `impl Debug`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
+  --> $DIR/call_method_on_inherent_impl_ref.rs:4:1
+   |
+LL | trait MyDebug {
+   | ^^^^^^^^^^^^^
+
+error[E0391]: cycle detected when computing type of opaque `my_foo::{opaque#0}`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:15:16
+   |
+LL | fn my_foo() -> impl std::fmt::Debug {
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `my_foo`...
+  --> $DIR/call_method_on_inherent_impl_ref.rs:20:9
+   |
+LL |         x.my_debug();
+   |         ^
+   = note: ...which requires evaluating trait selection obligation `my_foo::{opaque#0}: core::marker::Unpin`...
+   = note: ...which again requires computing type of opaque `my_foo::{opaque#0}`, completing the cycle
+note: cycle used when computing type of `my_foo::{opaque#0}`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:15:16
+   |
+LL | fn my_foo() -> impl std::fmt::Debug {
+   |                ^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0391, E0599.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
new file mode 100644
index 0000000000000..327f6ca3450f1
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
@@ -0,0 +1,31 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_on_inherent_impl_ref.rs:18:13
+   |
+LL |         let x = my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |         - type must be known at this point
+   |
+help: consider giving `x` an explicit type
+   |
+LL |         let x: /* Type */ = my_foo();
+   |              ++++++++++++
+
+error[E0282]: type annotations needed for `&_`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:28:13
+   |
+LL |         let x = &my_bar();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |           -------- type must be known at this point
+   |
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
+   |
+LL |         let x: &_ = &my_bar();
+   |              ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
new file mode 100644
index 0000000000000..40ad21532a4e2
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
@@ -0,0 +1,35 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl<T> MyDebug for &T
+where
+    T: std::fmt::Debug,
+{
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    //[current]~^ cycle
+    if false {
+        let x = my_foo();
+        //[next]~^ type annotations needed
+        x.my_debug();
+        //[current]~^ no method named `my_debug` found
+    }
+    ()
+}
+
+fn my_bar() -> impl std::fmt::Debug {
+    if false {
+        let x = &my_bar();
+        //[next]~^ type annotations needed
+        x.my_debug();
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_without_import.no_import.stderr b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
new file mode 100644
index 0000000000000..72982b695bbb0
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
@@ -0,0 +1,37 @@
+error[E0599]: no method named `fmt` found for opaque type `impl Debug` in the current scope
+  --> $DIR/call_method_without_import.rs:17:11
+   |
+LL |         x.fmt(f);
+   |           ^^^ method not found in `impl Debug`
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   |
+   = note: the method is available for `impl Debug` here
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: trait `Debug` which provides `fmt` is implemented but not in scope; perhaps you want to import it
+   |
+LL + use std::fmt::Debug;
+   |
+
+error[E0599]: no method named `fmt` found for mutable reference `&mut impl Debug` in the current scope
+  --> $DIR/call_method_without_import.rs:26:11
+   |
+LL |         x.fmt(f);
+   |           ^^^ method not found in `&mut impl Debug`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following traits which provide `fmt` are implemented but not in scope; perhaps you want to import one of them
+   |
+LL + use std::fmt::Binary;
+   |
+LL + use std::fmt::Debug;
+   |
+LL + use std::fmt::Display;
+   |
+LL + use std::fmt::LowerExp;
+   |
+     and 5 other candidates
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/call_method_without_import.rs b/tests/ui/impl-trait/call_method_without_import.rs
new file mode 100644
index 0000000000000..d62777ea2835d
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_without_import.rs
@@ -0,0 +1,42 @@
+//! Test that opaque types only pick up methods from traits in their bounds
+//! if the trait is imported.
+//!
+//! FIXME: always look through the bounds of an opaque type to see if there are
+//! methods that could be called on any of the bound traits, irrespective of
+//! imported traits.
+
+//@ revisions: import no_import
+//@[import] check-pass
+
+#[cfg(import)]
+use std::fmt::Debug as _;
+
+fn foo(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug {
+    if false {
+        let x = foo(f);
+        x.fmt(f);
+        //[no_import]~^ ERROR: no method named `fmt` found
+    }
+    ()
+}
+
+fn foo1(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug {
+    if false {
+        let x = &mut foo(f);
+        x.fmt(f);
+        //[no_import]~^ ERROR: no method named `fmt` found
+    }
+    ()
+}
+
+// inconsistent with this
+fn bar<T>(t: impl std::fmt::Debug, f: &mut std::fmt::Formatter<'_>) {
+    t.fmt(f);
+}
+
+// and the desugared version, of course
+fn baz<T: std::fmt::Debug>(t: T, f: &mut std::fmt::Formatter<'_>) {
+    t.fmt(f);
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution.rs b/tests/ui/impl-trait/method-resolution.rs
new file mode 100644
index 0000000000000..60fbacd86462b
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution.rs
@@ -0,0 +1,26 @@
+//! Since there is only one possible `bar` method, we invoke it and subsequently
+//! constrain `foo`'s RPIT to `u32`.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+trait Trait {}
+
+impl Trait for u32 {}
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Sized> {
+    if x {
+        let x = foo(false);
+        x.bar();
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution2.next.stderr b/tests/ui/impl-trait/method-resolution2.next.stderr
new file mode 100644
index 0000000000000..223430e1658b4
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution2.next.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution2.rs:25:11
+   |
+LL |         x.bar();
+   |           ^^^ multiple `bar` found
+   |
+note: candidate #1 is defined in an impl for the type `Bar<T>`
+  --> $DIR/method-resolution2.rs:19:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution2.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution2.rs b/tests/ui/impl-trait/method-resolution2.rs
new file mode 100644
index 0000000000000..88d4f3d9896c7
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution2.rs
@@ -0,0 +1,31 @@
+//! Check that the method call does not constrain the RPIT to `i32`, even though
+//! `i32` is the only type that satisfies the RPIT's trait bounds.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] check-pass
+
+trait Trait {}
+
+impl Trait for i32 {}
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+impl<T: Trait> Bar<T> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Trait> {
+    if x {
+        let x = foo(false);
+        x.bar();
+        //[next]~^ ERROR: multiple applicable items in scope
+    }
+    Bar(42_i32)
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution3.current.stderr b/tests/ui/impl-trait/method-resolution3.current.stderr
new file mode 100644
index 0000000000000..87dd862ef8f4f
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.current.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution3.rs:21:11
+   |
+LL |         x.bar();
+   |           ^^^ multiple `bar` found
+   |
+note: candidate #1 is defined in an impl for the type `Bar<i32>`
+  --> $DIR/method-resolution3.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution3.rs:11:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution3.next.stderr b/tests/ui/impl-trait/method-resolution3.next.stderr
new file mode 100644
index 0000000000000..87dd862ef8f4f
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.next.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution3.rs:21:11
+   |
+LL |         x.bar();
+   |           ^^^ multiple `bar` found
+   |
+note: candidate #1 is defined in an impl for the type `Bar<i32>`
+  --> $DIR/method-resolution3.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution3.rs:11:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution3.rs b/tests/ui/impl-trait/method-resolution3.rs
new file mode 100644
index 0000000000000..8c47ef4fc75c7
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.rs
@@ -0,0 +1,27 @@
+//! Check that we consider `Bar<impl Sized>` to successfully unify
+//! with both `Bar<u32>` and `Bar<i32>` (in isolation), so we bail
+//! out with ambiguity.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+impl Bar<i32> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Sized> {
+    if x {
+        let x = foo(false);
+        x.bar();
+        //~^ ERROR: multiple applicable items in scope
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution4.next.stderr b/tests/ui/impl-trait/method-resolution4.next.stderr
new file mode 100644
index 0000000000000..b48de0af3579d
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution4.next.stderr
@@ -0,0 +1,22 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-resolution4.rs:13:9
+   |
+LL |         foo(false).next().unwrap();
+   |         ^^^^^^^^^^ cannot infer type
+
+error[E0308]: mismatched types
+  --> $DIR/method-resolution4.rs:16:5
+   |
+LL | fn foo(b: bool) -> impl Iterator<Item = ()> {
+   |                    ------------------------ the expected opaque type
+...
+LL |     std::iter::empty()
+   |     ^^^^^^^^^^^^^^^^^^ types differ
+   |
+   = note: expected opaque type `impl Iterator<Item = ()>`
+                   found struct `std::iter::Empty<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0308.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs
new file mode 100644
index 0000000000000..91884eb59fd63
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution4.rs
@@ -0,0 +1,20 @@
+//! The recursive method call yields the opaque type. The
+//! `next` method call then constrains the hidden type to `&mut _`
+//! because `next` takes `&mut self`. We never resolve the inference
+//! variable, but get a type mismatch when comparing `&mut _` with
+//! `std::iter::Empty`.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] check-pass
+
+fn foo(b: bool) -> impl Iterator<Item = ()> {
+    if b {
+        foo(false).next().unwrap();
+        //[next]~^ type annotations needed
+    }
+    std::iter::empty()
+    //[next]~^ mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/recursive-parent-trait-method-call.rs b/tests/ui/impl-trait/recursive-parent-trait-method-call.rs
new file mode 100644
index 0000000000000..4da9a06a4659b
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-parent-trait-method-call.rs
@@ -0,0 +1,42 @@
+//! This test checks that we can resolve the `boxed` method call to `FutureExt`,
+//! because we know that the anonymous future does not implement `StreamExt`.
+
+//@ edition: 2021
+//@ check-pass
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait FutureExt: Future + Sized + Send + 'static {
+    fn boxed(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>> {
+        Box::pin(self)
+    }
+}
+
+trait StreamExt: Future + Sized + Send + 'static {
+    fn boxed(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>> {
+        Box::pin(self)
+    }
+}
+
+impl<T: Future + Sized + Send + 'static> FutureExt for T {}
+
+fn go(i: usize) -> impl Future<Output = ()> + Send + 'static {
+    async move {
+        if i != 0 {
+            spawn(async move {
+                let fut = go(i - 1).boxed();
+                fut.await;
+            })
+            .await;
+        }
+    }
+}
+
+pub fn spawn<T: Send>(
+    _: impl Future<Output = T> + Send + 'static,
+) -> impl Future<Output = ()> + Send + 'static {
+    async move { todo!() }
+}
+
+fn main() {}
diff --git a/tests/ui/methods/opaque_param_in_ufc.rs b/tests/ui/methods/opaque_param_in_ufc.rs
index a4b27a0131fd0..b170e6805f646 100644
--- a/tests/ui/methods/opaque_param_in_ufc.rs
+++ b/tests/ui/methods/opaque_param_in_ufc.rs
@@ -1,4 +1,7 @@
 #![feature(type_alias_impl_trait)]
+
+//@ check-pass
+
 struct Foo<T>(T);
 
 impl Foo<u32> {
@@ -15,14 +18,11 @@ fn bar() -> Bar {
 impl Foo<Bar> {
     fn foo() -> Bar {
         Self::method();
-        //~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
         Foo::<Bar>::method();
-        //~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
         let x = Foo(bar());
         Foo::method2(x);
         let x = Self(bar());
         Self::method2(x);
-        //~^ ERROR: no function or associated item named `method2` found for struct `Foo<Bar>`
         todo!()
     }
 }
diff --git a/tests/ui/methods/opaque_param_in_ufc.stderr b/tests/ui/methods/opaque_param_in_ufc.stderr
deleted file mode 100644
index 7e5bbbac8a9ab..0000000000000
--- a/tests/ui/methods/opaque_param_in_ufc.stderr
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:17:15
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method` not found for this struct
-...
-LL |         Self::method();
-   |               ^^^^^^ function or associated item not found in `Foo<Bar>`
-   |
-   = note: the function or associated item was found for
-           - `Foo<u32>`
-
-error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:19:21
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method` not found for this struct
-...
-LL |         Foo::<Bar>::method();
-   |                     ^^^^^^ function or associated item not found in `Foo<Bar>`
-   |
-   = note: the function or associated item was found for
-           - `Foo<u32>`
-
-error[E0599]: no function or associated item named `method2` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:24:15
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method2` not found for this struct
-...
-LL |         Self::method2(x);
-   |               ^^^^^^^ function or associated item not found in `Foo<Bar>`
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
new file mode 100644
index 0000000000000..a9c05ad33424d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
+  --> $DIR/method_resolution.rs:21:14
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         self.bar()
+   |              ^^^ method not found in `Bar<u32>`
+   |
+   = note: the method was found for
+           - `Bar<Foo>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
new file mode 100644
index 0000000000000..6b34358a56ea3
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
+  --> $DIR/method_resolution.rs:21:14
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         self.bar()
+   |              ^^^ method cannot be called on `Bar<u32>` due to unsatisfied trait bounds
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.rs b/tests/ui/type-alias-impl-trait/method_resolution.rs
new file mode 100644
index 0000000000000..f636aba15c0c4
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.rs
@@ -0,0 +1,30 @@
+//! `Bar<u32>::foo` is not defining `Foo`, so it cannot rely on the fact that
+//! `u32` is the hidden type of `Foo` to call `bar`
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(mut self) {
+        self.0 = 42_u32;
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {
+        self.bar()
+        //~^ ERROR: no method named `bar`
+    }
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.rs b/tests/ui/type-alias-impl-trait/method_resolution2.rs
new file mode 100644
index 0000000000000..f69661db79922
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution2.rs
@@ -0,0 +1,28 @@
+//! Check that we do unify `Bar<Foo>` with `Bar<u32>`, as the
+//! `foo` method call can be resolved unambiguously by doing so.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self) {
+        self.foo()
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {}
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
new file mode 100644
index 0000000000000..e992d059daf7d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
@@ -0,0 +1,21 @@
+error[E0307]: invalid `self` parameter type: `Bar<u32>`
+  --> $DIR/method_resolution3.rs:16:18
+   |
+LL |     fn bar(self: Bar<u32>) {
+   |                  ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0307]: invalid `self` parameter type: `&Bar<u32>`
+  --> $DIR/method_resolution3.rs:21:18
+   |
+LL |     fn baz(self: &Bar<u32>) {
+   |                  ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
new file mode 100644
index 0000000000000..9272017cdf5d1
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
@@ -0,0 +1,15 @@
+error[E0271]: type mismatch resolving `Foo == u32`
+  --> $DIR/method_resolution3.rs:16:18
+   |
+LL |     fn bar(self: Bar<u32>) {
+   |                  ^^^^^^^^ types differ
+
+error[E0271]: type mismatch resolving `Foo == u32`
+  --> $DIR/method_resolution3.rs:21:18
+   |
+LL |     fn baz(self: &Bar<u32>) {
+   |                  ^^^^^^^^^ types differ
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.rs b/tests/ui/type-alias-impl-trait/method_resolution3.rs
new file mode 100644
index 0000000000000..447f3144b822c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.rs
@@ -0,0 +1,36 @@
+//! Check that one cannot use arbitrary self types where a generic parameter
+//! mismatches with an opaque type. In theory this could unify with the opaque
+//! type, registering the generic parameter as the hidden type of the opaque type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait, arbitrary_self_types)]
+
+type Foo = impl Copy;
+
+#[derive(Copy, Clone)]
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self: Bar<u32>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `Foo == u32`
+        self.foo()
+    }
+    fn baz(self: &Bar<u32>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `Foo == u32`
+        self.foo()
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {}
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
new file mode 100644
index 0000000000000..3a2ca18f89097
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
@@ -0,0 +1,21 @@
+error[E0307]: invalid `self` parameter type: `Bar<Foo>`
+  --> $DIR/method_resolution4.rs:27:18
+   |
+LL |     fn foo(self: Bar<Foo>) {
+   |                  ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
+  --> $DIR/method_resolution4.rs:32:20
+   |
+LL |     fn foomp(self: &Bar<Foo>) {
+   |                    ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
new file mode 100644
index 0000000000000..33ed2800ebe0c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
@@ -0,0 +1,15 @@
+error[E0271]: type mismatch resolving `u32 == Foo`
+  --> $DIR/method_resolution4.rs:27:18
+   |
+LL |     fn foo(self: Bar<Foo>) {
+   |                  ^^^^^^^^ types differ
+
+error[E0271]: type mismatch resolving `u32 == Foo`
+  --> $DIR/method_resolution4.rs:32:20
+   |
+LL |     fn foomp(self: &Bar<Foo>) {
+   |                    ^^^^^^^^^ types differ
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.rs b/tests/ui/type-alias-impl-trait/method_resolution4.rs
new file mode 100644
index 0000000000000..42ed04b3c30f6
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.rs
@@ -0,0 +1,39 @@
+//! Check that one cannot use arbitrary self types where a generic parameter
+//! mismatches with an opaque type. In theory this could unify with the opaque
+//! type, registering the generic parameter as the hidden type of the opaque type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait, arbitrary_self_types)]
+
+mod foo {
+    pub type Foo = impl Copy;
+
+    fn foo() -> Foo {
+        42_u32
+    }
+}
+use foo::Foo;
+
+#[derive(Copy, Clone)]
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self) {}
+}
+
+impl Bar<u32> {
+    fn foo(self: Bar<Foo>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
+        self.bar()
+    }
+    fn foomp(self: &Bar<Foo>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
+        self.bar()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.rs b/tests/ui/type-alias-impl-trait/method_resolution5.rs
new file mode 100644
index 0000000000000..64355e4560de2
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution5.rs
@@ -0,0 +1,33 @@
+//! Even though `Bar<u32>::foo` is defining `Foo`, the old solver does
+//! not figure out that `u32` is the hidden type of `Foo` to call `bar`.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(mut self) {
+        self.0 = 42_u32;
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self)
+    where
+        Foo:,
+    {
+        self.bar()
+    }
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
new file mode 100644
index 0000000000000..f331da1af8793
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
@@ -0,0 +1,15 @@
+error: item does not constrain `Tait::{opaque#0}`, but has it in its signature
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:24:8
+   |
+LL |     fn foo(&mut self) {
+   |        ^^^
+   |
+   = note: consider moving the opaque type's declaration and defining uses into a separate module
+note: this opaque type is in the signature
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:17:13
+   |
+LL | type Tait = impl Iterator<Item = ()>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
new file mode 100644
index 0000000000000..2617ce124c105
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9
+   |
+LL |         self.bar.next().unwrap();
+   |         ^^^^^^^^ cannot infer type
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
new file mode 100644
index 0000000000000..b6adf08853f2f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
@@ -0,0 +1,31 @@
+//! This test demonstrates how method calls will attempt to unify an opaque type with a reference
+//! if the method takes `&self` as its argument. This is almost never what is desired, as the user
+//! would like to have method resolution happen on the opaque type instead of inferring the hidden
+//! type. Once type-alias-impl-trait requires annotating which functions should constrain the hidden
+//! type, this won't be as much of a problem, as most functions that do method calls on opaque types
+//! won't also be the ones defining the hidden type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait)]
+
+pub struct Foo {
+    bar: Tait,
+}
+
+type Tait = impl Iterator<Item = ()>;
+
+impl Foo {
+    pub fn new() -> Foo {
+        Foo { bar: std::iter::empty() }
+    }
+
+    fn foo(&mut self) {
+        //[current]~^ ERROR: item does not constrain
+        self.bar.next().unwrap();
+        //[next]~^ ERROR: type annotations needed
+    }
+}
+
+fn main() {}