about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-28 09:51:39 +0000
committerbors <bors@rust-lang.org>2024-03-28 09:51:39 +0000
commit551abd65bee759c1fd1cc0acd5ba7e5723823c54 (patch)
treea7f0f76f260e7ed98cac5068bf8ed7341f1b210f /tests
parentd0e8cbbd99ccc1be12b1aa743521ed89268e59a2 (diff)
parent59c217fed2bc74f3685bf3461674f6b3c7e113c3 (diff)
downloadrust-551abd65bee759c1fd1cc0acd5ba7e5723823c54.tar.gz
rust-551abd65bee759c1fd1cc0acd5ba7e5723823c54.zip
Auto merge of #116891 - aliemjay:opaque-region-infer-rework-2, r=compiler-errors,oli-obk
rework opaque type region inference

User-facing changes are documented in [this comment](https://github.com/rust-lang/rust/pull/116891#issuecomment-1973774412).

The design document is in [this comment](https://github.com/rust-lang/rust/pull/116891#issuecomment-1836900102).

---

\- Fix Ice in check_unique; ICE -> Error; fixes #122782.
\- Ignore uncaptured lifetime args; ICE -> Pass; fixes #111906, fixes #110623, fixes #109059, fixes #122307
\- Except equal parameters from the uniqueness check; Pass -> Error; fixes #113916.
\- Check RPITs for invalid args; Pass -> Error; fixes #111935; ICE -> Error; fixes #110726.
\- Rework opaque types region inference; Pass -> Error; fixes #113971, fixes #112841.
\- Reject external lifetimes as invalid args; Pass -> Error; fixes #105498.

r? `@ghost`
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr12
-rw-r--r--tests/ui/impl-trait/defining-use-captured-non-universal-region.rs22
-rw-r--r--tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr12
-rw-r--r--tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs74
-rw-r--r--tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs13
-rw-r--r--tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs16
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr2
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr2
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.rs2
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs4
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr24
-rw-r--r--tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr13
-rw-r--r--tests/ui/impl-trait/rpit/early_bound.rs1
-rw-r--r--tests/ui/impl-trait/rpit/early_bound.stderr12
-rw-r--r--tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs37
-rw-r--r--tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr31
-rw-r--r--tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs18
-rw-r--r--tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs22
-rw-r--r--tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs19
-rw-r--r--tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr21
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs37
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr59
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs52
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs38
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr27
-rw-r--r--tests/ui/type-alias-impl-trait/lifetime_mismatch.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr69
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr53
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch4.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch4.stderr12
35 files changed, 594 insertions, 164 deletions
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr
new file mode 100644
index 00000000000..ded9a92d8e8
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/defining-use-captured-non-universal-region.rs:13:18
+   |
+LL | fn foo<'a>() -> impl Sized + 'a {
+   |                              -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     let i: i32 = foo::<'_>();
+   |                  ^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs
new file mode 100644
index 00000000000..e18302dc061
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs
@@ -0,0 +1,22 @@
+// This was an ICE. See #110726.
+
+//@ revisions: statik infer fixed
+//@ [fixed] check-pass
+#![allow(unconditional_recursion)]
+
+fn foo<'a>() -> impl Sized + 'a {
+    #[cfg(statik)]
+    let i: i32 = foo::<'static>();
+    //[statik]~^ ERROR expected generic lifetime parameter, found `'static`
+
+    #[cfg(infer)]
+    let i: i32 = foo::<'_>();
+    //[infer]~^ ERROR expected generic lifetime parameter, found `'_`
+
+    #[cfg(fixed)]
+    let i: i32 = foo::<'a>();
+
+    i
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr
new file mode 100644
index 00000000000..43beb29f9ec
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/defining-use-captured-non-universal-region.rs:9:18
+   |
+LL | fn foo<'a>() -> impl Sized + 'a {
+   |                              -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+LL |     #[cfg(statik)]
+LL |     let i: i32 = foo::<'static>();
+   |                  ^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs
new file mode 100644
index 00000000000..56e099c28d2
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs
@@ -0,0 +1,74 @@
+// issue: #110623
+//@ check-pass
+
+use std::{collections::BTreeMap, num::ParseIntError, str::FromStr};
+
+enum FileSystem {
+    File(usize),
+    Directory(BTreeMap<String, FileSystem>),
+}
+
+impl FromStr for FileSystem {
+    type Err = ParseIntError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        if s.starts_with("dir") {
+            Ok(Self::new_dir())
+        } else {
+            Ok(Self::File(s.split_whitespace().next().unwrap().parse()?))
+        }
+    }
+}
+
+impl FileSystem {
+    fn new_dir() -> FileSystem {
+        FileSystem::Directory(BTreeMap::new())
+    }
+
+    fn insert(&mut self, name: String, other: FileSystem) -> Option<FileSystem> {
+        match self {
+            FileSystem::File(_) => panic!("can only insert into directory!"),
+            FileSystem::Directory(tree) => tree.insert(name, other),
+        }
+    }
+
+    // Recursively build a tree from commands. This uses (abuses?)
+    // the fact that `cd /` only appears at the start and that
+    // subsequent `cd`s can only move ONE level to use the recursion
+    // stack as the filesystem stack
+    fn build<'a>(
+        &mut self,
+        mut commands: impl Iterator<Item = &'a str> + 'a,
+    ) -> Option<impl Iterator<Item = &'a str> + 'a> {
+        let cmd = commands.next()?;
+        let mut elements = cmd.lines();
+        match elements.next().map(str::trim) {
+            Some("cd /") | None => self.build(commands),
+            Some("cd ..") => {
+                // return to higher scope
+                Some(commands)
+            }
+            Some("ls") => {
+                for item in elements {
+                    let name = item.split_whitespace().last().unwrap();
+                    let prior = self.insert(name.to_string(), item.parse().unwrap());
+                    debug_assert!(prior.is_none());
+                }
+                // continue on
+                self.build(commands)
+            }
+            Some(other_cd) => {
+                let name = other_cd
+                    .trim()
+                    .strip_prefix("cd ")
+                    .expect("expected a cd command");
+                let mut directory = FileSystem::new_dir();
+                let further_commands = directory.build(commands);
+                self.insert(name.to_string(), directory);
+                self.build(further_commands?) // THIS LINE FAILS TO COMPILE
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs
new file mode 100644
index 00000000000..a6dcad3face
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+trait Bar<const FOO: &'static str> {}
+impl Bar<"asdf"> for () {}
+
+fn foo<const FOO: &'static str>() -> impl Bar<"asdf"> {
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs
new file mode 100644
index 00000000000..f90ff51c651
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs
@@ -0,0 +1,16 @@
+// issue: #111906
+//@ check-pass
+
+#![allow(unconditional_recursion)]
+
+fn foo<'a: 'a>() -> impl Sized {
+    let _: () = foo::<'a>();
+    loop {}
+}
+
+fn bar<'a: 'a>() -> impl Sized + 'a {
+    let _: *mut &'a () = bar::<'a>();
+    loop {}
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
index 1d648162113..78ef8ec404c 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
@@ -1,4 +1,4 @@
-error: {foo<DefId(..)_'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
+error: {foo<'{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
   --> $DIR/erased-regions-in-hidden-ty.rs:12:36
    |
 LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
index 1d648162113..78ef8ec404c 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
@@ -1,4 +1,4 @@
-error: {foo<DefId(..)_'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
+error: {foo<'{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
   --> $DIR/erased-regions-in-hidden-ty.rs:12:36
    |
 LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
index 9d71685f179..e60f1badcae 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
@@ -10,7 +10,7 @@
 // Make sure that the compiler can handle `ReErased` in the hidden type of an opaque.
 
 fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
-    //~^ ERROR 'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
+    //~^ ERROR '{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
     // Can't write whole type because of lack of path sanitization
     || ()
 }
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
index 15778662375..199cbbf4fcc 100644
--- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
@@ -2,10 +2,8 @@
 use std::fmt::Debug;
 
 fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
-    //~^ ERROR cannot resolve opaque type
-
     |x| x
-    //~^ ERROR concrete type differs from previous defining opaque type use
+    //~^ ERROR expected generic lifetime parameter, found `'_`
 }
 
 fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) {
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
index c19420bbb0c..6064b09ef09 100644
--- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
@@ -1,21 +1,11 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/impl-fn-predefined-lifetimes.rs:7:9
-   |
-LL |     |x| x
-   |         ^ expected `impl Debug + '_`, got `&u8`
-   |
-note: previous use here
-  --> $DIR/impl-fn-predefined-lifetimes.rs:7:5
-   |
-LL |     |x| x
-   |     ^^^^^
-
-error[E0720]: cannot resolve opaque type
-  --> $DIR/impl-fn-predefined-lifetimes.rs:4:35
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/impl-fn-predefined-lifetimes.rs:5:9
    |
 LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
-   |                                   ^^^^^^^^^^^^^^^ cannot resolve opaque type
+   |                                                -- this generic parameter must be used with a generic lifetime parameter
+LL |     |x| x
+   |         ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
index 41d5f0f6449..5b3a4eb53ff 100644
--- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
+++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
@@ -5,6 +5,7 @@ trait Foo {
     fn bar<'other: 'a>() -> impl Sized + 'a {}
     //~^ ERROR use of undeclared lifetime name `'a`
     //~| ERROR use of undeclared lifetime name `'a`
+    //~| ERROR expected generic lifetime parameter, found `'static`
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
index b0832eb33ca..8975578dabd 100644
--- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
+++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
@@ -28,6 +28,15 @@ help: consider introducing lifetime `'a` here
 LL | trait Foo<'a> {
    |          ++++
 
-error: aborting due to 2 previous errors
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/bad-item-bound-within-rpitit-2.rs:5:45
+   |
+LL |     fn bar<'other: 'a>() -> impl Sized + 'a {}
+   |            ------                           ^^
+   |            |
+   |            cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0261`.
+Some errors have detailed explanations: E0261, E0792.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/impl-trait/rpit/early_bound.rs b/tests/ui/impl-trait/rpit/early_bound.rs
index 6dda687929c..005bcea59f2 100644
--- a/tests/ui/impl-trait/rpit/early_bound.rs
+++ b/tests/ui/impl-trait/rpit/early_bound.rs
@@ -5,6 +5,7 @@ fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
     let true = n else { loop {} };
     let _ = || {
         let _ = identity::<&'a ()>(test(false));
+        //~^ ERROR expected generic lifetime parameter, found `'_`
     };
     loop {}
 }
diff --git a/tests/ui/impl-trait/rpit/early_bound.stderr b/tests/ui/impl-trait/rpit/early_bound.stderr
index 780dea4e284..b0c7bd4199c 100644
--- a/tests/ui/impl-trait/rpit/early_bound.stderr
+++ b/tests/ui/impl-trait/rpit/early_bound.stderr
@@ -1,3 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/early_bound.rs:7:17
+   |
+LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
+   |                                          -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |         let _ = identity::<&'a ()>(test(false));
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: concrete type differs from previous defining opaque type use
   --> $DIR/early_bound.rs:3:29
    |
@@ -10,5 +19,6 @@ note: previous use here
 LL |         let _ = identity::<&'a ()>(test(false));
    |                                    ^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs
new file mode 100644
index 00000000000..5e04e6b091a
--- /dev/null
+++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs
@@ -0,0 +1,37 @@
+// issue: #111935
+
+#![allow(unconditional_recursion)]
+
+// Lt indirection is necessary to make the lifetime of the function late-bound,
+// in order to bypass some other bugs.
+type Lt<'lt> = Option<*mut &'lt ()>;
+
+mod statik {
+    use super::*;
+    // invalid defining use: Opaque<'static> := ()
+    fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+        let _: () = foo(Lt::<'static>::None);
+        //~^ ERROR expected generic lifetime parameter, found `'static`
+    }
+}
+
+mod infer {
+    use super::*;
+    // invalid defining use: Opaque<'_> := ()
+    fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+        let _: () = foo(Lt::<'_>::None);
+        //~^ ERROR expected generic lifetime parameter, found `'_`
+    }
+}
+
+mod equal {
+    use super::*;
+    // invalid defining use: Opaque<'a, 'a> := ()
+    // because of the use of equal lifetimes in args
+    fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
+        let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
+        //~^ ERROR non-defining opaque type use in defining scope
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr
new file mode 100644
index 00000000000..d2a224601fb
--- /dev/null
+++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr
@@ -0,0 +1,31 @@
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/non-defining-use-lifetimes.rs:13:16
+   |
+LL |     fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+   |                                           -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+LL |         let _: () = foo(Lt::<'static>::None);
+   |                ^^
+
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/non-defining-use-lifetimes.rs:22:16
+   |
+LL |     fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+   |                                           -- this generic parameter must be used with a generic lifetime parameter
+LL |         let _: () = foo(Lt::<'_>::None);
+   |                ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/non-defining-use-lifetimes.rs:32:16
+   |
+LL |         let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
+   |                ^^
+   |
+note: lifetime used multiple times
+  --> $DIR/non-defining-use-lifetimes.rs:31:58
+   |
+LL |     fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
+   |                                                          ^^   ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs
new file mode 100644
index 00000000000..3b83b2e544b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs
@@ -0,0 +1,18 @@
+// The defining use below has an unconstrained lifetime argument.
+// Opaque<'{empty}, 'a> := ();
+// Make sure we accept it because the lifetime parameter in such position is
+// irrelevant - it is an artifact of how we internally represent opaque
+// generics.
+// See issue #122307 for details.
+
+//@ check-pass
+#![feature(type_alias_impl_trait)]
+#![allow(unconditional_recursion)]
+
+type Opaque<'a> = impl Sized + 'a;
+
+fn test<'a>() -> Opaque<'a> {
+    let _: () = test::<'a>();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
index d97a3010a17..0e1d44e7bb3 100644
--- a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
+++ b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
@@ -8,12 +8,24 @@ impl<T> Equate for T { type Proj = T; }
 trait Indirect { type Ty; }
 impl<A, B: Equate<Proj = A>> Indirect for (A, B) { type Ty = (); }
 
-type Opq = impl Sized;
-fn define_1(_: Opq) {
-    let _ = None::<<(Opq, u8) as Indirect>::Ty>;
+mod basic {
+    use super::*;
+    type Opq = impl Sized;
+    fn define_1(_: Opq) {
+        let _ = None::<<(Opq, u8) as Indirect>::Ty>;
+    }
+    fn define_2() -> Opq {
+        0u8
+    }
 }
-fn define_2() -> Opq {
-    0u8
+
+// `Opq<'a> == &'b u8` shouldn't be an error because `'a == 'b`.
+mod lifetime {
+    use super::*;
+    type Opq<'a> = impl Sized + 'a;
+    fn define<'a: 'b, 'b: 'a>(_: Opq<'a>) {
+        let _ = None::<<(Opq<'a>, &'b u8) as Indirect>::Ty>;
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs
new file mode 100644
index 00000000000..9101e4385b3
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+mod case1 {
+    type Opaque<'x> = impl Sized + 'x;
+    fn foo<'s>() -> Opaque<'s> {
+        let _ = || { let _: Opaque<'s> = (); };
+        //~^ ERROR expected generic lifetime parameter, found `'_`
+    }
+}
+
+mod case2 {
+    type Opaque<'x> = impl Sized + 'x;
+    fn foo<'s>() -> Opaque<'s> {
+        let _ = || -> Opaque<'s> {};
+        //~^ ERROR expected generic lifetime parameter, found `'_`
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr
new file mode 100644
index 00000000000..a8fd1f691dd
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr
@@ -0,0 +1,21 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/defined-in-closure-external-lifetime.rs:6:29
+   |
+LL |     type Opaque<'x> = impl Sized + 'x;
+   |                 -- this generic parameter must be used with a generic lifetime parameter
+LL |     fn foo<'s>() -> Opaque<'s> {
+LL |         let _ = || { let _: Opaque<'s> = (); };
+   |                             ^^^^^^^^^^
+
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/defined-in-closure-external-lifetime.rs:14:34
+   |
+LL |     type Opaque<'x> = impl Sized + 'x;
+   |                 -- this generic parameter must be used with a generic lifetime parameter
+LL |     fn foo<'s>() -> Opaque<'s> {
+LL |         let _ = || -> Opaque<'s> {};
+   |                                  ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
new file mode 100644
index 00000000000..59ba2694a76
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
@@ -0,0 +1,37 @@
+// issue: #112841
+
+#![feature(type_alias_impl_trait)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+mod mod1 {
+    type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    fn test<'a>() -> Opaque<'a, 'a> {}
+    //~^ ERROR non-defining opaque type use in defining scope
+    //~| ERROR non-defining opaque type use in defining scope
+}
+
+mod mod2 {
+    type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {}
+    //~^ ERROR non-defining opaque type use in defining scope
+}
+
+mod mod3 {
+    type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    fn test<'a: 'b, 'b: 'a>(a: &'a str) -> Opaque<'a, 'b> { a }
+    //~^ ERROR non-defining opaque type use in defining scope
+}
+
+// This is similar to the previous cases in that 'a is equal to 'static,
+// which is is some sense an implicit parameter to `Opaque`.
+// For example, given a defining use `Opaque<'a> := &'a ()`,
+// it is ambiguous whether `Opaque<'a> := &'a ()` or `Opaque<'a> := &'static ()`
+mod mod4 {
+    type Opaque<'a> = impl super::Trait<'a, 'a>;
+    fn test<'a: 'static>() -> Opaque<'a> {}
+    //~^ ERROR expected generic lifetime parameter, found `'static`
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr
new file mode 100644
index 00000000000..b08bc8b8268
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr
@@ -0,0 +1,59 @@
+error: non-defining opaque type use in defining scope
+  --> $DIR/equal-lifetime-params-not-ok.rs:10:22
+   |
+LL |     fn test<'a>() -> Opaque<'a, 'a> {}
+   |                      ^^^^^^^^^^^^^^ generic argument `'a` used twice
+   |
+note: for this opaque type
+  --> $DIR/equal-lifetime-params-not-ok.rs:9:27
+   |
+LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/equal-lifetime-params-not-ok.rs:10:37
+   |
+LL |     fn test<'a>() -> Opaque<'a, 'a> {}
+   |                                     ^^
+   |
+note: lifetime used multiple times
+  --> $DIR/equal-lifetime-params-not-ok.rs:9:17
+   |
+LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+   |                 ^^  ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/equal-lifetime-params-not-ok.rs:17:49
+   |
+LL |     fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {}
+   |                                                 ^^
+   |
+note: lifetime used multiple times
+  --> $DIR/equal-lifetime-params-not-ok.rs:16:17
+   |
+LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+   |                 ^^  ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/equal-lifetime-params-not-ok.rs:23:61
+   |
+LL |     fn test<'a: 'b, 'b: 'a>(a: &'a str) -> Opaque<'a, 'b> { a }
+   |                                                             ^
+   |
+note: lifetime used multiple times
+  --> $DIR/equal-lifetime-params-not-ok.rs:22:17
+   |
+LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+   |                 ^^  ^^
+
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/equal-lifetime-params-not-ok.rs:33:42
+   |
+LL |     type Opaque<'a> = impl super::Trait<'a, 'a>;
+   |                 -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+LL |     fn test<'a: 'static>() -> Opaque<'a> {}
+   |                                          ^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs
new file mode 100644
index 00000000000..0ce85a4d6cb
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs
@@ -0,0 +1,52 @@
+// Normally we do not allow equal lifetimes in opaque type generic args at
+// their defining sites. An exception to this rule, however, is when the bounds
+// of the opaque type *require* the lifetimes to be equal.
+// issue: #113916
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+#![feature(impl_trait_in_assoc_type)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+mod equal_params {
+    type Opaque<'a: 'b, 'b: 'a> = impl super::Trait<'a, 'b>;
+    fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {
+        let _ = None::<&'a &'b &'a ()>;
+        0u8
+    }
+}
+
+mod equal_static {
+    type Opaque<'a: 'static> = impl Sized + 'a;
+    fn test<'a: 'static>() -> Opaque<'a> {
+        let _ = None::<&'static &'a ()>;
+        0u8
+    }
+}
+
+mod implied_bounds {
+    trait Traitor {
+        type Assoc;
+        fn define(self) -> Self::Assoc;
+    }
+
+    impl<'a> Traitor for &'static &'a () {
+        type Assoc = impl Sized + 'a;
+        fn define(self) -> Self::Assoc {
+            let _ = None::<&'static &'a ()>;
+            0u8
+        }
+    }
+
+    impl<'a, 'b> Traitor for (&'a &'b (), &'b &'a ()) {
+        type Assoc = impl Sized + 'a + 'b;
+        fn define(self) -> Self::Assoc {
+            let _ = None::<(&'a &'b (), &'b &'a ())>;
+            0u8
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr
new file mode 100644
index 00000000000..e5f86c8c193
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/generic-not-strictly-equal.rs:33:5
+   |
+LL | type Opaque<'a> = impl Copy + Captures<'a>;
+   |             -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     relate(opaque, hidden); // defining use: Opaque<'?1> := u8
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr
new file mode 100644
index 00000000000..693af69d6fa
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr
@@ -0,0 +1,15 @@
+error[E0700]: hidden type for `Opaque<'x>` captures lifetime that does not appear in bounds
+  --> $DIR/generic-not-strictly-equal.rs:33:5
+   |
+LL | type Opaque<'a> = impl Copy + Captures<'a>;
+   |                   ------------------------ opaque type defined here
+LL |
+LL | fn test<'x>(_: Opaque<'x>) {
+   |         -- hidden type `&'x u8` captures the lifetime `'x` as defined here
+...
+LL |     relate(opaque, hidden); // defining use: Opaque<'?1> := u8
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs
new file mode 100644
index 00000000000..a059fd3b822
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs
@@ -0,0 +1,38 @@
+// `Opaque<'?1> := u8` is not a valid defining use here.
+//
+// Due to fundamental limitations of the member constraints algorithm,
+// we require '?1 to be *equal* to some universal region.
+//
+// While '?1 is eventually inferred to be equal to 'x because of the constraint '?1: 'x,
+// we don't consider them equal in the strict sense because they lack the bidirectional outlives
+// constraints ['?1: 'x, 'x: '?1]. In NLL terms, they are not part of the same SCC.
+//
+// See #113971 for details.
+
+//@ revisions: basic member_constraints
+#![feature(type_alias_impl_trait)]
+
+trait Captures<'a> {}
+impl<T> Captures<'_> for T {}
+
+fn ensure_outlives<'a, X: 'a>(_: X) {}
+fn relate<X>(_: X, _: X) {}
+
+type Opaque<'a> = impl Copy + Captures<'a>;
+
+fn test<'x>(_: Opaque<'x>) {
+    let opaque = None::<Opaque<'_>>; // let's call this lifetime '?1
+
+    #[cfg(basic)]
+    let hidden = None::<u8>;
+
+    #[cfg(member_constraints)]
+    let hidden = None::<&'x u8>;
+
+    ensure_outlives::<'x>(opaque); // outlives constraint: '?1: 'x
+    relate(opaque, hidden); // defining use: Opaque<'?1> := u8
+    //[basic]~^ ERROR expected generic lifetime parameter, found `'_`
+    //[member_constraints]~^^ ERROR captures lifetime that does not appear in bounds
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
index ef9fe604ea7..3b54fb7ea99 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
@@ -13,6 +13,7 @@ type FutNothing<'a> = impl 'a + Future<Output = ()>;
 async fn operation(_: &mut ()) -> () {
     //~^ ERROR: concrete type differs from previous
     call(operation).await
+    //~^ ERROR: expected generic lifetime parameter, found `'any`
 }
 
 async fn call<F>(_f: F)
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index cd4982b2480..c41ed0642a4 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -6,20 +6,17 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |
    = note: `FutNothing` must be used in combination with a concrete type within the same module
 
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/hkl_forbidden4.rs:13:1
-   |
-LL | async fn operation(_: &mut ()) -> () {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
-   |
-note: previous use here
+error[E0792]: expected generic lifetime parameter, found `'any`
   --> $DIR/hkl_forbidden4.rs:15:5
    |
+LL | async fn operation(_: &mut ()) -> () {
+   |                       - this generic parameter must be used with a generic lifetime parameter
+LL |
 LL |     call(operation).await
    |     ^^^^^^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'any`
-  --> $DIR/hkl_forbidden4.rs:21:1
+  --> $DIR/hkl_forbidden4.rs:22:1
    |
 LL |   type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                   -- this generic parameter must be used with a generic lifetime parameter
@@ -29,6 +26,18 @@ LL | |
 LL | | }
    | |_^
 
-error: aborting due to 3 previous errors
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/hkl_forbidden4.rs:13:1
+   |
+LL | async fn operation(_: &mut ()) -> () {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
+   |
+note: previous use here
+  --> $DIR/hkl_forbidden4.rs:15:5
+   |
+LL |     call(operation).await
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
index 9ec585d93f5..45a55050c44 100644
--- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
+++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
@@ -5,7 +5,6 @@ type Foo<'a> = impl Sized;
 fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) {
     (x, y)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 type Bar<'a, 'b> = impl std::fmt::Debug;
@@ -13,9 +12,6 @@ type Bar<'a, 'b> = impl std::fmt::Debug;
 fn bar<'x, 'y>(i: &'x i32, j: &'y i32) -> (Bar<'x, 'y>, Bar<'y, 'x>) {
     (i, j)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
index 7f54f47d27d..4f7b0f17407 100644
--- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
@@ -14,53 +14,7 @@ LL |     (x, y)
    |     ^^^^^^
 
 error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:6:5
-   |
-LL |     (x, y)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'a` used here
-   |     lifetime `'b` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:6:5
-   |
-LL |     (x, y)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'x` used here
-   |     lifetime `'y` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
+  --> $DIR/lifetime_mismatch.rs:13:5
    |
 LL |     (i, j)
    |     ^^^^^^
@@ -69,27 +23,10 @@ LL |     (i, j)
    |     lifetime `'y` previously used here
    |
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
+  --> $DIR/lifetime_mismatch.rs:13:5
    |
 LL |     (i, j)
    |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
index 5bec38c5e5b..580fb58ef83 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
@@ -3,11 +3,8 @@
 type Foo<'a, 'b> = impl std::fmt::Debug;
 
 fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
-    (i, i)
+    (i, j)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
index 0ccb3e2221d..b2b9e604a6b 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
@@ -1,7 +1,7 @@
 error: opaque type used twice with different lifetimes
   --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
    |
-LL |     (i, i)
+LL |     (i, j)
    |     ^^^^^^
    |     |
    |     lifetime `'x` used here
@@ -10,55 +10,8 @@ LL |     (i, i)
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
   --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
    |
-LL |     (i, i)
+LL |     (i, j)
    |     ^^^^^^
 
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'x` used here
-   |     lifetime `'y` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.rs b/tests/ui/type-alias-impl-trait/param_mismatch4.rs
new file mode 100644
index 00000000000..e072f3ab8e0
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/param_mismatch4.rs
@@ -0,0 +1,16 @@
+//! This test checks that when checking for opaque types that
+//! only differ in lifetimes, we handle the case of non-generic
+//! regions correctly.
+#![feature(type_alias_impl_trait)]
+
+type Opq<'a> = impl Sized;
+
+// Two defining uses: Opq<'{empty}> and Opq<'a>.
+// This used to ICE.
+// issue: #122782
+fn build<'a>() -> Opq<'a> {
+    let _: Opq<'_> = ();
+    //~^ ERROR expected generic lifetime parameter, found `'_`
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.stderr b/tests/ui/type-alias-impl-trait/param_mismatch4.stderr
new file mode 100644
index 00000000000..d3fdea25a3d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/param_mismatch4.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/param_mismatch4.rs:12:12
+   |
+LL | type Opq<'a> = impl Sized;
+   |          -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     let _: Opq<'_> = ();
+   |            ^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.