rewrite leak check to be based on universes

In the new leak check, instead of getting a list of placeholders to
track, we look for any placeholder that is part of a universe which
was created during the snapshot.

We are looking for the following error patterns:

* P1: P2, where P1 != P2
* P1: R, where R is in some universe that cannot name P1

This new leak check is more precise than before, in that it accepts
this patterns:

* R: P1, even if R cannot name P1, because R = 'static is a valid
sol'n
* R: P1, R: P2, as above

Note that this leak check, when running during subtyping, is less
efficient than before in some sense because it is going to check and
re-check all the universes created since the snapshot. We're going to
move when the leak check runs to try and correct that.
This commit is contained in:
Niko Matsakis 2020-05-19 01:09:40 +00:00
parent 4199b3ae26
commit f2cf994483
29 changed files with 572 additions and 320 deletions

View file

@ -49,7 +49,7 @@ LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
| ------------- required by this bound in `tuple_one`
...
LL | tuple_one::<Tuple>();
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime
error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
--> $DIR/associated-types-eq-hr.rs:97:17
@ -74,7 +74,7 @@ LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
| ------------- required by this bound in `tuple_two`
...
LL | tuple_two::<Tuple>();
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime
error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
--> $DIR/associated-types-eq-hr.rs:107:18

View file

@ -1,12 +1,12 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
--> $DIR/hr-subtype.rs:45:26
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
| |_________________________________________________________________________________________- in this macro invocation
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
| |_____________________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>`
found enum `std::option::Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>`

View file

@ -1,12 +1,12 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
--> $DIR/hr-subtype.rs:45:26
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
LL | | for<'a> fn(&'a u32, &'a u32)) }
| |__________________________________________________________________- in this macro invocation
LL | | for<'a> fn(&'a u32, &'a u32)) }
| |__________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32)>`
found enum `std::option::Option<for<'a> fn(&'a u32, &'a u32)>`

View file

@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:104:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

View file

@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:104:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

View file

@ -1,12 +1,12 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
--> $DIR/hr-subtype.rs:45:26
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
LL | | fn(&'x u32)) }
| |___________________________________________- in this macro invocation
LL | | fn(&'x u32)) }
| |______________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a> fn(&'a u32)>`
found enum `std::option::Option<fn(&'x u32)>`

View file

@ -1,17 +1,14 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:104:1
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
LL | | for<'a> fn(Co<'a>, Co<'a>)) }
| |______________________________________________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>)>`
found enum `std::option::Option<for<'a> fn(Co<'a>, Co<'a>)>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
LL | / fn main() {
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,17 +1,14 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:104:1
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) }
| |______________________________________________________________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>) -> Contra<'a>>`
found enum `std::option::Option<for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
LL | / fn main() {
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:104:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

View file

@ -1,12 +1,12 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
--> $DIR/hr-subtype.rs:45:26
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
| |______________________________________________________________________________________________- in this macro invocation
LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
| |__________________________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>>`
found enum `std::option::Option<for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>>`

View file

@ -1,12 +1,12 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
--> $DIR/hr-subtype.rs:45:26
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
| |__________________________________________________________________________- in this macro invocation
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
| |__________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>`
found enum `std::option::Option<for<'a> fn(Inv<'a>, Inv<'a>)>`

View file

@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:104:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

View file

