1pub(crate) mod analysis;
4
5use std::{iter, mem, ops::ControlFlow};
6
7use hir_def::{
8 AdtId, TraitId,
9 hir::{ClosureKind, CoroutineKind, CoroutineSource, ExprId, PatId},
10 type_ref::TypeRefId,
11};
12use rustc_abi::ExternAbi;
13use rustc_type_ir::{
14 AliasTyKind, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts,
15 CoroutineClosureArgs, CoroutineClosureArgsParts, InferTy, Interner, TypeSuperVisitable,
16 TypeVisitable, TypeVisitableExt, TypeVisitor,
17 inherent::{BoundExistentialPredicates, GenericArgs as _, IntoKind, Ty as _},
18};
19use tracing::{debug, instrument};
20
21use crate::{
22 Span,
23 db::{InternedClosure, InternedClosureId, InternedCoroutineClosureId, InternedCoroutineId},
24 infer::{BreakableKind, Diverges, coerce::CoerceMany, pat::PatOrigin},
25 next_solver::{
26 AliasTy, Binder, ClauseKind, DbInterner, ErrorGuaranteed, FnSig, GenericArg, PolyFnSig,
27 PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, TermId, Ty, TyKind,
28 Unnormalized,
29 abi::Safety,
30 infer::{
31 BoundRegionConversionTime, InferOk, InferResult,
32 traits::{ObligationCause, PredicateObligations},
33 },
34 },
35};
36
37use super::{Expectation, InferenceContext};
38
39#[derive(Debug)]
40struct ClosureSignatures<'db> {
41 bound_sig: PolyFnSig<'db>,
43 liberated_sig: FnSig<'db>,
48}
49
50impl<'db> InferenceContext<'db> {
51 fn poll_option_ty(&mut self, item_ty: Ty<'db>) -> Ty<'db> {
52 let interner = self.interner();
53
54 let (Some(option), Some(poll)) = (self.lang_items.Option, self.lang_items.Poll) else {
55 return self.types.types.error;
56 };
57
58 let option_ty = Ty::new_adt(
59 interner,
60 AdtId::EnumId(option),
61 interner.mk_args(&[GenericArg::from(item_ty)]),
62 );
63
64 Ty::new_adt(interner, AdtId::EnumId(poll), interner.mk_args(&[GenericArg::from(option_ty)]))
65 }
66
67 pub(super) fn infer_closure(
68 &mut self,
69 body: ExprId,
70 args: &[PatId],
71 ret_type: Option<TypeRefId>,
72 arg_types: &[Option<TypeRefId>],
73 closure_kind: ClosureKind,
74 closure_expr: ExprId,
75 expected: &Expectation<'db>,
76 ) -> Ty<'db> {
77 assert_eq!(args.len(), arg_types.len());
78
79 let interner = self.interner();
80 let (expected_sig, expected_kind) = match expected.to_option(&self.table) {
84 Some(ty) => {
85 let ty = self.table.try_structurally_resolve_type(closure_expr.into(), ty);
86 self.deduce_closure_signature(closure_expr, ty, closure_kind)
87 }
88 None => (None, None),
89 };
90
91 let ClosureSignatures { bound_sig, mut liberated_sig } = self.sig_of_closure(
92 closure_expr,
93 args,
94 arg_types,
95 ret_type,
96 expected_sig,
97 closure_kind,
98 );
99
100 debug!(?bound_sig, ?liberated_sig);
101
102 let parent_args = self.identity_args();
103
104 let tupled_upvars_ty = self.table.next_ty_var(closure_expr.into());
105
106 let closure_loc =
107 InternedClosure { owner: self.owner, expr: closure_expr, kind: closure_kind };
108 let (closure_ty, resume_yield_tys) = match closure_kind {
113 ClosureKind::Closure => {
114 let sig = bound_sig.map_bound(|sig| {
117 interner.mk_fn_sig(
118 [Ty::new_tup(interner, sig.inputs())],
119 sig.output(),
120 sig.c_variadic(),
121 sig.safety(),
122 sig.abi(),
123 )
124 });
125
126 debug!(?sig, ?expected_kind);
127
128 let closure_kind_ty = match expected_kind {
129 Some(kind) => Ty::from_closure_kind(interner, kind),
130 None => self.table.next_ty_var(closure_expr.into()),
133 };
134
135 let closure_args = ClosureArgs::new(
136 interner,
137 ClosureArgsParts {
138 parent_args: parent_args.as_slice(),
139 closure_kind_ty,
140 closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(interner, sig),
141 tupled_upvars_ty,
142 },
143 );
144
145 let closure_id = InternedClosureId::new(self.db, closure_loc);
146
147 (Ty::new_closure(interner, closure_id.into(), closure_args.args), None)
148 }
149 ClosureKind::OldCoroutine(_) | ClosureKind::Coroutine { .. } => {
150 let yield_ty = match closure_kind {
151 ClosureKind::OldCoroutine(_)
152 | ClosureKind::Coroutine { kind: CoroutineKind::Gen, .. } => {
153 let yield_ty = self.table.next_ty_var(closure_expr.into());
154 self.require_type_is_sized(yield_ty, closure_expr.into());
155 yield_ty
156 }
157 ClosureKind::Coroutine { kind: CoroutineKind::Async, .. } => {
158 self.types.types.unit
159 }
160 ClosureKind::Coroutine { kind: CoroutineKind::AsyncGen, .. } => {
161 let yield_ty = self.table.next_ty_var(closure_expr.into());
162 self.require_type_is_sized(yield_ty, closure_expr.into());
163 self.poll_option_ty(yield_ty)
164 }
165 _ => unreachable!(),
166 };
167
168 let resume_ty =
170 liberated_sig.inputs().first().copied().unwrap_or(self.types.types.unit);
171
172 let kind_ty = match closure_kind {
177 ClosureKind::Coroutine { source: CoroutineSource::Closure, .. } => {
178 self.table.next_ty_var(closure_expr.into())
179 }
180 _ => self.types.types.unit,
181 };
182
183 let coroutine_args = CoroutineArgs::new(
184 interner,
185 CoroutineArgsParts {
186 parent_args: parent_args.as_slice(),
187 kind_ty,
188 resume_ty,
189 yield_ty,
190 return_ty: liberated_sig.output(),
191 tupled_upvars_ty,
192 },
193 );
194
195 let coroutine_id = InternedCoroutineId::new(self.db, closure_loc);
196
197 (
198 Ty::new_coroutine(interner, coroutine_id.into(), coroutine_args.args),
199 Some((resume_ty, yield_ty)),
200 )
201 }
202 ClosureKind::CoroutineClosure(coroutine_kind) => {
203 let (bound_return_ty, bound_yield_ty) = match coroutine_kind {
204 CoroutineKind::Gen => {
205 (self.types.types.unit, self.table.next_ty_var(closure_expr.into()))
206 }
207 CoroutineKind::Async => {
208 (bound_sig.skip_binder().output(), self.types.types.unit)
209 }
210 CoroutineKind::AsyncGen => {
211 let yield_ty = self.table.next_ty_var(closure_expr.into());
212 (self.types.types.unit, self.poll_option_ty(yield_ty))
213 }
214 };
215
216 let resume_ty = self.table.next_ty_var(closure_expr.into());
218
219 let closure_kind_ty = match expected_kind {
220 Some(kind) => Ty::from_closure_kind(interner, kind),
221
222 None => self.table.next_ty_var(closure_expr.into()),
225 };
226
227 let coroutine_captures_by_ref_ty = self.table.next_ty_var(closure_expr.into());
228
229 let closure_args = CoroutineClosureArgs::new(
230 interner,
231 CoroutineClosureArgsParts {
232 parent_args: parent_args.as_slice(),
233 closure_kind_ty,
234 signature_parts_ty: Ty::new_fn_ptr(
235 interner,
236 bound_sig.map_bound(|sig| {
237 interner.mk_fn_sig(
238 [
239 resume_ty,
240 Ty::new_tup_from_iter(
241 interner,
242 sig.inputs().iter().copied(),
243 ),
244 ],
245 Ty::new_tup(interner, &[bound_yield_ty, bound_return_ty]),
246 sig.c_variadic(),
247 sig.safety(),
248 sig.abi(),
249 )
250 }),
251 ),
252 tupled_upvars_ty,
253 coroutine_captures_by_ref_ty,
254 },
255 );
256
257 let coroutine_kind_ty = match expected_kind {
258 Some(kind) => Ty::from_coroutine_closure_kind(interner, kind),
259
260 None => self.table.next_ty_var(closure_expr.into()),
263 };
264
265 let coroutine_upvars_ty = self.table.next_ty_var(closure_expr.into());
266
267 let coroutine_closure_id = InternedCoroutineClosureId::new(self.db, closure_loc);
268
269 let coroutine_output_ty = closure_args
276 .coroutine_closure_sig()
277 .map_bound(|sig| {
278 sig.to_coroutine(
279 interner,
280 parent_args.as_slice(),
281 coroutine_kind_ty,
282 interner.coroutine_for_closure(coroutine_closure_id.into()),
283 coroutine_upvars_ty,
284 )
285 })
286 .skip_binder();
287 liberated_sig = interner.mk_fn_sig(
288 liberated_sig.inputs().iter().copied(),
289 coroutine_output_ty,
290 liberated_sig.c_variadic(),
291 liberated_sig.safety(),
292 liberated_sig.abi(),
293 );
294
295 (
296 Ty::new_coroutine_closure(
297 interner,
298 coroutine_closure_id.into(),
299 closure_args.args,
300 ),
301 None,
302 )
303 }
304 };
305
306 for (arg_pat, arg_ty) in args.iter().zip(liberated_sig.inputs()) {
308 self.infer_top_pat(*arg_pat, *arg_ty, PatOrigin::Param);
309 }
310
311 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
313 let prev_ret_ty = mem::replace(&mut self.return_ty, liberated_sig.output());
314 let prev_ret_coercion =
315 self.return_coercion.replace(CoerceMany::new(liberated_sig.output()));
316 let prev_resume_yield_tys = mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
317
318 self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
319 this.infer_return(body);
320 });
321
322 self.diverges = prev_diverges;
323 self.return_ty = prev_ret_ty;
324 self.return_coercion = prev_ret_coercion;
325 self.resume_yield_tys = prev_resume_yield_tys;
326
327 closure_ty
328 }
329
330 fn fn_trait_kind_from_def_id(&self, trait_id: TraitId) -> Option<rustc_type_ir::ClosureKind> {
331 match trait_id {
332 _ if self.lang_items.Fn == Some(trait_id) => Some(rustc_type_ir::ClosureKind::Fn),
333 _ if self.lang_items.FnMut == Some(trait_id) => Some(rustc_type_ir::ClosureKind::FnMut),
334 _ if self.lang_items.FnOnce == Some(trait_id) => {
335 Some(rustc_type_ir::ClosureKind::FnOnce)
336 }
337 _ => None,
338 }
339 }
340
341 fn async_fn_trait_kind_from_def_id(
342 &self,
343 trait_id: TraitId,
344 ) -> Option<rustc_type_ir::ClosureKind> {
345 match trait_id {
346 _ if self.lang_items.AsyncFn == Some(trait_id) => Some(rustc_type_ir::ClosureKind::Fn),
347 _ if self.lang_items.AsyncFnMut == Some(trait_id) => {
348 Some(rustc_type_ir::ClosureKind::FnMut)
349 }
350 _ if self.lang_items.AsyncFnOnce == Some(trait_id) => {
351 Some(rustc_type_ir::ClosureKind::FnOnce)
352 }
353 _ => None,
354 }
355 }
356
357 fn deduce_closure_signature(
360 &mut self,
361 closure_expr: ExprId,
362 expected_ty: Ty<'db>,
363 closure_kind: ClosureKind,
364 ) -> (Option<PolyFnSig<'db>>, Option<rustc_type_ir::ClosureKind>) {
365 match expected_ty.kind() {
366 TyKind::Alias(AliasTy { kind: rustc_type_ir::Opaque { def_id }, args, .. }) => self
367 .deduce_closure_signature_from_predicates(
368 closure_expr,
369 expected_ty,
370 closure_kind,
371 def_id
372 .0
373 .predicates(self.db)
374 .iter_instantiated_copied(self.interner(), args.as_slice())
375 .map(Unnormalized::skip_norm_wip)
376 .map(|clause| clause.as_predicate()),
377 ),
378 TyKind::Dynamic(object_type, ..) => {
379 let sig = object_type.projection_bounds().into_iter().find_map(|pb| {
380 let pb = pb.with_self_ty(self.interner(), Ty::new_unit(self.interner()));
381 self.deduce_sig_from_projection(closure_expr, closure_kind, pb)
382 });
383 let kind = object_type
384 .principal_def_id()
385 .and_then(|did| self.fn_trait_kind_from_def_id(did.0));
386 (sig, kind)
387 }
388 TyKind::Infer(rustc_type_ir::TyVar(vid)) => self
389 .deduce_closure_signature_from_predicates(
390 closure_expr,
391 Ty::new_var(self.interner(), self.table.infer_ctxt.root_var(vid)),
392 closure_kind,
393 self.table.obligations_for_self_ty(vid).into_iter().map(|obl| obl.predicate),
394 ),
395 TyKind::FnPtr(sig_tys, hdr) => match closure_kind {
396 ClosureKind::Closure => {
397 let expected_sig = sig_tys.with(hdr);
398 (Some(expected_sig), Some(rustc_type_ir::ClosureKind::Fn))
399 }
400 ClosureKind::OldCoroutine(_)
401 | ClosureKind::Coroutine { .. }
402 | ClosureKind::CoroutineClosure(_) => (None, None),
403 },
404 _ => (None, None),
405 }
406 }
407
408 fn deduce_closure_signature_from_predicates(
409 &mut self,
410 closure_expr: ExprId,
411 expected_ty: Ty<'db>,
412 closure_kind: ClosureKind,
413 predicates: impl DoubleEndedIterator<Item = Predicate<'db>>,
414 ) -> (Option<PolyFnSig<'db>>, Option<rustc_type_ir::ClosureKind>) {
415 let mut expected_sig = None;
416 let mut expected_kind = None;
417
418 for pred in rustc_type_ir::elaborate::elaborate(
419 self.interner(),
420 predicates.rev(),
424 )
425 .filter_only_self()
427 {
428 debug!(?pred);
429 let bound_predicate = pred.kind();
430
431 if expected_sig.is_none()
434 && let PredicateKind::Clause(ClauseKind::Projection(proj_predicate)) =
435 bound_predicate.skip_binder()
436 {
437 let inferred_sig = self.deduce_sig_from_projection(
438 closure_expr,
439 closure_kind,
440 bound_predicate.rebind(proj_predicate),
441 );
442
443 struct MentionsTy<'db> {
447 expected_ty: Ty<'db>,
448 }
449 impl<'db> TypeVisitor<DbInterner<'db>> for MentionsTy<'db> {
450 type Result = ControlFlow<()>;
451
452 fn visit_ty(&mut self, t: Ty<'db>) -> Self::Result {
453 if t == self.expected_ty {
454 ControlFlow::Break(())
455 } else {
456 t.super_visit_with(self)
457 }
458 }
459 }
460
461 if let Some(inferred_sig) = inferred_sig {
464 let generalized_fnptr_sig = self.table.next_ty_var(closure_expr.into());
482 let inferred_fnptr_sig = Ty::new_fn_ptr(self.interner(), inferred_sig);
483 _ = self
485 .table
486 .infer_ctxt
487 .at(&ObligationCause::new(closure_expr), self.table.param_env)
488 .eq(inferred_fnptr_sig, generalized_fnptr_sig)
489 .map(|infer_ok| self.table.register_infer_ok(infer_ok));
490
491 let resolved_sig = self.resolve_vars_if_possible(generalized_fnptr_sig);
492
493 if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
494 expected_sig = Some(resolved_sig.fn_sig(self.interner()));
495 }
496 } else if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
497 expected_sig = inferred_sig;
498 }
499 }
500
501 let trait_def_id = match bound_predicate.skip_binder() {
506 PredicateKind::Clause(ClauseKind::Projection(data)) => {
507 Some(data.projection_term.trait_def_id(self.interner()).0)
508 }
509 PredicateKind::Clause(ClauseKind::Trait(data)) => Some(data.def_id().0),
510 _ => None,
511 };
512
513 if let Some(trait_def_id) = trait_def_id {
514 let found_kind = match closure_kind {
515 ClosureKind::Closure | ClosureKind::CoroutineClosure(CoroutineKind::Gen) => {
516 self.fn_trait_kind_from_def_id(trait_def_id)
517 }
518 ClosureKind::CoroutineClosure(CoroutineKind::Async) => self
519 .async_fn_trait_kind_from_def_id(trait_def_id)
520 .or_else(|| self.fn_trait_kind_from_def_id(trait_def_id)),
521 _ => None,
522 };
523
524 if let Some(found_kind) = found_kind {
525 match (expected_kind, found_kind) {
527 (None, _) => expected_kind = Some(found_kind),
528 (
529 Some(rustc_type_ir::ClosureKind::FnMut),
530 rustc_type_ir::ClosureKind::Fn,
531 ) => expected_kind = Some(rustc_type_ir::ClosureKind::Fn),
532 (
533 Some(rustc_type_ir::ClosureKind::FnOnce),
534 rustc_type_ir::ClosureKind::Fn | rustc_type_ir::ClosureKind::FnMut,
535 ) => expected_kind = Some(found_kind),
536 _ => {}
537 }
538 }
539 }
540 }
541
542 (expected_sig, expected_kind)
543 }
544
545 fn deduce_sig_from_projection(
552 &mut self,
553 closure_expr: ExprId,
554 closure_kind: ClosureKind,
555 projection: PolyProjectionPredicate<'db>,
556 ) -> Option<PolyFnSig<'db>> {
557 let SolverDefId::TypeAliasId(def_id) = projection.item_def_id() else { unreachable!() };
558
559 match closure_kind {
562 ClosureKind::Closure if Some(def_id) == self.lang_items.FnOnceOutput => {
563 self.extract_sig_from_projection(projection)
564 }
565 ClosureKind::CoroutineClosure(CoroutineKind::Async)
566 if Some(def_id) == self.lang_items.AsyncFnOnceOutput =>
567 {
568 self.extract_sig_from_projection(projection)
569 }
570 ClosureKind::CoroutineClosure(CoroutineKind::Async)
574 if Some(def_id) == self.lang_items.FnOnceOutput =>
575 {
576 self.extract_sig_from_projection_and_future_bound(closure_expr, projection)
577 }
578 _ => None,
579 }
580 }
581
582 fn extract_sig_from_projection(
585 &self,
586 projection: PolyProjectionPredicate<'db>,
587 ) -> Option<PolyFnSig<'db>> {
588 let projection = self.resolve_vars_if_possible(projection);
589
590 let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1);
591 debug!(?arg_param_ty);
592
593 let TyKind::Tuple(input_tys) = arg_param_ty.kind() else {
594 return None;
595 };
596
597 let ret_param_ty = projection.skip_binder().term.expect_type();
599 debug!(?ret_param_ty);
600
601 let sig =
602 projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, ret_param_ty));
603
604 Some(sig)
605 }
606
607 fn extract_sig_from_projection_and_future_bound(
630 &mut self,
631 closure_expr: ExprId,
632 projection: PolyProjectionPredicate<'db>,
633 ) -> Option<PolyFnSig<'db>> {
634 let projection = self.resolve_vars_if_possible(projection);
635
636 let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1);
637 debug!(?arg_param_ty);
638
639 let TyKind::Tuple(input_tys) = arg_param_ty.kind() else {
640 return None;
641 };
642
643 let TyKind::Infer(rustc_type_ir::TyVar(return_vid)) =
649 projection.skip_binder().term.expect_type().kind()
650 else {
651 return None;
652 };
653
654 let mut return_ty = None;
656 for bound in self.table.obligations_for_self_ty(return_vid) {
657 if let PredicateKind::Clause(ClauseKind::Projection(ret_projection)) =
658 bound.predicate.kind().skip_binder()
659 && let ret_projection = bound.predicate.kind().rebind(ret_projection)
660 && let Some(ret_projection) = ret_projection.no_bound_vars()
661 && let TermId::TypeAliasId(assoc_type) = ret_projection.def_id().0
662 && Some(assoc_type) == self.lang_items.FutureOutput
663 {
664 return_ty = Some(ret_projection.term.expect_type());
665 break;
666 }
667 }
668
669 let return_ty = return_ty.unwrap_or_else(|| self.table.next_ty_var(closure_expr.into()));
684
685 let sig = projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, return_ty));
686
687 Some(sig)
688 }
689
690 fn sig_of_closure(
691 &mut self,
692 closure_expr: ExprId,
693 decl_inputs: &[PatId],
694 decl_input_tys: &[Option<TypeRefId>],
695 decl_output_ty: Option<TypeRefId>,
696 expected_sig: Option<PolyFnSig<'db>>,
697 closure_kind: ClosureKind,
698 ) -> ClosureSignatures<'db> {
699 if let Some(e) = expected_sig {
700 self.sig_of_closure_with_expectation(
701 closure_expr,
702 decl_inputs,
703 decl_input_tys,
704 decl_output_ty,
705 e,
706 closure_kind,
707 )
708 } else {
709 self.sig_of_closure_no_expectation(
710 closure_expr,
711 decl_input_tys,
712 decl_output_ty,
713 closure_kind,
714 )
715 }
716 }
717
718 fn sig_of_closure_no_expectation(
721 &mut self,
722 closure_expr: ExprId,
723 decl_inputs: &[Option<TypeRefId>],
724 decl_output: Option<TypeRefId>,
725 closure_kind: ClosureKind,
726 ) -> ClosureSignatures<'db> {
727 let bound_sig =
728 self.supplied_sig_of_closure(closure_expr, decl_inputs, decl_output, closure_kind);
729
730 self.closure_sigs(bound_sig)
731 }
732
733 fn sig_of_closure_with_expectation(
781 &mut self,
782 closure_expr: ExprId,
783 decl_inputs: &[PatId],
784 decl_input_tys: &[Option<TypeRefId>],
785 decl_output_ty: Option<TypeRefId>,
786 expected_sig: PolyFnSig<'db>,
787 closure_kind: ClosureKind,
788 ) -> ClosureSignatures<'db> {
789 if expected_sig.c_variadic() {
793 return self.sig_of_closure_no_expectation(
794 closure_expr,
795 decl_input_tys,
796 decl_output_ty,
797 closure_kind,
798 );
799 } else if expected_sig.skip_binder().inputs_and_output.len() != decl_input_tys.len() + 1 {
800 return self.sig_of_closure_with_mismatched_number_of_arguments(
801 decl_input_tys,
802 decl_output_ty,
803 );
804 }
805
806 assert!(!expected_sig.skip_binder().has_vars_bound_above(rustc_type_ir::INNERMOST));
810 let bound_sig = expected_sig.map_bound(|sig| {
811 self.interner().mk_fn_sig(
812 sig.inputs().iter().copied(),
813 sig.output(),
814 sig.c_variadic(),
815 Safety::Safe,
816 ExternAbi::RustCall,
817 )
818 });
819
820 let bound_sig = self.interner().anonymize_bound_vars(bound_sig);
824
825 let closure_sigs = self.closure_sigs(bound_sig);
826
827 match self.merge_supplied_sig_with_expectation(
833 closure_expr,
834 decl_inputs,
835 decl_input_tys,
836 decl_output_ty,
837 closure_sigs,
838 closure_kind,
839 ) {
840 Ok(infer_ok) => self.table.register_infer_ok(infer_ok),
841 Err(_) => self.sig_of_closure_no_expectation(
842 closure_expr,
843 decl_input_tys,
844 decl_output_ty,
845 closure_kind,
846 ),
847 }
848 }
849
850 fn sig_of_closure_with_mismatched_number_of_arguments(
851 &mut self,
852 decl_inputs: &[Option<TypeRefId>],
853 decl_output: Option<TypeRefId>,
854 ) -> ClosureSignatures<'db> {
855 let error_sig = self.error_sig_of_closure(decl_inputs, decl_output);
856
857 self.closure_sigs(error_sig)
858 }
859
860 fn merge_supplied_sig_with_expectation(
864 &mut self,
865 closure_expr: ExprId,
866 decl_inputs: &[PatId],
867 decl_input_tys: &[Option<TypeRefId>],
868 decl_output_ty: Option<TypeRefId>,
869 mut expected_sigs: ClosureSignatures<'db>,
870 closure_kind: ClosureKind,
871 ) -> InferResult<'db, ClosureSignatures<'db>> {
872 let supplied_sig = self.supplied_sig_of_closure(
877 closure_expr,
878 decl_input_tys,
879 decl_output_ty,
880 closure_kind,
881 );
882
883 debug!(?supplied_sig);
884
885 self.table.commit_if_ok(|table| {
900 let mut all_obligations = PredicateObligations::new();
901 let supplied_sig = table.infer_ctxt.instantiate_binder_with_fresh_vars(
902 closure_expr.into(),
903 BoundRegionConversionTime::FnCall,
904 supplied_sig,
905 );
906
907 for ((decl_input, supplied_ty), expected_ty) in iter::zip(
910 iter::zip(decl_inputs, supplied_sig.inputs().iter().copied()),
911 expected_sigs.liberated_sig.inputs().iter().copied(),
912 ) {
913 let cause = ObligationCause::new(*decl_input);
915 let InferOk { value: (), obligations } =
916 table.infer_ctxt.at(&cause, table.param_env).eq(expected_ty, supplied_ty)?;
917 all_obligations.extend(obligations);
918 }
919
920 let supplied_output_ty = supplied_sig.output();
921 let cause = ObligationCause::new(
922 decl_output_ty.map(Span::TypeRefId).unwrap_or(closure_expr.into()),
923 );
924 let InferOk { value: (), obligations } =
925 table
926 .infer_ctxt
927 .at(&cause, table.param_env)
928 .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
929 all_obligations.extend(obligations);
930
931 let inputs =
932 supplied_sig.inputs().iter().copied().map(|ty| table.resolve_vars_if_possible(ty));
933
934 expected_sigs.liberated_sig = table.interner().mk_fn_sig(
935 inputs,
936 supplied_output_ty,
937 expected_sigs.liberated_sig.c_variadic(),
938 Safety::Safe,
939 ExternAbi::RustCall,
940 );
941
942 Ok(InferOk { value: expected_sigs, obligations: all_obligations })
943 })
944 }
945
946 fn supplied_sig_of_closure(
951 &mut self,
952 closure_expr: ExprId,
953 decl_inputs: &[Option<TypeRefId>],
954 decl_output: Option<TypeRefId>,
955 closure_kind: ClosureKind,
956 ) -> PolyFnSig<'db> {
957 let interner = self.interner();
958
959 let supplied_return = match decl_output {
960 Some(output) => self.make_body_ty(output),
961 None => match closure_kind {
962 ClosureKind::Coroutine {
966 kind: CoroutineKind::Async,
967 source: CoroutineSource::Fn,
968 } => {
969 debug!("closure is async fn body");
970 self.deduce_future_output_from_obligations(closure_expr).unwrap_or_else(|| {
971 self.table.next_ty_var(closure_expr.into())
979 })
980 }
981 ClosureKind::Coroutine {
983 kind: CoroutineKind::Gen | CoroutineKind::AsyncGen,
984 ..
985 } => self.types.types.unit,
986
987 ClosureKind::Coroutine { kind: CoroutineKind::Async, .. }
991 | ClosureKind::OldCoroutine(_)
992 | ClosureKind::Closure
993 | ClosureKind::CoroutineClosure(_) => self.table.next_ty_var(closure_expr.into()),
994 },
995 };
996 let supplied_arguments = decl_inputs.iter().map(|&input| match input {
998 Some(input) => self.make_body_ty(input),
999 None => self.table.next_ty_var(closure_expr.into()),
1000 });
1001
1002 Binder::dummy(interner.mk_fn_sig(
1003 supplied_arguments,
1004 supplied_return,
1005 false,
1006 Safety::Safe,
1007 ExternAbi::RustCall,
1008 ))
1009 }
1010
1011 #[instrument(skip(self), level = "debug", ret)]
1018 fn deduce_future_output_from_obligations(&mut self, body_def_id: ExprId) -> Option<Ty<'db>> {
1019 let ret_coercion = self
1020 .return_coercion
1021 .as_ref()
1022 .unwrap_or_else(|| panic!("async fn coroutine outside of a fn"));
1023
1024 let ret_ty = ret_coercion.expected_ty();
1025 let ret_ty = self.table.resolve_vars_with_obligations(ret_ty);
1026
1027 let get_future_output = |predicate: Predicate<'db>| {
1028 let bound_predicate = predicate.kind();
1035 if let PredicateKind::Clause(ClauseKind::Projection(proj_predicate)) =
1036 bound_predicate.skip_binder()
1037 {
1038 self.deduce_future_output_from_projection(bound_predicate.rebind(proj_predicate))
1039 } else {
1040 None
1041 }
1042 };
1043
1044 let output_ty = match ret_ty.kind() {
1045 TyKind::Infer(InferTy::TyVar(ret_vid)) => self
1046 .table
1047 .obligations_for_self_ty(ret_vid)
1048 .into_iter()
1049 .find_map(|obligation| get_future_output(obligation.predicate))?,
1050 TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { .. }, .. }) => {
1051 return Some(self.types.types.error);
1052 }
1053 TyKind::Alias(AliasTy { kind: AliasTyKind::Opaque { def_id }, args, .. }) => def_id
1054 .0
1055 .predicates(self.db)
1056 .iter_instantiated_copied(self.interner(), &args)
1057 .map(Unnormalized::skip_norm_wip)
1058 .find_map(|p| get_future_output(p.as_predicate()))?,
1059 TyKind::Error(_) => return Some(ret_ty),
1060 _ => {
1061 panic!("invalid async fn coroutine return type: {ret_ty:?}")
1062 }
1063 };
1064
1065 Some(output_ty)
1066 }
1067
1068 fn deduce_future_output_from_projection(
1076 &self,
1077 predicate: PolyProjectionPredicate<'db>,
1078 ) -> Option<Ty<'db>> {
1079 debug!("deduce_future_output_from_projection(predicate={:?})", predicate);
1080
1081 let Some(predicate) = predicate.no_bound_vars() else {
1084 debug!("deduce_future_output_from_projection: has late-bound regions");
1085 return None;
1086 };
1087
1088 let trait_def_id = predicate.projection_term.trait_def_id(self.interner()).0;
1090 if Some(trait_def_id) != self.lang_items.Future {
1091 debug!("deduce_future_output_from_projection: not a future");
1092 return None;
1093 }
1094
1095 let output_assoc_item = self.lang_items.FutureOutput;
1098 if output_assoc_item.map(Into::into) != Some(predicate.def_id().0) {
1099 panic!(
1100 "projecting associated item `{:?}` from future, which is not Output `{:?}`",
1101 predicate.projection_term.kind(self.interner()),
1102 output_assoc_item,
1103 );
1104 }
1105
1106 let output_ty = self.resolve_vars_if_possible(predicate.term);
1110 debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
1111 Some(output_ty.expect_type())
1113 }
1114
1115 fn error_sig_of_closure(
1119 &mut self,
1120 decl_inputs: &[Option<TypeRefId>],
1121 decl_output: Option<TypeRefId>,
1122 ) -> PolyFnSig<'db> {
1123 let interner = self.interner();
1124 let err_ty = Ty::new_error(interner, ErrorGuaranteed);
1125
1126 if let Some(output) = decl_output {
1127 self.make_body_ty(output);
1128 }
1129 let supplied_arguments = decl_inputs.iter().map(|&input| match input {
1130 Some(input) => {
1131 self.make_body_ty(input);
1132 err_ty
1133 }
1134 None => err_ty,
1135 });
1136
1137 let result = Binder::dummy(interner.mk_fn_sig(
1138 supplied_arguments,
1139 err_ty,
1140 false,
1141 Safety::Safe,
1142 ExternAbi::RustCall,
1143 ));
1144
1145 debug!("supplied_sig_of_closure: result={:?}", result);
1146
1147 result
1148 }
1149
1150 fn closure_sigs(&self, bound_sig: PolyFnSig<'db>) -> ClosureSignatures<'db> {
1151 let liberated_sig =
1153 self.interner().liberate_late_bound_regions(self.owner.into(), bound_sig);
1154 ClosureSignatures { bound_sig, liberated_sig }
1155 }
1156}