@@ -56,18 +56,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
56
56
// It's always helpful for inference if we know the kind of
57
57
// closure sooner rather than later, so first examine the expected
58
58
// type, and see if can glean a closure kind from there.
59
- let (expected_sig, expected_kind) = match closure.kind {
60
- hir::ClosureKind::Closure => match expected.to_option(self) {
61
- Some(ty) => {
62
- self.deduce_closure_signature(self.try_structurally_resolve_type(expr_span, ty))
63
- }
64
- None => (None, None),
65
- },
66
- // We don't want to deduce a signature from `Fn` bounds for coroutines
67
- // or coroutine-closures, because the former does not implement `Fn`
68
- // ever, and the latter's signature doesn't correspond to the coroutine
69
- // type that it returns.
70
- hir::ClosureKind::Coroutine(_) | hir::ClosureKind::CoroutineClosure(_) => (None, None),
59
+ let (expected_sig, expected_kind) = match expected.to_option(self) {
60
+ Some(ty) => self.deduce_closure_signature(
61
+ self.try_structurally_resolve_type(expr_span, ty),
62
+ closure.kind,
63
+ ),
64
+ None => (None, None),
71
65
};
72
66
73
67
let ClosureSignatures { bound_sig, mut liberated_sig } =
@@ -323,11 +317,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
323
317
fn deduce_closure_signature(
324
318
&self,
325
319
expected_ty: Ty<'tcx>,
320
+ closure_kind: hir::ClosureKind,
326
321
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
327
322
match *expected_ty.kind() {
328
323
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
329
324
.deduce_closure_signature_from_predicates(
330
325
expected_ty,
326
+ closure_kind,
331
327
self.tcx
332
328
.explicit_item_bounds(def_id)
333
329
.iter_instantiated_copied(self.tcx, args)
@@ -336,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
336
332
ty::Dynamic(object_type, ..) => {
337
333
let sig = object_type.projection_bounds().find_map(|pb| {
338
334
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
339
- self.deduce_sig_from_projection(None, pb)
335
+ self.deduce_sig_from_projection(None, closure_kind, pb)
340
336
});
341
337
let kind = object_type
342
338
.principal_def_id()
@@ -345,19 +341,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
345
341
}
346
342
ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates(
347
343
Ty::new_var(self.tcx, self.root_var(vid)),
344
+ closure_kind,
348
345
self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
349
346
),
350
- ty::FnPtr(sig) => {
351
- let expected_sig = ExpectedSig { cause_span: None, sig };
352
- (Some(expected_sig), Some(ty::ClosureKind::Fn))
353
- }
347
+ ty::FnPtr(sig) => match closure_kind {
348
+ hir::ClosureKind::Closure => {
349
+ let expected_sig = ExpectedSig { cause_span: None, sig };
350
+ (Some(expected_sig), Some(ty::ClosureKind::Fn))
351
+ }
352
+ hir::ClosureKind::Coroutine(_) | hir::ClosureKind::CoroutineClosure(_) => {
353
+ (None, None)
354
+ }
355
+ },
354
356
_ => (None, None),
355
357
}
356
358
}
357
359
358
360
fn deduce_closure_signature_from_predicates(
359
361
&self,
360
362
expected_ty: Ty<'tcx>,
363
+ closure_kind: hir::ClosureKind,
361
364
predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
362
365
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
363
366
let mut expected_sig = None;
@@ -386,6 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
386
389
span,
387
390
self.deduce_sig_from_projection(
388
391
Some(span),
392
+ closure_kind,
389
393
bound_predicate.rebind(proj_predicate),
390
394
),
391
395
);
@@ -422,13 +426,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
422
426
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => Some(data.def_id()),
423
427
_ => None,
424
428
};
425
- if let Some(closure_kind) =
426
- trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_def_id(def_id))
427
- {
428
- expected_kind = Some(
429
- expected_kind
430
- .map_or_else(|| closure_kind, |current| cmp::min(current, closure_kind)),
431
- );
429
+
430
+ if let Some(trait_def_id) = trait_def_id {
431
+ let found_kind = match closure_kind {
432
+ hir::ClosureKind::Closure => self.tcx.fn_trait_kind_from_def_id(trait_def_id),
433
+ hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => {
434
+ self.tcx.async_fn_trait_kind_from_def_id(trait_def_id)
435
+ }
436
+ _ => None,
437
+ };
438
+
439
+ if let Some(found_kind) = found_kind {
440
+ expected_kind = Some(
441
+ expected_kind
442
+ .map_or_else(|| found_kind, |current| cmp::min(current, found_kind)),
443
+ );
444
+ }
432
445
}
433
446
}
434
447
@@ -445,14 +458,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
445
458
fn deduce_sig_from_projection(
446
459
&self,
447
460
cause_span: Option<Span>,
461
+ closure_kind: hir::ClosureKind,
448
462
projection: ty::PolyProjectionPredicate<'tcx>,
449
463
) -> Option<ExpectedSig<'tcx>> {
450
464
let tcx = self.tcx;
451
465
452
466
let trait_def_id = projection.trait_def_id(tcx);
453
- // For now, we only do signature deduction based off of the `Fn` traits.
454
- if !tcx.is_fn_trait(trait_def_id) {
455
- return None;
467
+
468
+ // For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
469
+ // for closures and async closures, respectively.
470
+ match closure_kind {
471
+ hir::ClosureKind::Closure
472
+ if self.tcx.fn_trait_kind_from_def_id(trait_def_id).is_some() => {}
473
+ hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async)
474
+ if self.tcx.async_fn_trait_kind_from_def_id(trait_def_id).is_some() => {}
475
+ _ => return None,
456
476
}
457
477
458
478
let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
0 commit comments