@ -1,65 +1,65 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:33:26
--> $DIR/hr-subtype.rs:39:26
|
LL | gimme::<$t2>(None::<$t1>);
| ^^^^^^^^^^^ lifetime mismatch
...
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
LL | | fn(Inv<'y>)) }
| |__________________________________________________- in this macro invocation
LL | | fn(Inv<'y>)) }
| |______________- in this macro invocation
|
= note: expected enum `std::option::Option<fn(Inv<'y>)>`
found enum `std::option::Option<fn(Inv<'x>)>`
note: the lifetime `'x` as defined on the function body at 32:20...
--> $DIR/hr-subtype.rs:32:20
note: the lifetime `'x` as defined on the function body at 38:20...
--> $DIR/hr-subtype.rs:38:20
|
LL | fn subtype<'x,'y:'x,'z:'y>() {
LL | fn subtype<'x, 'y: 'x, 'z: 'y>() {
| ^^
...
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
LL | | fn(Inv<'y>)) }
| |__________________________________________________- in this macro invocation
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 32:23
--> $DIR/hr-subtype.rs:32:23
LL | | fn(Inv<'y>)) }
| |______________- in this macro invocation
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:24
--> $DIR/hr-subtype.rs:38:24
|
LL | fn subtype<'x,'y:'x,'z:'y>() {
| ^^
LL | fn subtype<'x, 'y: 'x, 'z: 'y>() {
| ^^
...
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
LL | | fn(Inv<'y>)) }
| |__________________________________________________- in this macro invocation
LL | | fn(Inv<'y>)) }
| |______________- in this macro invocation
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
--> $DIR/hr-subtype.rs:45:26
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ lifetime mismatch
...
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
LL | | fn(Inv<'y>)) }
| |__________________________________________________- in this macro invocation
LL | | fn(Inv<'y>)) }
| |______________- in this macro invocation
|
= note: expected enum `std::option::Option<fn(Inv<'x>)>`
found enum `std::option::Option<fn(Inv<'y>)>`
note: the lifetime `'x` as defined on the function body at 38:22...
--> $DIR/hr-subtype.rs:38:22
note: the lifetime `'x` as defined on the function body at 44:22...
--> $DIR/hr-subtype.rs:44:22
|
LL | fn supertype<'x,'y:'x,'z:'y>() {
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
| ^^
...
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
LL | | fn(Inv<'y>)) }
| |__________________________________________________- in this macro invocation
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25
--> $DIR/hr-subtype.rs:38:25
LL | | fn(Inv<'y>)) }
| |______________- in this macro invocation
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26
--> $DIR/hr-subtype.rs:44:26
|
LL | fn supertype<'x,'y:'x,'z:'y>() {
| ^^
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
| ^^
...
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
LL | | fn(Inv<'y>)) }
| |__________________________________________________- in this macro invocation
LL | | fn(Inv<'y>)) }
| |______________- in this macro invocation
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View file

@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:104:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

View file

@ -1,33 +1,33 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
--> $DIR/hr-subtype.rs:45:26
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ lifetime mismatch
...
LL | / check! { free_x_vs_free_y: (fn(&'x u32),
LL | | fn(&'y u32)) }
| |__________________________________________- in this macro invocation
LL | | fn(&'y u32)) }
| |______________- in this macro invocation
|
= note: expected enum `std::option::Option<fn(&'x u32)>`
found enum `std::option::Option<fn(&'y u32)>`
note: the lifetime `'x` as defined on the function body at 38:22...
--> $DIR/hr-subtype.rs:38:22
note: the lifetime `'x` as defined on the function body at 44:22...
--> $DIR/hr-subtype.rs:44:22
|
LL | fn supertype<'x,'y:'x,'z:'y>() {
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
| ^^
...
LL | / check! { free_x_vs_free_y: (fn(&'x u32),
LL | | fn(&'y u32)) }
| |__________________________________________- in this macro invocation
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25
--> $DIR/hr-subtype.rs:38:25
LL | | fn(&'y u32)) }
| |______________- in this macro invocation
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26
--> $DIR/hr-subtype.rs:44:26
|
LL | fn supertype<'x,'y:'x,'z:'y>() {
| ^^
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
| ^^
...
LL | / check! { free_x_vs_free_y: (fn(&'x u32),
LL | | fn(&'y u32)) }
| |__________________________________________- in this macro invocation
LL | | fn(&'y u32)) }
| |______________- in this macro invocation
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View file

@ -18,24 +18,30 @@
// revisions: bound_inv_a_b_vs_bound_inv_a
// revisions: bound_a_b_ret_a_vs_bound_a_ret_a
fn gimme<T>(_: Option<T>) { }
fn gimme<T>(_: Option<T>) {}
struct Inv<'a> { x: *mut &'a u32 }
struct Inv<'a> {
x: *mut &'a u32,
}
struct Co<'a> { x: fn(&'a u32) }
struct Co<'a> {
x: fn(&'a u32),
}
struct Contra<'a> { x: &'a u32 }
struct Contra<'a> {
x: &'a u32,
}
macro_rules! check {
($rev:ident: ($t1:ty, $t2:ty)) => {
#[cfg($rev)]
fn subtype<'x,'y:'x,'z:'y>() {
fn subtype<'x, 'y: 'x, 'z: 'y>() {
gimme::<$t2>(None::<$t1>);
//[free_inv_x_vs_free_inv_y]~^ ERROR
}
#[cfg($rev)]
fn supertype<'x,'y:'x,'z:'y>() {
fn supertype<'x, 'y: 'x, 'z: 'y>() {
gimme::<$t1>(None::<$t2>);
//[bound_a_vs_free_x]~^ ERROR
//[free_x_vs_free_y]~^^ ERROR
@ -43,35 +49,33 @@ macro_rules! check {
//[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR
//[free_inv_x_vs_free_inv_y]~^^^^^ ERROR
//[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types
//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR
//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR
//[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR
//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^ ERROR
}
}
};
}
// If both have bound regions, they are equivalent, regardless of
// variant.
check! { bound_a_vs_bound_a: (for<'a> fn(&'a u32),
for<'a> fn(&'a u32)) }
for<'a> fn(&'a u32)) }
check! { bound_a_vs_bound_b: (for<'a> fn(&'a u32),
for<'b> fn(&'b u32)) }
for<'b> fn(&'b u32)) }
check! { bound_inv_a_vs_bound_inv_b: (for<'a> fn(Inv<'a>),
for<'b> fn(Inv<'b>)) }
for<'b> fn(Inv<'b>)) }
check! { bound_co_a_vs_bound_co_b: (for<'a> fn(Co<'a>),
for<'b> fn(Co<'b>)) }
for<'b> fn(Co<'b>)) }
// Bound is a subtype of free.
check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
fn(&'x u32)) }
fn(&'x u32)) }
// Two free regions are relatable if subtyping holds.
check! { free_x_vs_free_x: (fn(&'x u32),
fn(&'x u32)) }
fn(&'x u32)) }
check! { free_x_vs_free_y: (fn(&'x u32),
fn(&'y u32)) }
fn(&'y u32)) }
check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
fn(Inv<'y>)) }
fn(Inv<'y>)) }
// Somewhat surprisingly, a fn taking two distinct bound lifetimes and
// a fn taking one bound lifetime can be interchangeable, but only if
@ -82,25 +86,27 @@ check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
// intersection;
// - if we are contravariant, then 'a can be inferred to 'static.
check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
for<'a> fn(&'a u32, &'a u32)) }
for<'a> fn(&'a u32, &'a u32)) }
check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
for<'a> fn(Co<'a>, Co<'a>)) }
for<'a> fn(Co<'a>, Co<'a>)) }
check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) }
for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) }
// If we make those lifetimes invariant, then the two types are not interchangeable.
check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
for<'a> fn(Inv<'a>, Inv<'a>)) }
for<'a> fn(Inv<'a>, Inv<'a>)) }
check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
#[rustc_error]
fn main() {
//[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error]
//[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error]
//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error]
//[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error]
//[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error]
//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error]
//[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_co_a_b_vs_bound_co_a]~^^^^^^ ERROR
//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR
}

View file

@ -2,6 +2,8 @@
//
// In particular, we test this pattern in trait solving, where it is not connected
// to any part of the source code.
//
// check-pass
trait Trait<T> {}
@ -30,9 +32,6 @@ fn main() {
// - `?b: ?a` -- solveable if `?b` is inferred to `'static`
// - So the subtyping check succeeds, somewhat surprisingly.
// This is because we can use `'static`.
//
// NB. *However*, the reinstated leak-check gives an error here.
foo::<()>();
//~^ ERROR not satisfied
}

View file

@ -1,18 +0,0 @@
error[E0277]: the trait bound `(): Trait<for<'b> fn(fn(&'b u32))>` is not satisfied
--> $DIR/hrtb-exists-forall-trait-covariant.rs:36:11
|
LL | fn foo<T>()
| --- required by a bound in this
LL | where
LL | T: Trait<for<'b> fn(fn(&'b u32))>,
| ------------------------------ required by this bound in `foo`
...
LL | foo::<()>();
| ^^ the trait `Trait<for<'b> fn(fn(&'b u32))>` is not implemented for `()`
|
= help: the following implementations were found:
<() as Trait<fn(fn(&'a u32))>>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -13,11 +13,11 @@ struct S;
// Given 'cx, return 'cx
type F = for<'cx> fn(&'cx S) -> &'cx S;
fn want_F(f: F) { }
fn want_F(f: F) {}
// Given anything, return 'static
type G = for<'cx> fn(&'cx S) -> &'static S;
fn want_G(f: G) { }
fn want_G(f: G) {}
// Should meet both.
fn foo(x: &S) -> &'static S {
@ -25,7 +25,7 @@ fn foo(x: &S) -> &'static S {
}
// Should meet both.
fn bar<'a,'b>(x: &'a S) -> &'b S {
fn bar<'a, 'b>(x: &'a S) -> &'b S {
panic!()
}
@ -37,7 +37,7 @@ fn baz(x: &S) -> &S {
fn supply_F() {
want_F(foo);
want_F(bar); //~ ERROR mismatched types
want_F(bar);
want_F(baz);
}
@ -48,5 +48,4 @@ fn supply_G() {
want_G(baz); //~ ERROR mismatched types
}
pub fn main() {
}
pub fn main() {}

View file

@ -1,12 +1,3 @@
error[E0308]: mismatched types
--> $DIR/regions-fn-subtyping-return-static-fail.rs:40:12
|
LL | want_F(bar);
| ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
|
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S`
found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}`
error[E0308]: mismatched types
--> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12
|
@ -16,6 +7,6 @@ LL | want_G(baz);
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
found fn item `for<'r> fn(&'r S) -> &'r S {baz}`
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -5,6 +5,8 @@
// *ANY* lifetime and returns a reference with the 'static lifetime.
// This can safely be considered to be an instance of `F` because all
// lifetimes are sublifetimes of 'static.
//
// check-pass
#![allow(dead_code)]
#![allow(unused_variables)]
@ -14,11 +16,11 @@ struct S;
// Given 'cx, return 'cx
type F = for<'cx> fn(&'cx S) -> &'cx S;
fn want_F(f: F) { }
fn want_F(f: F) {}
// Given anything, return 'static
type G = for<'cx> fn(&'cx S) -> &'static S;
fn want_G(f: G) { }
fn want_G(f: G) {}
// Should meet both.
fn foo(x: &S) -> &'static S {
@ -26,7 +28,7 @@ fn foo(x: &S) -> &'static S {
}
// Should meet both.
fn bar<'a,'b>(x: &'a S) -> &'b S {
fn bar<'a, 'b>(x: &'a S) -> &'b S {
panic!()
}
@ -38,10 +40,9 @@ fn baz(x: &S) -> &S {
fn supply_F() {
want_F(foo);
want_F(bar); //~ ERROR mismatched types
want_F(bar);
want_F(baz);
}
pub fn main() {
}
pub fn main() {}

View file

@ -1,12 +0,0 @@
error[E0308]: mismatched types
--> $DIR/regions-fn-subtyping-return-static.rs:41:12
|
LL | want_F(bar);
| ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
|
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S`
found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -36,7 +36,7 @@ error[E0271]: type mismatch resolving `for<'a, 'b> <fn(_) -> _ {id::<_>} as std:
--> $DIR/rfc1623.rs:25:8
|
LL | f: &id,
| ^^^ expected bound lifetime parameter 'a, found concrete lifetime
| ^^^ expected bound lifetime parameter 'b, found concrete lifetime
|
= note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>`