Rollup merge of #116436 - compiler-errors:structurally-normalize-for-closure, r=lcnr

Structurally normalize for closure

Fixes some signature deduction problems in the new trait solver (and in the case of async, an ICE).

r? lcnr
This commit is contained in:
Matthias Krüger 2023-10-11 20:08:21 +02:00 committed by GitHub
commit 3712ea82f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 7 deletions

View File

@ -56,7 +56,9 @@ pub fn check_expr_closure(
// closure sooner rather than later, so first examine the expected // closure sooner rather than later, so first examine the expected
// type, and see if can glean a closure kind from there. // type, and see if can glean a closure kind from there.
let (expected_sig, expected_kind) = match expected.to_option(self) { let (expected_sig, expected_kind) = match expected.to_option(self) {
Some(ty) => self.deduce_closure_signature(ty), Some(ty) => {
self.deduce_closure_signature(self.try_structurally_resolve_type(expr_span, ty))
}
None => (None, None), None => (None, None),
}; };
let body = self.tcx.hir().body(closure.body); let body = self.tcx.hir().body(closure.body);
@ -688,8 +690,9 @@ fn deduce_future_output_from_obligations(
span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn") span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn")
}); });
let closure_span = self.tcx.def_span(expr_def_id);
let ret_ty = ret_coercion.borrow().expected_ty(); let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); let ret_ty = self.try_structurally_resolve_type(closure_span, ret_ty);
let get_future_output = |predicate: ty::Predicate<'tcx>, span| { let get_future_output = |predicate: ty::Predicate<'tcx>, span| {
// Search for a pending obligation like // Search for a pending obligation like
@ -711,8 +714,6 @@ fn deduce_future_output_from_obligations(
} }
}; };
let span = self.tcx.def_span(expr_def_id);
let output_ty = match *ret_ty.kind() { let output_ty = match *ret_ty.kind() {
ty::Infer(ty::TyVar(ret_vid)) => { ty::Infer(ty::TyVar(ret_vid)) => {
self.obligations_for_self_ty(ret_vid).find_map(|obligation| { self.obligations_for_self_ty(ret_vid).find_map(|obligation| {
@ -726,17 +727,22 @@ fn deduce_future_output_from_obligations(
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
ty::Error(_) => return None, ty::Error(_) => return None,
_ => span_bug!( _ => span_bug!(
span, closure_span,
"async fn generator return type not an inference variable: {ret_ty}" "async fn generator return type not an inference variable: {ret_ty}"
), ),
}; };
let output_ty = self.normalize(span, output_ty); let output_ty = self.normalize(closure_span, output_ty);
// async fn that have opaque types in their return type need to redo the conversion to inference variables // async fn that have opaque types in their return type need to redo the conversion to inference variables
// as they fetch the still opaque version from the signature. // as they fetch the still opaque version from the signature.
let InferOk { value: output_ty, obligations } = self let InferOk { value: output_ty, obligations } = self
.replace_opaque_types_with_inference_vars(output_ty, body_def_id, span, self.param_env); .replace_opaque_types_with_inference_vars(
output_ty,
body_def_id,
closure_span,
self.param_env,
);
self.register_predicates(obligations); self.register_predicates(obligations);
Some(output_ty) Some(output_ty)

View File

@ -0,0 +1,12 @@
// compile-flags: -Ztrait-solver=next
// check-pass
#![feature(return_position_impl_trait_in_trait)]
trait Foo {
fn test() -> impl Fn(u32) -> u32 {
|x| x.count_ones()
}
}
fn main() {}

View File

@ -0,0 +1,11 @@
// compile-flags: -Ztrait-solver=next
// check-pass
// edition:2021
#![feature(async_fn_in_trait)]
trait Foo {
async fn bar() {}
}
fn main() {}