Skip to content

Commit ca4a18f

Browse files
committed
Add some FnDef LUB coercion tests
1 parent 6c6b302 commit ca4a18f

File tree

4 files changed

+321
-0
lines changed

4 files changed

+321
-0
lines changed

tests/ui/fn/fn_def_coercion.rs

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//! Test that coercing between function items of the same function,
2+
//! but with different generic args succeeds in typeck, but then fails
3+
//! in borrowck when the lifetimes can't actually be merged.
4+
5+
fn foo<T>(t: T) -> T {
6+
t
7+
}
8+
9+
fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
10+
let mut x = foo::<&'a ()>; //~ ERROR: lifetime may not live long enough
11+
x = foo::<&'b ()>; //~ ERROR: lifetime may not live long enough
12+
x = foo::<&'c ()>;
13+
x(a);
14+
x(b);
15+
x(c);
16+
}
17+
18+
fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
19+
let x = foo::<&'c ()>;
20+
let _: &'c () = x(a); //~ ERROR lifetime may not live long enough
21+
}
22+
23+
fn h<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
24+
let x = foo::<&'a ()>;
25+
let _: &'a () = x(c);
26+
}
27+
28+
fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
29+
let mut x = foo::<&'c ()>;
30+
x = foo::<&'b ()>; //~ ERROR lifetime may not live long enough
31+
x = foo::<&'a ()>; //~ ERROR lifetime may not live long enough
32+
x(a);
33+
x(b);
34+
x(c);
35+
}
36+
37+
fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
38+
let x = match true {
39+
true => foo::<&'b ()>, //~ ERROR lifetime may not live long enough
40+
false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
41+
};
42+
x(a);
43+
x(b);
44+
x(c);
45+
}
46+
47+
fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
48+
let x = match true {
49+
true => foo::<&'c ()>,
50+
false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
51+
};
52+
53+
x(a);
54+
x(b); //~ ERROR lifetime may not live long enough
55+
x(c);
56+
}
57+
58+
fn main() {}

