about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-14 13:36:13 +0000
committerbors <bors@rust-lang.org>2023-08-14 13:36:13 +0000
commite8459109bbb440764c1c877032189a27b9e76c4e (patch)
tree1dbb9103019ea28fe677e1396bf4290c24b575b3 /tests
parent3071e0aef6dfd0a150c3fb1da0abad4ec86ca0aa (diff)
parente04f582e567e1519a2c6909453b33ebc1497750a (diff)
downloadrust-e8459109bbb440764c1c877032189a27b9e76c4e.tar.gz
rust-e8459109bbb440764c1c877032189a27b9e76c4e.zip
Auto merge of #112842 - lcnr:non-defining-use, r=oli-obk
check for non-defining uses of RPIT

This PR requires defining uses of RPIT and the async functions return type to use unique generic parameters as type and const arguments, (mostly) fixing #111935. This changes the following snippet to an error (it compiled since 1.62):
```rust
fn foo<T>() -> impl Sized {
    let _: () = foo::<u8>(); //~ ERROR non-defining use of `impl Sized`
}
```
Since 1.62 we only checked that the generic arguments of opaque types are unique parameters for TAIT and ignored RPITs, so this PR changes the behavior here to be consistent.

For defining uses which do not have unique params as arguments it is unclear how the hidden type should map to the generic params of the opaque. In the following snippet, should the hidden type of `foo<T>::opaque` be `T` or `u32`.
```rust
fn foo<T>() -> impl Sized {
    let _: u32 = foo::<u32>();
    foo::<T>()
}
```
There are no crater regressions caused by this change.

---

