summaryrefslogtreecommitdiffstats
path: root/src/test/ui/lub-glb
diff options
context:
space:
mode:
Diffstat (limited to '')
-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
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-eq.rs27
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr21
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr12
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr20
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr2
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr2
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr12
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs29
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr19
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs39
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-object.rs23
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-object.stderr21
16 files changed, 408 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 000000000..8700a88a3
--- /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 000000000..557480173
--- /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 000000000..f86f22d5e
--- /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 000000000..f9d07e79f
--- /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() {}
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs
new file mode 100644
index 000000000..fbf4aee02
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs
@@ -0,0 +1,27 @@
+// Test that we give a note when the old LUB/GLB algorithm would have
+// succeeded but the new code (which requires equality) gives an
+// error. However, now that we handle subtyping correctly, we no
+// longer get an error, because we recognize these two types as
+// equivalent!
+//
+// check-pass
+
+fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
+ // The two types above are actually equivalent. With the older
+ // leak check, though, we didn't consider them as equivalent, and
+ // hence we gave errors. But now we've fixed that.
+ let z = match 22 {
+ 0 => x,
+ _ => y,
+ };
+}
+
+fn foo_cast(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
+ let z = match 22 {
+ // No error with an explicit cast:
+ 0 => x as for<'a> fn(&'a u8, &'a u8),
+ _ => y,
+ };
+}
+
+fn main() {}
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr
new file mode 100644
index 000000000..4448f9326
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr
@@ -0,0 +1,21 @@
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/old-lub-glb-hr-noteq1.rs:17:14
+ |
+LL | let z = match 22 {
+ | _____________-
+LL | | 0 => x,
+ | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+LL | | _ => y,
+ | | ^ one type is more general than the other
+LL | |
+... |
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+ = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+ found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr
new file mode 100644
index 000000000..0d6131135
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/old-lub-glb-hr-noteq1.rs:17:14
+ |
+LL | _ => y,
+ | ^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+ found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr
new file mode 100644
index 000000000..dd0fdf3a1
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr
@@ -0,0 +1,20 @@
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/old-lub-glb-hr-noteq1.rs:14:14
+ |
+LL | let z = match 22 {
+ | _____________-
+LL | | 0 => x,
+ | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+LL | | _ => y,
+ | | ^ one type is more general than the other
+LL | |
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+ = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+ found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr
new file mode 100644
index 000000000..217392aa3
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr
@@ -0,0 +1,2 @@
+error: unknown debugging option: `borrowck`
+
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr
new file mode 100644
index 000000000..217392aa3
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr
@@ -0,0 +1,2 @@
+error: unknown debugging option: `borrowck`
+
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr
new file mode 100644
index 000000000..cb046d0b0
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/old-lub-glb-hr-noteq1.rs:14:14
+ |
+LL | _ => y,
+ | ^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+ found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs
new file mode 100644
index 000000000..589119abb
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs
@@ -0,0 +1,29 @@
+// Test taking the LUB of two function types that are not equatable but where one is more
+// general than the other. Test the case where the more general type (`x`) is the first
+// match arm specifically.
+
+// revisions: leak noleak
+//[noleak] compile-flags:-Zno-leak-check
+
+fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
+ // The two types above are not equivalent. With the older LUB/GLB
+ // algorithm, this may have worked (I don't remember), but now it
+ // doesn't because we require equality.
+ let z = match 22 {
+ 0 => x,
+ _ => y,
+ //[leak]~^ ERROR `match` arms have incompatible types
+ //[noleak]~^^ ERROR mismatched types
+ };
+}
+
+fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
+ // But we can *upcast* explicitly the type of `x` and figure
+ // things out:
+ let z = match 22 {
+ 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8,
+ _ => y,
+ };
+}
+
+fn main() {}
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr
new file mode 100644
index 000000000..e54fcf068
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr
@@ -0,0 +1,19 @@
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/old-lub-glb-hr-noteq2.rs:25:14
+ |
+LL | let z = match 22 {
+ | _____________-
+LL | | 0 => y,
+ | | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
+LL | | _ => x,
+ | | ^ one type is more general than the other
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+ = note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
+ found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs
new file mode 100644
index 000000000..9940c40da
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs
@@ -0,0 +1,39 @@
+// Test taking the LUB of two function types that are not equatable but where
+// one is more general than the other. Test the case where the more general type
+// (`x`) is the second match arm specifically.
+//
+// FIXME(#73154) Pure NLL checker without leak check accepts this test.
+// (Note that it still errors in old-lub-glb-hr-noteq1.rs). What happens
+// is that, due to the ordering of the match arms, we pick the correct "more
+// general" fn type, and we ignore the errors from the non-NLL type checker that
+// requires equality. The NLL type checker only requires a subtyping
+// relationship, and that holds. To unblock landing NLL - and ensure that we can
+// choose to make this always in error in the future - we perform the leak check
+// after coercing a function pointer.
+
+// revisions: leak noleak
+//[noleak] compile-flags: -Zno-leak-check
+
+//[noleak] check-pass
+
+fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
+ // The two types above are not equivalent. With the older LUB/GLB
+ // algorithm, this may have worked (I don't remember), but now it
+ // doesn't because we require equality.
+ let z = match 22 {
+ 0 => y,
+ _ => x,
+ //[leak]~^ ERROR `match` arms have incompatible types
+ };
+}
+
+fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
+ // But we can *upcast* explicitly the type of `x` and figure
+ // things out:
+ let z = match 22 {
+ 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8,
+ _ => y,
+ };
+}
+
+fn main() {}
diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs
new file mode 100644
index 000000000..b6ead9c68
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-object.rs
@@ -0,0 +1,23 @@
+// Test that we give a note when the old LUB/GLB algorithm would have
+// succeeded but the new code (which is stricter) gives an error.
+
+trait Foo<T, U> {}
+
+fn foo(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) {
+ let z = match 22 {
+ 0 => x,
+ _ => y,
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ };
+}
+
+fn bar(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) {
+ // Accepted with explicit case:
+ let z = match 22 {
+ 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>,
+ _ => y,
+ };
+}
+
+fn main() {}
diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr
new file mode 100644
index 000000000..3d0c171e0
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+ --> $DIR/old-lub-glb-object.rs:9:14
+ |
+LL | _ => y,
+ | ^ one type is more general than the other
+ |
+ = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
+ found trait object `dyn for<'a> Foo<&'a u8, &'a u8>`
+
+error[E0308]: mismatched types
+ --> $DIR/old-lub-glb-object.rs:9:14
+ |
+LL | _ => y,
+ | ^ one type is more general than the other
+ |
+ = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
+ found trait object `dyn for<'a> Foo<&'a u8, &'a u8>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.