about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2022-06-22 07:03:59 +0900
committerGitHub <noreply@github.com>2022-06-22 07:03:59 +0900
commitfdeecb2314794934892dbb9334c3aad8bbbbfde2 (patch)
tree8f76857b1cfe84621c5e03e415443e566065607f /src
parentdc80ca78b6ec2b6bba02560470347433bcd0bb3c (diff)
parent0667b00acf939634ff1fd310ed5de2d49c65c6bb (diff)
downloadrust-fdeecb2314794934892dbb9334c3aad8bbbbfde2.tar.gz
rust-fdeecb2314794934892dbb9334c3aad8bbbbfde2.zip
Rollup merge of #97867 - lcnr:lub-binder, r=oli-obk
lub: don't bail out due to empty binders

allows for the following to compile. The equivalent code using `struct Wrapper<'upper>(fn(&'upper ());` already compiles on stable.
```rust
let _: fn(&'upper ()) = match v {
    true => lt_in_fn::<'a>(),
    false => lt_in_fn::<'b>(),
};
```
see https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7034a677190110941223cafac6632f70 for a complete example

r? ```@rust-lang/types```
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/lub-glb/empty-binder-future-compat.rs22
-rw-r--r--src/test/ui/lub-glb/empty-binders-err.rs55
-rw-r--r--src/test/ui/lub-glb/empty-binders-err.stderr59
-rw-r--r--src/test/ui/lub-glb/empty-binders.rs45
4 files changed, 181 insertions, 0 deletions
diff --git a/src/test/ui/lub-glb/empty-binder-future-compat.rs b/src/test/ui/lub-glb/empty-binder-future-compat.rs
new file mode 100644
index 00000000000..8700a88a36e
--- /dev/null
+++ b/src/test/ui/lub-glb/empty-binder-future-compat.rs
@@ -0,0 +1,22 @@
+// check-pass
+fn lt_in_fn_fn<'a: 'a>() -> fn(fn(&'a ())) {
+    |_| ()
+}
+
+
+fn foo<'a, 'b, 'lower>(v: bool)
+where
+    'a: 'lower,
+    'b: 'lower,
+{
+        // if we infer `x` to be higher ranked in the future,
+        // this would cause a type error.
+        let x = match v {
+            true => lt_in_fn_fn::<'a>(),
+            false => lt_in_fn_fn::<'b>(),
+        };
+
+        let _: fn(fn(&'lower())) = x;
+}
+
+fn main() {}
diff --git a/src/test/ui/lub-glb/empty-binders-err.rs b/src/test/ui/lub-glb/empty-binders-err.rs
new file mode 100644
index 00000000000..557480173ee
--- /dev/null
+++ b/src/test/ui/lub-glb/empty-binders-err.rs
@@ -0,0 +1,55 @@
+fn lt<'a: 'a>() -> &'a () {
+    &()
+}
+
+fn lt_in_fn<'a: 'a>() -> fn(&'a ()) {
+    |_| ()
+}
+
+struct Contra<'a>(fn(&'a ()));
+fn lt_in_contra<'a: 'a>() -> Contra<'a> {
+    Contra(|_| ())
+}
+
+fn covariance<'a, 'b, 'upper>(v: bool)
+where
+    'upper: 'a,
+    'upper: 'b,
+
+{
+    let _: &'upper () = match v {
+        //~^ ERROR lifetime may not live long enough
+        //~| ERROR lifetime may not live long enough
+        true => lt::<'a>(),
+        false => lt::<'b>(),
+    };
+}
+
+fn contra_fn<'a, 'b, 'lower>(v: bool)
+where
+    'a: 'lower,
+    'b: 'lower,
+
+{
+
+    let _: fn(&'lower ()) = match v {
+        //~^ ERROR lifetime may not live long enough
+        true => lt_in_fn::<'a>(),
+        false => lt_in_fn::<'b>(),
+    };
+}
+
+fn contra_struct<'a, 'b, 'lower>(v: bool)
+where
+    'a: 'lower,
+    'b: 'lower,
+
+{
+    let _: Contra<'lower> = match v {
+        //~^ ERROR lifetime may not live long enough
+        true => lt_in_contra::<'a>(),
+        false => lt_in_contra::<'b>(),
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/lub-glb/empty-binders-err.stderr b/src/test/ui/lub-glb/empty-binders-err.stderr
new file mode 100644
index 00000000000..f86f22d5e40
--- /dev/null
+++ b/src/test/ui/lub-glb/empty-binders-err.stderr
@@ -0,0 +1,59 @@
+error: lifetime may not live long enough
+  --> $DIR/empty-binders-err.rs:20:12
+   |
+LL | fn covariance<'a, 'b, 'upper>(v: bool)
+   |               --      ------ lifetime `'upper` defined here
+   |               |
+   |               lifetime `'a` defined here
+...
+LL |     let _: &'upper () = match v {
+   |            ^^^^^^^^^^ type annotation requires that `'a` must outlive `'upper`
+   |
+   = help: consider adding the following bound: `'a: 'upper`
+
+error: lifetime may not live long enough
+  --> $DIR/empty-binders-err.rs:20:12
+   |
+LL | fn covariance<'a, 'b, 'upper>(v: bool)
+   |                   --  ------ lifetime `'upper` defined here
+   |                   |
+   |                   lifetime `'b` defined here
+...
+LL |     let _: &'upper () = match v {
+   |            ^^^^^^^^^^ type annotation requires that `'b` must outlive `'upper`
+   |
+   = help: consider adding the following bound: `'b: 'upper`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: add bound `'a: 'upper`
+   = help: add bound `'b: 'upper`
+
+error: lifetime may not live long enough
+  --> $DIR/empty-binders-err.rs:35:12
+   |
+LL | fn contra_fn<'a, 'b, 'lower>(v: bool)
+   |              --      ------ lifetime `'lower` defined here
+   |              |
+   |              lifetime `'a` defined here
+...
+LL |     let _: fn(&'lower ()) = match v {
+   |            ^^^^^^^^^^^^^^ type annotation requires that `'lower` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'lower: 'a`
+
+error: lifetime may not live long enough
+  --> $DIR/empty-binders-err.rs:48:12
+   |
+LL | fn contra_struct<'a, 'b, 'lower>(v: bool)
+   |                  --      ------ lifetime `'lower` defined here
+   |                  |
+   |                  lifetime `'a` defined here
+...
+LL |     let _: Contra<'lower> = match v {
+   |            ^^^^^^^^^^^^^^ type annotation requires that `'lower` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'lower: 'a`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/lub-glb/empty-binders.rs b/src/test/ui/lub-glb/empty-binders.rs
new file mode 100644
index 00000000000..f9d07e79fda
--- /dev/null
+++ b/src/test/ui/lub-glb/empty-binders.rs
@@ -0,0 +1,45 @@
+// check-pass
+//
+// Check that computing the lub works even for empty binders.
+fn lt<'a: 'a>() -> &'a () {
+    &()
+}
+
+fn lt_in_fn<'a: 'a>() -> fn(&'a ()) {
+    |_| ()
+}
+
+struct Contra<'a>(fn(&'a ()));
+fn lt_in_contra<'a: 'a>() -> Contra<'a> {
+    Contra(|_| ())
+}
+
+fn ok<'a, 'b, 'upper, 'lower>(v: bool)
+where
+    'upper: 'a,
+    'upper: 'b,
+    'a: 'lower,
+    'b: 'lower,
+
+{
+    let _: &'lower () = match v {
+        true => lt::<'a>(),
+        false => lt::<'b>(),
+    };
+
+    // This errored in the past because LUB and GLB always
+    // bailed out when encountering binders, even if they were
+    // empty.
+    let _: fn(&'upper ()) = match v {
+        true => lt_in_fn::<'a>(),
+        false => lt_in_fn::<'b>(),
+    };
+
+    // This was already accepted, as relate didn't encounter any binders.
+    let _: Contra<'upper> = match v {
+        true => lt_in_contra::<'a>(),
+        false => lt_in_contra::<'b>(),
+    };
+}
+
+fn main() {}