The same issue exists for lifetime arguments which is not fixed by this PR, currently resulting in an ICE in mir borrowck (I wasn't able to get an example which didn't ICE, it might be possible):
```rust
fn foo<'a: 'a>() -> impl Sized {
    let _: &'static () = foo::<'static>();
    //~^ ICE opaque type with non-universal region substs
    foo::<'a>()
}
```
Fixing this for lifetimes as well is blocked on https://github.com/rust-lang/rust/issues/113916. Due to this issue, functions returning an RPIT with lifetime parameters equal in the region constraint graph would always result in an error, resulting in breakage found via crater: https://github.com/rust-lang/rust/pull/112842#issuecomment-1610057887
```rust
trait Trait<'a, 'b> {}
impl Trait<'_, '_> for () {}

struct Type<'a>(&'a ());
impl<'a> Type<'a> {
    // `'b == 'a`
    fn do_stuff<'b: 'a>(&'b self) -> impl Trait<'a, 'b> {
        // This fails as long there is something in the body
        // which adds the outlives constraints to the constraint graph.
        //
        // This is the case for nested closures.
        (|| ())()

    }
}
```
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/impl-trait/issue-99073-2.rs1
-rw-r--r--tests/ui/impl-trait/issue-99073-2.stderr18
-rw-r--r--tests/ui/impl-trait/issue-99073.rs1
-rw-r--r--tests/ui/impl-trait/issue-99073.stderr21
-rw-r--r--tests/ui/impl-trait/rpit/equal-lifetime-params-ok.rs19
-rw-r--r--tests/ui/impl-trait/rpit/non-defining-use.rs14
-rw-r--r--tests/ui/impl-trait/rpit/non-defining-use.stderr31
7 files changed, 95 insertions, 10 deletions
diff --git a/tests/ui/impl-trait/issue-99073-2.rs b/tests/ui/impl-trait/issue-99073-2.rs
index 14ac688806b..37ea211bec3 100644
--- a/tests/ui/impl-trait/issue-99073-2.rs
+++ b/tests/ui/impl-trait/issue-99073-2.rs
@@ -8,6 +8,7 @@ fn test<T: Display>(t: T, recurse: bool) -> impl Display {
     let f = || {
         let i: u32 = test::<i32>(-1, false);
         //~^ ERROR concrete type differs from previous defining opaque type use
+        //~| ERROR expected generic type parameter, found `i32`
         println!("{i}");
     };
     if recurse {
diff --git a/tests/ui/impl-trait/issue-99073-2.stderr b/tests/ui/impl-trait/issue-99073-2.stderr
index 913bc8f5674..06b2b84569f 100644
--- a/tests/ui/impl-trait/issue-99073-2.stderr
+++ b/tests/ui/impl-trait/issue-99073-2.stderr
@@ -1,3 +1,12 @@
+error[E0792]: expected generic type parameter, found `i32`
+  --> $DIR/issue-99073-2.rs:9:22
+   |
+LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
+   |         - this generic parameter must be used with a generic type parameter
+LL |     let f = || {
+LL |         let i: u32 = test::<i32>(-1, false);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^
+
 error: concrete type differs from previous defining opaque type use
   --> $DIR/issue-99073-2.rs:9:22
    |
@@ -5,10 +14,11 @@ LL |         let i: u32 = test::<i32>(-1, false);
    |                      ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32`
    |
 note: previous use here
-  --> $DIR/issue-99073-2.rs:16:5
+  --> $DIR/issue-99073-2.rs:7:45
    |
-LL |     t
-   |     ^
+LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
+   |                                             ^^^^^^^^^^^^
 
-error: aborting due to 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/issue-99073.rs b/tests/ui/impl-trait/issue-99073.rs
index 7798e247df0..b4ef3e66f96 100644
--- a/tests/ui/impl-trait/issue-99073.rs
+++ b/tests/ui/impl-trait/issue-99073.rs
@@ -5,4 +5,5 @@ fn main() {
 fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
   move || f(fix(&f))
   //~^ ERROR concrete type differs from previous defining opaque type use
+  //~| ERROR expected generic type parameter, found `&F`
 }
diff --git a/tests/ui/impl-trait/issue-99073.stderr b/tests/ui/impl-trait/issue-99073.stderr
index 54636795349..a8400080e5a 100644
--- a/tests/ui/impl-trait/issue-99073.stderr
+++ b/tests/ui/impl-trait/issue-99073.stderr
@@ -1,14 +1,23 @@
-error: concrete type differs from previous defining opaque type use
+error[E0792]: expected generic type parameter, found `&F`
   --> $DIR/issue-99073.rs:6:11
    |
+LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
+   |        - this generic parameter must be used with a generic type parameter
+LL |   move || f(fix(&f))
+   |           ^^^^^^^^^^
+
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/issue-99073.rs:6:13
+   |
 LL |   move || f(fix(&f))
-   |           ^^^^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G`
+   |             ^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G`
    |
 note: previous use here
-  --> $DIR/issue-99073.rs:6:3
+  --> $DIR/issue-99073.rs:5:36
    |
-LL |   move || f(fix(&f))
-   |   ^^^^^^^^^^^^^^^^^^
+LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
+   |                                    ^^^^^^^^^
 
-error: aborting due to 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/equal-lifetime-params-ok.rs b/tests/ui/impl-trait/rpit/equal-lifetime-params-ok.rs
new file mode 100644
index 00000000000..6207381c745
--- /dev/null
+++ b/tests/ui/impl-trait/rpit/equal-lifetime-params-ok.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+// related to #113916, check that using RPITs in functions with lifetime params
+// which are constrained to be equal compiles.
+
+trait Trait<'a, 'b> {}
+impl Trait<'_, '_> for () {}
+fn pass<'a: 'b, 'b: 'a>() -> impl Trait<'a, 'b> {
+    (|| {})()
+}
+
+struct Foo<'a>(&'a ());
+impl<'a> Foo<'a> {
+    fn bar<'b: 'a>(&'b self) -> impl Trait<'a, 'b> {
+        let _: &'a &'b &'a ();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/rpit/non-defining-use.rs b/tests/ui/impl-trait/rpit/non-defining-use.rs
new file mode 100644
index 00000000000..255a8929a87
--- /dev/null
+++ b/tests/ui/impl-trait/rpit/non-defining-use.rs
@@ -0,0 +1,14 @@
+// Regression test for #111935 that non-defining uses of RPIT result in errors
+#![allow(unconditional_recursion)]
+fn foo<T>() -> impl Sized {
+    let _: () = foo::<u8>(); //~ ERROR expected generic type parameter, found `u8`
+}
+
+fn bar<T>(val: T) -> impl Sized {
+    let _: u8 = bar(0u8);
+    //~^ ERROR concrete type differs from previous defining opaque type use
+    //~| ERROR expected generic type parameter, found `u8`
+    val
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/rpit/non-defining-use.stderr b/tests/ui/impl-trait/rpit/non-defining-use.stderr
new file mode 100644
index 00000000000..19987d47672
--- /dev/null
+++ b/tests/ui/impl-trait/rpit/non-defining-use.stderr
@@ -0,0 +1,31 @@
+error[E0792]: expected generic type parameter, found `u8`
+  --> $DIR/non-defining-use.rs:4:12
+   |
+LL | fn foo<T>() -> impl Sized {
+   |        - this generic parameter must be used with a generic type parameter
+LL |     let _: () = foo::<u8>();
+   |            ^^
+
+error[E0792]: expected generic type parameter, found `u8`
+  --> $DIR/non-defining-use.rs:8:12
+   |
+LL | fn bar<T>(val: T) -> impl Sized {
+   |        - this generic parameter must be used with a generic type parameter
+LL |     let _: u8 = bar(0u8);
+   |            ^^
+
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/non-defining-use.rs:8:17
+   |
+LL |     let _: u8 = bar(0u8);
+   |                 ^^^^^^^^ expected `T`, got `u8`
+   |
+note: previous use here
+  --> $DIR/non-defining-use.rs:7:22
+   |
+LL | fn bar<T>(val: T) -> impl Sized {
+   |                      ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0792`.