Skip to content

Commit 9fd0ab6

Browse files
authored
Rollup merge of #141334 - lcnr:coerce-nested-obligations, r=compiler-errors
eagerly check nested obligations when coercing fndefs fixes rust-lang/trait-system-refactor-initiative#212 r? `@compiler-errors`
2 parents ab9109a + 196c3b3 commit 9fd0ab6

11 files changed

+47
-3
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,9 +1190,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11901190
(ty::FnDef(..), ty::FnDef(..)) => {
11911191
// Don't reify if the function types have a LUB, i.e., they
11921192
// are the same function and their parameters have a LUB.
1193-
match self
1194-
.commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty))
1195-
{
1193+
match self.commit_if_ok(|_| {
1194+
// We need to eagerly handle nested obligations due to lazy norm.
1195+
if self.next_trait_solver() {
1196+
let ocx = ObligationCtxt::new(self);
1197+
let value = ocx.lub(cause, self.param_env, prev_ty, new_ty)?;
1198+
if ocx.select_where_possible().is_empty() {
1199+
Ok(InferOk {
1200+
value,
1201+
obligations: ocx.into_pending_obligations(),
1202+
})
1203+
} else {
1204+
Err(TypeError::Mismatch)
1205+
}
1206+
} else {
1207+
self.at(cause, self.param_env).lub(prev_ty, new_ty)
1208+
}
1209+
}) {
11961210
// We have a LUB of prev_ty and new_ty, just return it.
11971211
Ok(ok) => return Ok(self.register_infer_ok_obligations(ok)),
11981212
Err(_) => {

compiler/rustc_trait_selection/src/traits/engine.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,20 @@ where
188188
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
189189
}
190190

191+
/// Computes the least-upper-bound, or mutual supertype, of two values.
192+
pub fn lub<T: ToTrace<'tcx>>(
193+
&self,
194+
cause: &ObligationCause<'tcx>,
195+
param_env: ty::ParamEnv<'tcx>,
196+
expected: T,
197+
actual: T,
198+
) -> Result<T, TypeError<'tcx>> {
199+
self.infcx
200+
.at(cause, param_env)
201+
.lub(expected, actual)
202+
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
203+
}
204+
191205
#[must_use]
192206
pub fn select_where_possible(&self) -> Vec<E> {
193207
self.engine.borrow_mut().select_where_possible(self.infcx)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ compile-flags: -Znext-solver
2+
//@ check-pass
3+
4+
// Make sure that we consider nested obligations when checking whether
5+
// we should coerce fn definitions to function pointers.
6+
7+
fn foo<const N: usize>() {}
8+
fn bar<T>() {}
9+
fn main() {
10+
let _ = if true { foo::<{ 0 + 0 }> } else { foo::<1> };
11+
let _ = if true {
12+
bar::<for<'a> fn(<Vec<&'a ()> as IntoIterator>::Item)>
13+
} else {
14+
bar::<fn(i32)>
15+
};
16+
}

0 commit comments

Comments
 (0)