Skip to content

Commit b5c79a9

Browse files
committed
leak check lub in fndef<->fndef coerce-lubs
1 parent dde25a6 commit b5c79a9

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,9 +1174,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11741174
(ty::FnDef(..), ty::FnDef(..)) => {
11751175
// Don't reify if the function types have a LUB, i.e., they
11761176
// are the same function and their parameters have a LUB.
1177-
match self.commit_if_ok(|_| {
1177+
match self.commit_if_ok(|snapshot| {
1178+
let outer_universe = self.infcx.universe();
1179+
11781180
// We need to eagerly handle nested obligations due to lazy norm.
1179-
if self.next_trait_solver() {
1181+
let result = if self.next_trait_solver() {
11801182
let ocx = ObligationCtxt::new(self);
11811183
let value = ocx.lub(cause, self.param_env, prev_ty, new_ty)?;
11821184
if ocx.try_evaluate_obligations().is_empty() {
@@ -1189,7 +1191,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11891191
}
11901192
} else {
11911193
self.at(cause, self.param_env).lub(prev_ty, new_ty)
1192-
}
1194+
};
1195+
1196+
self.leak_check(outer_universe, Some(snapshot))?;
1197+
result
11931198
}) {
11941199
// We have a LUB of prev_ty and new_ty, just return it.
11951200
Ok(ok) => return Ok(self.register_infer_ok_obligations(ok)),
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//@ check-pass
2+
3+
fn foo<T>() {}
4+
5+
fn fndef_lub_leak_check() {
6+
macro_rules! lub {
7+
($lhs:expr, $rhs:expr) => {
8+
if true { $lhs } else { $rhs }
9+
};
10+
}
11+
12+
// These don't current lub but could in theory one day.
13+
// If that happens this test should be adjusted to use
14+
// fn ptrs that can't be lub'd.
15+
let lhs = foo::<for<'a> fn(&'static (), &'a ())>;
16+
let rhs = foo::<for<'a> fn(&'a (), &'static ())>;
17+
18+
// If we leak check then we know we should coerce these
19+
// to `fn()`, if we don't leak check we may try to keep
20+
// them as `FnDef`s which would result in a borrowck
21+
// error.
22+
let lubbed = lub!(lhs, rhs);
23+
24+
// assert that we coerced lhs/rhs to a fn ptr
25+
is_fnptr(lubbed);
26+
}
27+
28+
trait FnPtr {}
29+
impl FnPtr for fn() {}
30+
fn is_fnptr<T: FnPtr>(_: T) {}
31+
32+
fn main() {}

0 commit comments

Comments
 (0)