Skip to content

Commit 7391a34

Browse files
committed
leak check when lubbing closures/fndefs to fnptrs
1 parent a3bb431 commit 7391a34

File tree

4 files changed

+269
-0
lines changed

4 files changed

+269
-0
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,11 +1210,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12101210
if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) {
12111211
// The signature must match.
12121212
let (a_sig, b_sig) = self.normalize(new.span, (a_sig, b_sig));
1213+
let outer_universe = self.infcx.universe();
12131214
let sig = self
12141215
.at(cause, self.param_env)
12151216
.lub(a_sig, b_sig)
12161217
.map(|ok| self.register_infer_ok_obligations(ok))?;
12171218

1219+
self.leak_check(outer_universe, None)?;
1220+
12181221
// Reify both sides and return the reified fn pointer type.
12191222
let fn_ptr = Ty::new_fn_ptr(self.tcx, sig);
12201223
let prev_adjustment = match prev_ty.kind() {
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
error[E0308]: `if` and `else` have incompatible types
2+
--> $DIR/leak_check_lub_to_fnptr.rs:21:21
3+
|
4+
LL | lub!(lhs_fnptr, rhs_fnptr);
5+
| --------- ^^^^^^^^^ one type is more general than the other
6+
| |
7+
| expected because of this
8+
|
9+
= note: expected fn pointer `for<'a> fn(&'a (), &())`
10+
found fn pointer `for<'a> fn(&(), &'a ())`
11+
12+
error[E0308]: `if` and `else` have incompatible types
13+
--> $DIR/leak_check_lub_to_fnptr.rs:27:21
14+
|
15+
LL | lub!(lhs_fndef, rhs_fndef);
16+
| --------- ^^^^^^^^^ one type is more general than the other
17+
| |
18+
| expected because of this
19+
|
20+
= note: expected fn item `for<'a> fn(&'a (), &'static ()) {lub_to_fnptr_leak_checking::lhs_fndef}`
21+
found fn item `for<'a> fn(&'static (), &'a ()) {lub_to_fnptr_leak_checking::rhs_fndef}`
22+
23+
error[E0308]: `if` and `else` have incompatible types
24+
--> $DIR/leak_check_lub_to_fnptr.rs:33:23
25+
|
26+
LL | let lhs_closure = |_: &(), _: &'static ()| {};
27+
| ------------------------ the expected closure
28+
LL | let rhs_closure = |_: &'static (), _: &()| {};
29+
| ------------------------ the found closure
30+
LL | lub!(lhs_closure, rhs_closure);
31+
| ----------- ^^^^^^^^^^^ one type is more general than the other
32+
| |
33+
| expected because of this
34+
|
35+
= note: expected closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:31:23: 31:47}`
36+
found closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:32:23: 32:47}`
37+
= note: closure has signature: `for<'a> fn(&'static (), &'a ())`
38+
= note: no two closures, even if identical, have the same type
39+
= help: consider boxing your closure and/or using it as a trait object
40+
41+
error[E0308]: `if` and `else` have incompatible types
42+
--> $DIR/leak_check_lub_to_fnptr.rs:42:23
43+
|
44+
LL | let lhs_closure = |_: &(), _: &'static ()| {};
45+
| ------------------------ the expected closure
46+
LL | let rhs_closure = |_: &'static (), _: &'static ()| {};
47+
| -------------------------------- the found closure
48+
LL |
49+
LL | lub!(lhs_closure, rhs_closure);
50+
| ----------- ^^^^^^^^^^^ one type is more general than the other
51+
| |
52+
| expected because of this
53+
|
54+
= note: expected closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:39:23: 39:47}`
55+
found closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:40:23: 40:55}`
56+
= note: closure has signature: `fn(&'static (), &'static ())`
57+
= note: no two closures, even if identical, have the same type
58+
= help: consider boxing your closure and/or using it as a trait object
59+
60+
error[E0308]: `if` and `else` have incompatible types
61+
--> $DIR/leak_check_lub_to_fnptr.rs:44:23
62+
|
63+
LL | let lhs_closure = |_: &(), _: &'static ()| {};
64+
| ------------------------ the found closure
65+
LL | let rhs_closure = |_: &'static (), _: &'static ()| {};
66+
| -------------------------------- the expected closure
67+
...
68+
LL | lub!(rhs_closure, lhs_closure);
69+
| ----------- ^^^^^^^^^^^ one type is more general than the other
70+
| |
71+
| expected because of this
72+
|
73+
= note: expected closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:40:23: 40:55}`
74+
found closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:39:23: 39:47}`
75+
= note: closure has signature: `for<'a> fn(&'a (), &'static ())`
76+
= note: no two closures, even if identical, have the same type
77+
= help: consider boxing your closure and/or using it as a trait object
78+
79+
error[E0308]: `if` and `else` have incompatible types
80+
--> $DIR/leak_check_lub_to_fnptr.rs:54:21
81+
|
82+
LL | lub!(lhs_fndef, rhs_fndef);
83+
| --------- ^^^^^^^^^ one type is more general than the other
84+
| |
85+
| expected because of this
86+
|
87+
= note: expected fn item `for<'a> fn(&'a (), &'static ()) {order_dependence_fndefs::lhs_fndef}`
88+
found fn item `fn(&'static (), &'static ()) {order_dependence_fndefs::rhs_fndef}`
89+
90+
error[E0308]: `if` and `else` have incompatible types
91+
--> $DIR/leak_check_lub_to_fnptr.rs:56:21
92+
|
93+
LL | lub!(rhs_fndef, lhs_fndef);
94+
| --------- ^^^^^^^^^ one type is more general than the other
95+
| |
96+
| expected because of this
97+
|
98+
= note: expected fn item `fn(&'static (), &'static ()) {order_dependence_fndefs::rhs_fndef}`
99+
found fn item `for<'a> fn(&'a (), &'static ()) {order_dependence_fndefs::lhs_fndef}`
100+
101+
error: aborting due to 7 previous errors
102+
103+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
error[E0308]: `if` and `else` have incompatible types
2+
--> $DIR/leak_check_lub_to_fnptr.rs:21:21
3+
|
4+
LL | lub!(lhs_fnptr, rhs_fnptr);
5+
| --------- ^^^^^^^^^ one type is more general than the other
6+
| |
7+
| expected because of this
8+
|
9+
= note: expected fn pointer `for<'a> fn(&'a (), &())`
10+
found fn pointer `for<'a> fn(&(), &'a ())`
11+
12+
error[E0308]: `if` and `else` have incompatible types
13+
--> $DIR/leak_check_lub_to_fnptr.rs:27:21
14+
|
15+
LL | lub!(lhs_fndef, rhs_fndef);
16+
| --------- ^^^^^^^^^ one type is more general than the other
17+
| |
18+
| expected because of this
19+
|
20+
= note: expected fn item `for<'a> fn(&'a (), &'static ()) {lub_to_fnptr_leak_checking::lhs_fndef}`
21+
found fn item `for<'a> fn(&'static (), &'a ()) {lub_to_fnptr_leak_checking::rhs_fndef}`
22+
23+
error[E0308]: `if` and `else` have incompatible types
24+
--> $DIR/leak_check_lub_to_fnptr.rs:33:23
25+
|
26+
LL | let lhs_closure = |_: &(), _: &'static ()| {};
27+
| ------------------------ the expected closure
28+
LL | let rhs_closure = |_: &'static (), _: &()| {};
29+
| ------------------------ the found closure
30+
LL | lub!(lhs_closure, rhs_closure);
31+
| ----------- ^^^^^^^^^^^ one type is more general than the other
32+
| |
33+
| expected because of this
34+
|
35+
= note: expected closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:31:23: 31:47}`
36+
found closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:32:23: 32:47}`
37+
= note: closure has signature: `for<'a> fn(&'static (), &'a ())`
38+
= note: no two closures, even if identical, have the same type
39+
= help: consider boxing your closure and/or using it as a trait object
40+
41+
error[E0308]: `if` and `else` have incompatible types
42+
--> $DIR/leak_check_lub_to_fnptr.rs:42:23
43+
|
44+
LL | let lhs_closure = |_: &(), _: &'static ()| {};
45+
| ------------------------ the expected closure
46+
LL | let rhs_closure = |_: &'static (), _: &'static ()| {};
47+
| -------------------------------- the found closure
48+
LL |
49+
LL | lub!(lhs_closure, rhs_closure);
50+
| ----------- ^^^^^^^^^^^ one type is more general than the other
51+
| |
52+
| expected because of this
53+
|
54+
= note: expected closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:39:23: 39:47}`
55+
found closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:40:23: 40:55}`
56+
= note: closure has signature: `fn(&'static (), &'static ())`
57+
= note: no two closures, even if identical, have the same type
58+
= help: consider boxing your closure and/or using it as a trait object
59+
60+
error[E0308]: `if` and `else` have incompatible types
61+
--> $DIR/leak_check_lub_to_fnptr.rs:44:23
62+
|
63+
LL | let lhs_closure = |_: &(), _: &'static ()| {};
64+
| ------------------------ the found closure
65+
LL | let rhs_closure = |_: &'static (), _: &'static ()| {};
66+
| -------------------------------- the expected closure
67+
...
68+
LL | lub!(rhs_closure, lhs_closure);
69+
| ----------- ^^^^^^^^^^^ one type is more general than the other
70+
| |
71+
| expected because of this
72+
|
73+
= note: expected closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:40:23: 40:55}`
74+
found closure `{closure@$DIR/leak_check_lub_to_fnptr.rs:39:23: 39:47}`
75+
= note: closure has signature: `for<'a> fn(&'a (), &'static ())`
76+
= note: no two closures, even if identical, have the same type
77+
= help: consider boxing your closure and/or using it as a trait object
78+
79+
error[E0308]: `if` and `else` have incompatible types
80+
--> $DIR/leak_check_lub_to_fnptr.rs:54:21
81+
|
82+
LL | lub!(lhs_fndef, rhs_fndef);
83+
| --------- ^^^^^^^^^ one type is more general than the other
84+
| |
85+
| expected because of this
86+
|
87+
= note: expected fn item `for<'a> fn(&'a (), &'static ()) {order_dependence_fndefs::lhs_fndef}`
88+
found fn item `fn(&'static (), &'static ()) {order_dependence_fndefs::rhs_fndef}`
89+
90+
error[E0308]: `if` and `else` have incompatible types
91+
--> $DIR/leak_check_lub_to_fnptr.rs:56:21
92+
|
93+
LL | lub!(rhs_fndef, lhs_fndef);
94+
| --------- ^^^^^^^^^ one type is more general than the other
95+
| |
96+
| expected because of this
97+
|
98+
= note: expected fn item `fn(&'static (), &'static ()) {order_dependence_fndefs::rhs_fndef}`
99+
found fn item `for<'a> fn(&'a (), &'static ()) {order_dependence_fndefs::lhs_fndef}`
100+
101+
error: aborting due to 7 previous errors
102+
103+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//@ revisions: livecode deadcode
2+
3+
#![allow(unreachable_code)]
4+
5+
fn mk<T>() -> T {
6+
loop {}
7+
}
8+
9+
macro_rules! lub {
10+
($lhs:expr, $rhs:expr) => {
11+
if true { $lhs } else { $rhs }
12+
};
13+
}
14+
15+
fn lub_to_fnptr_leak_checking() {
16+
#[cfg(deadcode)]
17+
loop {}
18+
19+
let lhs_fnptr = mk::<fn(&(), &'static ())>();
20+
let rhs_fnptr = mk::<fn(&'static (), &())>();
21+
lub!(lhs_fnptr, rhs_fnptr);
22+
//[livecode]~^ ERROR: `if` and `else` have incompatible types
23+
//[deadcode]~^^ ERROR: `if` and `else` have incompatible types
24+
25+
fn lhs_fndef(_: &(), _: &'static ()) {};
26+
fn rhs_fndef(_: &'static (), _: &()) {};
27+
lub!(lhs_fndef, rhs_fndef);
28+
//[livecode]~^ ERROR: `if` and `else` have incompatible types
29+
//[deadcode]~^^ ERROR: `if` and `else` have incompatible types
30+
31+
let lhs_closure = |_: &(), _: &'static ()| {};
32+
let rhs_closure = |_: &'static (), _: &()| {};
33+
lub!(lhs_closure, rhs_closure);
34+
//[livecode]~^ ERROR: `if` and `else` have incompatible types
35+
//[deadcode]~^^ ERROR: `if` and `else` have incompatible types
36+
}
37+
38+
fn order_dependence_closures() {
39+
let lhs_closure = |_: &(), _: &'static ()| {};
40+
let rhs_closure = |_: &'static (), _: &'static ()| {};
41+
42+
lub!(lhs_closure, rhs_closure);
43+
//~^ ERROR: `if` and `else` have incompatible types
44+
lub!(rhs_closure, lhs_closure);
45+
//~^ ERROR: `if` and `else` have incompatible types
46+
47+
}
48+
49+
50+
fn order_dependence_fndefs() {
51+
fn lhs_fndef(_: &(), _: &'static ()) {}
52+
fn rhs_fndef(_: &'static (), _: &'static ()) {}
53+
54+
lub!(lhs_fndef, rhs_fndef);
55+
//~^ ERROR: `if` and `else` have incompatible types
56+
lub!(rhs_fndef, lhs_fndef);
57+
//~^ ERROR: `if` and `else` have incompatible types
58+
}
59+
60+
fn main() {}

0 commit comments

Comments
 (0)