diff options
Diffstat (limited to '')
-rw-r--r-- | src/test/ui/lub-glb/empty-binder-future-compat.rs | 22 | ||||
-rw-r--r-- | src/test/ui/lub-glb/empty-binders-err.rs | 55 | ||||
-rw-r--r-- | src/test/ui/lub-glb/empty-binders-err.stderr | 59 | ||||
-rw-r--r-- | src/test/ui/lub-glb/empty-binders.rs | 45 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-eq.rs | 27 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr | 21 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr | 12 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr | 20 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr | 2 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr | 2 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr | 12 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs | 29 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr | 19 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs | 39 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-object.rs | 23 | ||||
-rw-r--r-- | src/test/ui/lub-glb/old-lub-glb-object.stderr | 21 |
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`. |