tests/ui/fn/fn_def_coercion.stderr

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/fn_def_coercion.rs:10:17
3+
|
4+
LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | let mut x = foo::<&'a ()>;
9+
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
10+
|
11+
= help: consider adding the following bound: `'a: 'b`
12+
= note: requirement occurs because of a function pointer to `foo`
13+
= note: the function `foo` is invariant over the parameter `T`
14+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
15+
16+
error: lifetime may not live long enough
17+
--> $DIR/fn_def_coercion.rs:11:5
18+
|
19+
LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
20+
| -- -- lifetime `'b` defined here
21+
| |
22+
| lifetime `'a` defined here
23+
LL | let mut x = foo::<&'a ()>;
24+
LL | x = foo::<&'b ()>;
25+
| ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
26+
|
27+
= help: consider adding the following bound: `'b: 'a`
28+
= note: requirement occurs because of a function pointer to `foo`
29+
= note: the function `foo` is invariant over the parameter `T`
30+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
31+
32+
help: `'a` and `'b` must be the same: replace one with the other
33+
34+
error: lifetime may not live long enough
35+
--> $DIR/fn_def_coercion.rs:20:12
36+
|
37+
LL | fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
38+
| -- -- lifetime `'c` defined here
39+
| |
40+
| lifetime `'a` defined here
41+
LL | let x = foo::<&'c ()>;
42+
LL | let _: &'c () = x(a);
43+
| ^^^^^^ type annotation requires that `'a` must outlive `'c`
44+
|
45+
= help: consider adding the following bound: `'a: 'c`
46+
47+
error: lifetime may not live long enough
48+
--> $DIR/fn_def_coercion.rs:30:5
49+
|
50+
LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
51+
| -- -- lifetime `'b` defined here
52+
| |
53+
| lifetime `'a` defined here
54+
LL | let mut x = foo::<&'c ()>;
55+
LL | x = foo::<&'b ()>;
56+
| ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
57+
|
58+
= help: consider adding the following bound: `'b: 'a`
59+
= note: requirement occurs because of a function pointer to `foo`
60+
= note: the function `foo` is invariant over the parameter `T`
61+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
62+
63+
error: lifetime may not live long enough
64+
--> $DIR/fn_def_coercion.rs:31:5
65+
|
66+
LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
67+
| -- -- lifetime `'b` defined here
68+
| |
69+
| lifetime `'a` defined here
70+
...
71+
LL | x = foo::<&'a ()>;
72+
| ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
73+
|
74+
= help: consider adding the following bound: `'a: 'b`
75+
= note: requirement occurs because of a function pointer to `foo`
76+
= note: the function `foo` is invariant over the parameter `T`
77+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
78+
79+
help: `'a` and `'b` must be the same: replace one with the other
80+
|
81+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
82+
83+
error: lifetime may not live long enough
84+
--> $DIR/fn_def_coercion.rs:39:17
85+
|
86+
LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
87+
| -- -- lifetime `'b` defined here
88+
| |
89+
| lifetime `'a` defined here
90+
LL | let x = match true {
91+
LL | true => foo::<&'b ()>,
92+
| ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
93+
|
94+
= help: consider adding the following bound: `'b: 'a`
95+
= note: requirement occurs because of a function pointer to `foo`
96+
= note: the function `foo` is invariant over the parameter `T`
97+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
98+
99+
error: lifetime may not live long enough
100+
--> $DIR/fn_def_coercion.rs:40:18
101+
|
102+
LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
103+
| -- -- lifetime `'b` defined here
104+
| |
105+
| lifetime `'a` defined here
106+
...
107+
LL | false => foo::<&'a ()>,
108+
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
109+
|
110+
= help: consider adding the following bound: `'a: 'b`
111+
= note: requirement occurs because of a function pointer to `foo`
112+
= note: the function `foo` is invariant over the parameter `T`
113+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
114+
115+
help: `'a` and `'b` must be the same: replace one with the other
116+
|
117+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
118+
119+
error: lifetime may not live long enough
120+
--> $DIR/fn_def_coercion.rs:50:18
121+
|
122+
LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
123+
| -- -- lifetime `'c` defined here
124+
| |
125+
| lifetime `'a` defined here
126+
...
127+
LL | false => foo::<&'a ()>,
128+
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c`
129+
|
130+
= help: consider adding the following bound: `'a: 'c`
131+
= note: requirement occurs because of a function pointer to `foo`
132+
= note: the function `foo` is invariant over the parameter `T`
133+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
134+
135+
error: lifetime may not live long enough
136+
--> $DIR/fn_def_coercion.rs:54:5
137+
|
138+
LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
139+
| -- -- lifetime `'b` defined here
140+
| |
141+
| lifetime `'a` defined here
142+
...
143+
LL | x(b);
144+
| ^^^^ argument requires that `'b` must outlive `'a`
145+
|
146+
= help: consider adding the following bound: `'b: 'a`
147+
148+
help: the following changes may resolve your lifetime errors
149+
|
150+
= help: add bound `'a: 'c`
151+
= help: add bound `'b: 'a`
152+
153+
error: aborting due to 9 previous errors
154+

tests/ui/fn/fn_def_opaque_coercion.rs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//! Test that coercing between function items of the same function,
2+
//! but with different args works.
3+
4+
#![feature(type_alias_impl_trait)]
5+
6+
fn foo<T>(t: T) -> T {
7+
t
8+
}
9+
10+
type F = impl Sized;
11+
12+
fn f(a: F) {
13+
let mut x = foo::<F>;
14+
x = foo::<()>;
15+
x(a);
16+
x(());
17+
}
18+
19+
type G = impl Sized;
20+
21+
fn g(a: G) {
22+
let x = foo::<()>;
23+
let _: () = x(a);
24+
}
25+
26+
type H = impl Sized;
27+
28+
fn h(a: H) {
29+
let x = foo::<H>;
30+
let _: H = x(());
31+
}
32+
33+
type I = impl Sized;
34+
35+
fn i(a: I) {
36+
let mut x = foo::<()>;
37+
x = foo::<I>;
38+
x(a);
39+
x(());
40+
}
41+
42+
type J = impl Sized;
43+
44+
fn j(a: J) {
45+
let x = match true {
46+
true => foo::<J>,
47+
false => foo::<()>, //~ ERROR: incompatible types
48+
};
49+
x(a);
50+
x(());
51+
}
52+
53+
fn k() -> impl Sized {
54+
fn bind<T, F: FnOnce(T) -> T>(_: T, f: F) -> F {
55+
f
56+
}
57+
let x = match true {
58+
true => {
59+
let f = foo;
60+
bind(k(), f)
61+
}
62+
false => foo::<()>, //~ ERROR: incompatible types
63+
};
64+
todo!()
65+
}
66+
67+
fn main() {}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
error[E0308]: `match` arms have incompatible types
2+
--> $DIR/fn_def_opaque_coercion.rs:47:18
3+
|
4+
LL | type J = impl Sized;
5+
| ---------- the expected opaque type
6+
...
7+
LL | let x = match true {
8+
| _____________-
9+
LL | | true => foo::<J>,
10+
| | -------- this is found to be of type `fn(J) -> J {foo::<J>}`
11+
LL | | false => foo::<()>,
12+
| | ^^^^^^^^^ expected opaque type, found `()`
13+
LL | | };
14+
| |_____- `match` arms have incompatible types
15+
|
16+
= note: expected fn item `fn(J) -> J {foo::<J>}`
17+
found fn item `fn(()) {foo::<()>}`
18+
19+
error[E0308]: `match` arms have incompatible types
20+
--> $DIR/fn_def_opaque_coercion.rs:62:18
21+
|
22+
LL | fn k() -> impl Sized {
23+
| ---------- the expected opaque type
24+
...
25+
LL | let x = match true {
26+
| _____________-
27+
LL | | true => {
28+
LL | | let f = foo;
29+
LL | | bind(k(), f)
30+
| | ------------ this is found to be of type `fn(impl Sized) -> impl Sized {foo::<impl Sized>}`
31+
LL | | }
32+
LL | | false => foo::<()>,
33+
| | ^^^^^^^^^ expected opaque type, found `()`
34+
LL | | };
35+
| |_____- `match` arms have incompatible types
36+
|
37+
= note: expected fn item `fn(impl Sized) -> impl Sized {foo::<impl Sized>}`
38+
found fn item `fn(()) {foo::<()>}`
39+
40+
error: aborting due to 2 previous errors
41+
42+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)