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 indexmap::IndexMap;
13use rustc_abi::ExternAbi;
14use rustc_type_ir::{
15 AliasTyKind, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts,
16 CoroutineClosureArgs, CoroutineClosureArgsParts, InferTy, Interner, TypeSuperVisitable,
17 TypeVisitable, TypeVisitableExt, TypeVisitor,
18 inherent::{BoundExistentialPredicates, GenericArgs as _, IntoKind, Ty as _},
19};
20use tracing::{debug, instrument};
21
22use crate::{
23 Span,
24 db::{InternedClosure, InternedClosureId, InternedCoroutineClosureId, InternedCoroutineId},
25 infer::{BreakableKind, ClosureData, Diverges, coerce::CoerceMany, pat::PatOrigin},
26 next_solver::{
27 AliasTy, Binder, ClauseKind, DbInterner, ErrorGuaranteed, FnSig, GenericArg, PolyFnSig,
28 PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, StoredFnSig, TermId, Ty,
29 TyKind, Unnormalized,
30 abi::Safety,
31 infer::{
32 BoundRegionConversionTime, InferOk, InferResult,
33 traits::{ObligationCause, PredicateObligations},
34 },
35 },
36};
37
38use super::{Expectation, InferenceContext, unify::UseSubtyping};
39
40#[derive(Debug)]
41struct ClosureSignatures<'db> {
42 bound_sig: PolyFnSig<'db>,
44 liberated_sig: FnSig<'db>,
49}
50
51impl<'db> InferenceContext<'db> {
52 fn poll_option_ty(&mut self, item_ty: Ty<'db>) -> Ty<'db> {
53 let interner = self.interner();
54
55 let (Some(option), Some(poll)) = (self.lang_items.Option, self.lang_items.Poll) else {
56 return self.types.types.error;
57 };
58
59 let option_ty = Ty::new_adt(
60 interner,
61 AdtId::EnumId(option),
62 interner.mk_args(&[GenericArg::from(item_ty)]),
63 );
64
65 Ty::new_adt(interner, AdtId::EnumId(poll), interner.mk_args(&[GenericArg::from(option_ty)]))
66 }
67
68 pub(super) fn infer_closure(
69 &mut self,
70 body: ExprId,
71 args: &[PatId],
72 ret_type: Option<TypeRefId>,
73 arg_types: &[Option<TypeRefId>],
74 closure_kind: ClosureKind,
75 closure_expr: ExprId,
76 expected: &Expectation<'db>,
77 ) -> Ty<'db> {
78 assert_eq!(args.len(), arg_types.len());
79
80 let interner = self.interner();
81 let (expected_sig, expected_kind) = match expected.to_option(&self.table) {
85 Some(ty) => {
86 let ty = self.table.try_structurally_resolve_type(closure_expr.into(), ty);
87 self.deduce_closure_signature(closure_expr, ty, closure_kind)
88 }
89 None => (None, None),
90 };
91
92 let ClosureSignatures { bound_sig, mut liberated_sig } = self.sig_of_closure(
93 closure_expr,
94 args,
95 arg_types,
96 ret_type,
97 expected_sig,
98 closure_kind,
99 );
100
101 debug!(?bound_sig, ?liberated_sig);
102
103 let parent_args = self.identity_args();
104
105 let tupled_upvars_ty = self.table.next_ty_var(closure_expr.into());
106
107 let closure_loc =
108 InternedClosure { owner: self.owner, expr: closure_expr, kind: closure_kind };
109 let (closure_ty, resume_yield_tys) = match closure_kind {
114 ClosureKind::Closure => {
115 let sig = bound_sig.map_bound(|sig| {
118 interner.mk_fn_sig(
119 [Ty::new_tup(interner, sig.inputs())],
120 sig.output(),
121 sig.c_variadic(),
122 sig.safety(),
123 sig.abi(),
124 )
125 });
126
127 debug!(?sig, ?expected_kind);
128
129 let closure_kind_ty = match expected_kind {
130 Some(kind) => Ty::from_closure_kind(interner, kind),
131 None => self.table.next_ty_var(closure_expr.into()),
134 };
135
136 let closure_args = ClosureArgs::new(
137 interner,
138 ClosureArgsParts {
139 parent_args: parent_args.as_slice(),
140 closure_kind_ty,
141 closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(interner, sig),
142 tupled_upvars_ty,
143 },
144 );
145
146 let closure_id = InternedClosureId::new(self.db, closure_loc);
147
148 (Ty::new_closure(interner, closure_id.into(), closure_args.args), None)
149 }
150 ClosureKind::OldCoroutine(_) | ClosureKind::Coroutine { .. } => {
151 let yield_ty = match closure_kind {
152 ClosureKind::OldCoroutine(_)
153 | ClosureKind::Coroutine { kind: CoroutineKind::Gen, .. } => {
154 let yield_ty = self.table.next_ty_var(closure_expr.into());
155 self.require_type_is_sized(yield_ty, closure_expr.into());
156 yield_ty
157 }
158 ClosureKind::Coroutine { kind: CoroutineKind::Async, .. } => {
159 self.types.types.unit
160 }
161 ClosureKind::Coroutine { kind: CoroutineKind::AsyncGen, .. } => {
162 let yield_ty = self.table.next_ty_var(closure_expr.into());
163 self.require_type_is_sized(yield_ty, closure_expr.into());
164 self.poll_option_ty(yield_ty)
165 }
166 _ => unreachable!(),
167 };
168
169 let resume_ty =
171 liberated_sig.inputs().first().copied().unwrap_or(self.types.types.unit);
172
173 let kind_ty = match closure_kind {
178 ClosureKind::Coroutine { source: CoroutineSource::Closure, .. } => {
179 self.table.next_ty_var(closure_expr.into())
180 }
181 _ => self.types.types.unit,
182 };
183
184 let coroutine_args = CoroutineArgs::new(
185 interner,
186 CoroutineArgsParts {
187 parent_args: parent_args.as_slice(),
188 kind_ty,
189 resume_ty,
190 yield_ty,
191 return_ty: liberated_sig.output(),
192 tupled_upvars_ty,
193 },
194 );
195
196 let coroutine_id = InternedCoroutineId::new(self.db, closure_loc);
197
198 (
199 Ty::new_coroutine(interner, coroutine_id.into(), coroutine_args.args),
200 Some((resume_ty, yield_ty)),
201 )
202 }
203 ClosureKind::CoroutineClosure(coroutine_kind) => {
204 let (bound_return_ty, bound_yield_ty) = match coroutine_kind {
205 CoroutineKind::Gen => {
206 (self.types.types.unit, self.table.next_ty_var(closure_expr.into()))
207 }
208 CoroutineKind::Async => {
209 (bound_sig.skip_binder().output(), self.types.types.unit)
210 }
211 CoroutineKind::AsyncGen => {
212 let yield_ty = self.table.next_ty_var(closure_expr.into());
213 (self.types.types.unit, self.poll_option_ty(yield_ty))
214 }
215 };
216
217 let resume_ty = self.table.next_ty_var(closure_expr.into());
219
220 let closure_kind_ty = match expected_kind {
221 Some(kind) => Ty::from_closure_kind(interner, kind),
222
223 None => self.table.next_ty_var(closure_expr.into()),
226 };
227
228 let coroutine_captures_by_ref_ty = self.table.next_ty_var(closure_expr.into());
229
230 let closure_args = CoroutineClosureArgs::new(
231 interner,
232 CoroutineClosureArgsParts {
233 parent_args: parent_args.as_slice(),
234 closure_kind_ty,
235 signature_parts_ty: Ty::new_fn_ptr(
236 interner,
237 bound_sig.map_bound(|sig| {
238 interner.mk_fn_sig(
239 [
240 resume_ty,
241 Ty::new_tup_from_iter(
242 interner,
243 sig.inputs().iter().copied(),
244 ),
245 ],
246 Ty::new_tup(interner, &[bound_yield_ty, bound_return_ty]),
247 sig.c_variadic(),
248 sig.safety(),
249 sig.abi(),
250 )
251 }),
252 ),
253 tupled_upvars_ty,
254 coroutine_captures_by_ref_ty,
255 },
256 );
257
258 let coroutine_kind_ty = match expected_kind {
259 Some(kind) => Ty::from_coroutine_closure_kind(interner, kind),
260
261 None => self.table.next_ty_var(closure_expr.into()),
264 };
265
266 let coroutine_upvars_ty = self.table.next_ty_var(closure_expr.into());
267
268 let coroutine_closure_id = InternedCoroutineClosureId::new(self.db, closure_loc);
269
270 let coroutine_output_ty = interner.liberate_late_bound_regions(
277 self.owner.into(),
278 closure_args.coroutine_closure_sig().map_bound(|sig| {
279 sig.to_coroutine(
280 interner,
281 parent_args.as_slice(),
282 coroutine_kind_ty,
283 interner.coroutine_for_closure(coroutine_closure_id.into()),
284 coroutine_upvars_ty,
285 )
286 }),
287 );
288 liberated_sig = interner.mk_fn_sig(
289 liberated_sig.inputs().iter().copied(),
290 coroutine_output_ty,
291 liberated_sig.c_variadic(),
292 liberated_sig.safety(),
293 liberated_sig.abi(),
294 );
295
296 (
297 Ty::new_coroutine_closure(
298 interner,
299 coroutine_closure_id.into(),
300 closure_args.args,
301 ),
302 None,
303 )
304 }
305 };
306
307 self.result.closures_data.insert(
308 closure_expr,
309 ClosureData {
310 liberated_sig: StoredFnSig::new(liberated_sig),
311 fake_reads: Box::default(),
312 min_captures: IndexMap::default(),
313 },
314 );
315
316 for (arg_pat, arg_ty) in args.iter().zip(liberated_sig.inputs()) {
318 self.infer_top_pat(*arg_pat, *arg_ty, PatOrigin::Param);
319 }
320
321 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
323 let prev_ret_ty = mem::replace(&mut self.return_ty, liberated_sig.output());
324 let prev_ret_coercion =
325 self.return_coercion.replace(CoerceMany::new(liberated_sig.output()));
326 let prev_resume_yield_tys = mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
327
328 self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
329 this.infer_return(body);
330 });
331
332 self.diverges = prev_diverges;
333 self.return_ty = prev_ret_ty;
334 self.return_coercion = prev_ret_coercion;
335 self.resume_yield_tys = prev_resume_yield_tys;
336
337 closure_ty
338 }
339
340 fn fn_trait_kind_from_def_id(&self, trait_id: TraitId) -> Option<rustc_type_ir::ClosureKind> {
341 match trait_id {
342 _ if self.lang_items.Fn == Some(trait_id) => Some(rustc_type_ir::ClosureKind::Fn),
343 _ if self.lang_items.FnMut == Some(trait_id) => Some(rustc_type_ir::ClosureKind::FnMut),
344 _ if self.lang_items.FnOnce == Some(trait_id) => {
345 Some(rustc_type_ir::ClosureKind::FnOnce)
346 }
347 _ => None,
348 }
349 }
350
351 fn async_fn_trait_kind_from_def_id(
352 &self,
353 trait_id: TraitId,
354 ) -> Option<rustc_type_ir::ClosureKind> {
355 match trait_id {
356 _ if self.lang_items.AsyncFn == Some(trait_id) => Some(rustc_type_ir::ClosureKind::Fn),
357 _ if self.lang_items.AsyncFnMut == Some(trait_id) => {
358 Some(rustc_type_ir::ClosureKind::FnMut)
359 }
360 _ if self.lang_items.AsyncFnOnce == Some(trait_id) => {
361 Some(rustc_type_ir::ClosureKind::FnOnce)
362 }
363 _ => None,
364 }
365 }
366
367 fn deduce_closure_signature(
370 &mut self,
371 closure_expr: ExprId,
372 expected_ty: Ty<'db>,
373 closure_kind: ClosureKind,
374 ) -> (Option<PolyFnSig<'db>>, Option<rustc_type_ir::ClosureKind>) {
375 match expected_ty.kind() {
376 TyKind::Alias(AliasTy { kind: rustc_type_ir::Opaque { def_id }, args, .. }) => self
377 .deduce_closure_signature_from_predicates(
378 closure_expr,
379 expected_ty,
380 closure_kind,
381 def_id
382 .0
383 .predicates(self.db)
384 .iter_instantiated_copied(self.interner(), args.as_slice())
385 .map(Unnormalized::skip_norm_wip)
386 .map(|clause| clause.as_predicate()),
387 ),
388 TyKind::Dynamic(object_type, ..) => {
389 let sig = object_type.projection_bounds().into_iter().find_map(|pb| {
390 let pb = pb.with_self_ty(self.interner(), Ty::new_unit(self.interner()));
391 self.deduce_sig_from_projection(closure_expr, closure_kind, pb)
392 });
393 let kind = object_type
394 .principal_def_id()
395 .and_then(|did| self.fn_trait_kind_from_def_id(did.0));
396 (sig, kind)
397 }
398 TyKind::Infer(rustc_type_ir::TyVar(vid)) => self
399 .deduce_closure_signature_from_predicates(
400 closure_expr,
401 Ty::new_var(self.interner(), self.table.infer_ctxt.root_var(vid)),
402 closure_kind,
403 self.table
404 .obligations_for_self_ty(vid, UseSubtyping::No)
405 .into_iter()
406 .map(|obl| obl.predicate),
407 ),
408 TyKind::FnPtr(sig_tys, hdr) => match closure_kind {
409 ClosureKind::Closure => {
410 let expected_sig = sig_tys.with(hdr);
411 (Some(expected_sig), Some(rustc_type_ir::ClosureKind::Fn))
412 }
413 ClosureKind::OldCoroutine(_)
414 | ClosureKind::Coroutine { .. }
415 | ClosureKind::CoroutineClosure(_) => (None, None),
416 },
417 _ => (None, None),
418 }
419 }
420
421 fn deduce_closure_signature_from_predicates(
422 &mut self,
423 closure_expr: ExprId,
424 expected_ty: Ty<'db>,
425 closure_kind: ClosureKind,
426 predicates: impl DoubleEndedIterator<Item = Predicate<'db>>,
427 ) -> (Option<PolyFnSig<'db>>, Option<rustc_type_ir::ClosureKind>) {
428 let mut expected_sig = None;
429 let mut expected_kind = None;
430
431 for pred in rustc_type_ir::elaborate::elaborate(
432 self.interner(),
433 predicates.rev(),
437 )
438 .filter_only_self()
440 {
441 debug!(?pred);
442 let bound_predicate = pred.kind();
443
444 if expected_sig.is_none()
447 && let PredicateKind::Clause(ClauseKind::Projection(proj_predicate)) =
448 bound_predicate.skip_binder()
449 {
450 let inferred_sig = self.deduce_sig_from_projection(
451 closure_expr,
452 closure_kind,
453 bound_predicate.rebind(proj_predicate),
454 );
455
456 struct MentionsTy<'db> {
460 expected_ty: Ty<'db>,
461 }
462 impl<'db> TypeVisitor<DbInterner<'db>> for MentionsTy<'db> {
463 type Result = ControlFlow<()>;
464
465 fn visit_ty(&mut self, t: Ty<'db>) -> Self::Result {
466 if t == self.expected_ty {
467 ControlFlow::Break(())
468 } else {
469 t.super_visit_with(self)
470 }
471 }
472 }
473
474 if let Some(inferred_sig) = inferred_sig {
477 let generalized_fnptr_sig = self.table.next_ty_var(closure_expr.into());
495 let inferred_fnptr_sig = Ty::new_fn_ptr(self.interner(), inferred_sig);
496 _ = self
498 .table
499 .infer_ctxt
500 .at(&ObligationCause::new(closure_expr), self.table.param_env)
501 .eq(inferred_fnptr_sig, generalized_fnptr_sig)
502 .map(|infer_ok| self.table.register_infer_ok(infer_ok));
503
504 let resolved_sig = self.resolve_vars_if_possible(generalized_fnptr_sig);
505
506 if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
507 expected_sig = Some(resolved_sig.fn_sig(self.interner()));
508 }
509 } else if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
510 expected_sig = inferred_sig;
511 }
512 }
513
514 let trait_def_id = match bound_predicate.skip_binder() {
519 PredicateKind::Clause(ClauseKind::Projection(data)) => {
520 Some(data.projection_term.trait_def_id(self.interner()).0)
521 }
522 PredicateKind::Clause(ClauseKind::Trait(data)) => Some(data.def_id().0),
523 _ => None,
524 };
525
526 if let Some(trait_def_id) = trait_def_id {
527 let found_kind = match closure_kind {
528 ClosureKind::Closure | ClosureKind::CoroutineClosure(CoroutineKind::Gen) => {
529 self.fn_trait_kind_from_def_id(trait_def_id)
530 }
531 ClosureKind::CoroutineClosure(CoroutineKind::Async) => self
532 .async_fn_trait_kind_from_def_id(trait_def_id)
533 .or_else(|| self.fn_trait_kind_from_def_id(trait_def_id)),
534 _ => None,
535 };
536
537 if let Some(found_kind) = found_kind {
538 match (expected_kind, found_kind) {
540 (None, _) => expected_kind = Some(found_kind),
541 (
542 Some(rustc_type_ir::ClosureKind::FnMut),
543 rustc_type_ir::ClosureKind::Fn,
544 ) => expected_kind = Some(rustc_type_ir::ClosureKind::Fn),
545 (
546 Some(rustc_type_ir::ClosureKind::FnOnce),
547 rustc_type_ir::ClosureKind::Fn | rustc_type_ir::ClosureKind::FnMut,
548 ) => expected_kind = Some(found_kind),
549 _ => {}
550 }
551 }
552 }
553 }
554
555 (expected_sig, expected_kind)
556 }
557
558 fn deduce_sig_from_projection(
565 &mut self,
566 closure_expr: ExprId,
567 closure_kind: ClosureKind,
568 projection: PolyProjectionPredicate<'db>,
569 ) -> Option<PolyFnSig<'db>> {
570 let SolverDefId::TypeAliasId(def_id) = projection.item_def_id() else { unreachable!() };
571
572 match closure_kind {
575 ClosureKind::Closure if Some(def_id) == self.lang_items.FnOnceOutput => {
576 self.extract_sig_from_projection(projection)
577 }
578 ClosureKind::CoroutineClosure(CoroutineKind::Async)
579 if Some(def_id) == self.lang_items.AsyncFnOnceOutput =>
580 {
581 self.extract_sig_from_projection(projection)
582 }
583 ClosureKind::CoroutineClosure(CoroutineKind::Async)
587 if Some(def_id) == self.lang_items.FnOnceOutput =>
588 {
589 self.extract_sig_from_projection_and_future_bound(closure_expr, projection)
590 }
591 _ => None,
592 }
593 }
594
595 fn extract_sig_from_projection(
598 &self,
599 projection: PolyProjectionPredicate<'db>,
600 ) -> Option<PolyFnSig<'db>> {
601 let projection = self.resolve_vars_if_possible(projection);
602
603 let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1);
604 debug!(?arg_param_ty);
605
606 let TyKind::Tuple(input_tys) = arg_param_ty.kind() else {
607 return None;
608 };
609
610 let ret_param_ty = projection.skip_binder().term.expect_type();
612 debug!(?ret_param_ty);
613
614 let sig =
615 projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, ret_param_ty));
616
617 Some(sig)
618 }
619
620 fn extract_sig_from_projection_and_future_bound(
643 &mut self,
644 closure_expr: ExprId,
645 projection: PolyProjectionPredicate<'db>,
646 ) -> Option<PolyFnSig<'db>> {
647 let projection = self.resolve_vars_if_possible(projection);
648
649 let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1);
650 debug!(?arg_param_ty);
651
652 let TyKind::Tuple(input_tys) = arg_param_ty.kind() else {
653 return None;
654 };
655
656 let TyKind::Infer(rustc_type_ir::TyVar(return_vid)) =
662 projection.skip_binder().term.expect_type().kind()
663 else {
664 return None;
665 };
666
667 let mut return_ty = None;
669 for bound in self.table.obligations_for_self_ty(return_vid, UseSubtyping::No) {
670 if let PredicateKind::Clause(ClauseKind::Projection(ret_projection)) =
671 bound.predicate.kind().skip_binder()
672 && let ret_projection = bound.predicate.kind().rebind(ret_projection)
673 && let Some(ret_projection) = ret_projection.no_bound_vars()
674 && let TermId::TypeAliasId(assoc_type) = ret_projection.def_id().0
675 && Some(assoc_type) == self.lang_items.FutureOutput
676 {
677 return_ty = Some(ret_projection.term.expect_type());
678 break;
679 }
680 }
681
682 let return_ty = return_ty.unwrap_or_else(|| self.table.next_ty_var(closure_expr.into()));
697
698 let sig = projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, return_ty));
699
700 Some(sig)
701 }
702
703 fn sig_of_closure(
704 &mut self,
705 closure_expr: ExprId,
706 decl_inputs: &[PatId],
707 decl_input_tys: &[Option<TypeRefId>],
708 decl_output_ty: Option<TypeRefId>,
709 expected_sig: Option<PolyFnSig<'db>>,
710 closure_kind: ClosureKind,
711 ) -> ClosureSignatures<'db> {
712 if let Some(e) = expected_sig {
713 self.sig_of_closure_with_expectation(
714 closure_expr,
715 decl_inputs,
716 decl_input_tys,
717 decl_output_ty,
718 e,
719 closure_kind,
720 )
721 } else {
722 self.sig_of_closure_no_expectation(
723 closure_expr,
724 decl_input_tys,
725 decl_output_ty,
726 closure_kind,
727 )
728 }
729 }
730
731 fn sig_of_closure_no_expectation(
734 &mut self,
735 closure_expr: ExprId,
736 decl_inputs: &[Option<TypeRefId>],
737 decl_output: Option<TypeRefId>,
738 closure_kind: ClosureKind,
739 ) -> ClosureSignatures<'db> {
740 let bound_sig =
741 self.supplied_sig_of_closure(closure_expr, decl_inputs, decl_output, closure_kind);
742
743 self.closure_sigs(bound_sig)
744 }
745
746 fn sig_of_closure_with_expectation(
794 &mut self,
795 closure_expr: ExprId,
796 decl_inputs: &[PatId],
797 decl_input_tys: &[Option<TypeRefId>],
798 decl_output_ty: Option<TypeRefId>,
799 expected_sig: PolyFnSig<'db>,
800 closure_kind: ClosureKind,
801 ) -> ClosureSignatures<'db> {
802 if expected_sig.c_variadic() {
806 return self.sig_of_closure_no_expectation(
807 closure_expr,
808 decl_input_tys,
809 decl_output_ty,
810 closure_kind,
811 );
812 } else if expected_sig.skip_binder().inputs_and_output.len() != decl_input_tys.len() + 1 {
813 return self.sig_of_closure_with_mismatched_number_of_arguments(
814 decl_input_tys,
815 decl_output_ty,
816 );
817 }
818
819 assert!(!expected_sig.skip_binder().has_vars_bound_above(rustc_type_ir::INNERMOST));
823 let bound_sig = expected_sig.map_bound(|sig| {
824 self.interner().mk_fn_sig(
825 sig.inputs().iter().copied(),
826 sig.output(),
827 sig.c_variadic(),
828 Safety::Safe,
829 ExternAbi::RustCall,
830 )
831 });
832
833 let bound_sig = self.interner().anonymize_bound_vars(bound_sig);
837
838 let closure_sigs = self.closure_sigs(bound_sig);
839
840 match self.merge_supplied_sig_with_expectation(
846 closure_expr,
847 decl_inputs,
848 decl_input_tys,
849 decl_output_ty,
850 closure_sigs,
851 closure_kind,
852 ) {
853 Ok(infer_ok) => self.table.register_infer_ok(infer_ok),
854 Err(_) => self.sig_of_closure_no_expectation(
855 closure_expr,
856 decl_input_tys,
857 decl_output_ty,
858 closure_kind,
859 ),
860 }
861 }
862
863 fn sig_of_closure_with_mismatched_number_of_arguments(
864 &mut self,
865 decl_inputs: &[Option<TypeRefId>],
866 decl_output: Option<TypeRefId>,
867 ) -> ClosureSignatures<'db> {
868 let error_sig = self.error_sig_of_closure(decl_inputs, decl_output);
869
870 self.closure_sigs(error_sig)
871 }
872
873 fn merge_supplied_sig_with_expectation(
877 &mut self,
878 closure_expr: ExprId,
879 decl_inputs: &[PatId],
880 decl_input_tys: &[Option<TypeRefId>],
881 decl_output_ty: Option<TypeRefId>,
882 mut expected_sigs: ClosureSignatures<'db>,
883 closure_kind: ClosureKind,
884 ) -> InferResult<'db, ClosureSignatures<'db>> {
885 let supplied_sig = self.supplied_sig_of_closure(
890 closure_expr,
891 decl_input_tys,
892 decl_output_ty,
893 closure_kind,
894 );
895
896 debug!(?supplied_sig);
897
898 self.table.commit_if_ok(|table| {
913 let mut all_obligations = PredicateObligations::new();
914 let supplied_sig = table.infer_ctxt.instantiate_binder_with_fresh_vars(
915 closure_expr.into(),
916 BoundRegionConversionTime::FnCall,
917 supplied_sig,
918 );
919
920 for ((decl_input, supplied_ty), expected_ty) in iter::zip(
923 iter::zip(decl_inputs, supplied_sig.inputs().iter().copied()),
924 expected_sigs.liberated_sig.inputs().iter().copied(),
925 ) {
926 let cause = ObligationCause::new(*decl_input);
928 let InferOk { value: (), obligations } =
929 table.infer_ctxt.at(&cause, table.param_env).eq(expected_ty, supplied_ty)?;
930 all_obligations.extend(obligations);
931 }
932
933 let supplied_output_ty = supplied_sig.output();
934 let cause = ObligationCause::new(
935 decl_output_ty.map(Span::TypeRefId).unwrap_or(closure_expr.into()),
936 );
937 let InferOk { value: (), obligations } =
938 table
939 .infer_ctxt
940 .at(&cause, table.param_env)
941 .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
942 all_obligations.extend(obligations);
943
944 let inputs =
945 supplied_sig.inputs().iter().copied().map(|ty| table.resolve_vars_if_possible(ty));
946
947 expected_sigs.liberated_sig = table.interner().mk_fn_sig(
948 inputs,
949 supplied_output_ty,
950 expected_sigs.liberated_sig.c_variadic(),
951 Safety::Safe,
952 ExternAbi::RustCall,
953 );
954
955 Ok(InferOk { value: expected_sigs, obligations: all_obligations })
956 })
957 }
958
959 fn supplied_sig_of_closure(
964 &mut self,
965 closure_expr: ExprId,
966 decl_inputs: &[Option<TypeRefId>],
967 decl_output: Option<TypeRefId>,
968 closure_kind: ClosureKind,
969 ) -> PolyFnSig<'db> {
970 let interner = self.interner();
971
972 let supplied_return = match decl_output {
973 Some(output) => self.make_ty(output),
974 None => match closure_kind {
975 ClosureKind::Coroutine {
979 kind: CoroutineKind::Async,
980 source: CoroutineSource::Fn,
981 } => {
982 debug!("closure is async fn body");
983 self.deduce_future_output_from_obligations(closure_expr).unwrap_or_else(|| {
984 self.table.next_ty_var(closure_expr.into())
992 })
993 }
994 ClosureKind::Coroutine {
996 kind: CoroutineKind::Gen | CoroutineKind::AsyncGen,
997 ..
998 } => self.types.types.unit,
999
1000 ClosureKind::Coroutine { kind: CoroutineKind::Async, .. }
1004 | ClosureKind::OldCoroutine(_)
1005 | ClosureKind::Closure
1006 | ClosureKind::CoroutineClosure(_) => self.table.next_ty_var(closure_expr.into()),
1007 },
1008 };
1009 let supplied_arguments = decl_inputs.iter().map(|&input| match input {
1011 Some(input) => self.make_ty(input),
1012 None => self.table.next_ty_var(closure_expr.into()),
1013 });
1014
1015 Binder::dummy(interner.mk_fn_sig(
1016 supplied_arguments,
1017 supplied_return,
1018 false,
1019 Safety::Safe,
1020 ExternAbi::RustCall,
1021 ))
1022 }
1023
1024 #[instrument(skip(self), level = "debug", ret)]
1031 fn deduce_future_output_from_obligations(&mut self, body_def_id: ExprId) -> Option<Ty<'db>> {
1032 let ret_coercion = self
1033 .return_coercion
1034 .as_ref()
1035 .unwrap_or_else(|| panic!("async fn coroutine outside of a fn"));
1036
1037 let ret_ty = ret_coercion.expected_ty();
1038 let ret_ty = self.table.resolve_vars_with_obligations(ret_ty);
1039
1040 let get_future_output = |predicate: Predicate<'db>| {
1041 let bound_predicate = predicate.kind();
1048 if let PredicateKind::Clause(ClauseKind::Projection(proj_predicate)) =
1049 bound_predicate.skip_binder()
1050 {
1051 self.deduce_future_output_from_projection(bound_predicate.rebind(proj_predicate))
1052 } else {
1053 None
1054 }
1055 };
1056
1057 let output_ty = match ret_ty.kind() {
1058 TyKind::Infer(InferTy::TyVar(ret_vid)) => self
1059 .table
1060 .obligations_for_self_ty(ret_vid, UseSubtyping::No)
1061 .into_iter()
1062 .find_map(|obligation| get_future_output(obligation.predicate))?,
1063 TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { .. }, .. }) => {
1064 return Some(self.types.types.error);
1065 }
1066 TyKind::Alias(AliasTy { kind: AliasTyKind::Opaque { def_id }, args, .. }) => def_id
1067 .0
1068 .predicates(self.db)
1069 .iter_instantiated_copied(self.interner(), &args)
1070 .map(Unnormalized::skip_norm_wip)
1071 .find_map(|p| get_future_output(p.as_predicate()))?,
1072 TyKind::Error(_) => return Some(ret_ty),
1073 _ => {
1074 panic!("invalid async fn coroutine return type: {ret_ty:?}")
1075 }
1076 };
1077
1078 Some(output_ty)
1079 }
1080
1081 fn deduce_future_output_from_projection(
1089 &self,
1090 predicate: PolyProjectionPredicate<'db>,
1091 ) -> Option<Ty<'db>> {
1092 debug!("deduce_future_output_from_projection(predicate={:?})", predicate);
1093
1094 let Some(predicate) = predicate.no_bound_vars() else {
1097 debug!("deduce_future_output_from_projection: has late-bound regions");
1098 return None;
1099 };
1100
1101 let trait_def_id = predicate.projection_term.trait_def_id(self.interner()).0;
1103 if Some(trait_def_id) != self.lang_items.Future {
1104 debug!("deduce_future_output_from_projection: not a future");
1105 return None;
1106 }
1107
1108 let output_assoc_item = self.lang_items.FutureOutput;
1111 if output_assoc_item.map(Into::into) != Some(predicate.def_id().0) {
1112 panic!(
1113 "projecting associated item `{:?}` from future, which is not Output `{:?}`",
1114 predicate.projection_term.kind(self.interner()),
1115 output_assoc_item,
1116 );
1117 }
1118
1119 let output_ty = self.resolve_vars_if_possible(predicate.term);
1123 debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
1124 Some(output_ty.expect_type())
1126 }
1127
1128 fn error_sig_of_closure(
1132 &mut self,
1133 decl_inputs: &[Option<TypeRefId>],
1134 decl_output: Option<TypeRefId>,
1135 ) -> PolyFnSig<'db> {
1136 let interner = self.interner();
1137 let err_ty = Ty::new_error(interner, ErrorGuaranteed);
1138
1139 if let Some(output) = decl_output {
1140 self.make_ty(output);
1141 }
1142 let supplied_arguments = decl_inputs.iter().map(|&input| match input {
1143 Some(input) => {
1144 self.make_ty(input);
1145 err_ty
1146 }
1147 None => err_ty,
1148 });
1149
1150 let result = Binder::dummy(interner.mk_fn_sig(
1151 supplied_arguments,
1152 err_ty,
1153 false,
1154 Safety::Safe,
1155 ExternAbi::RustCall,
1156 ));
1157
1158 debug!("supplied_sig_of_closure: result={:?}", result);
1159
1160 result
1161 }
1162
1163 fn closure_sigs(&self, bound_sig: PolyFnSig<'db>) -> ClosureSignatures<'db> {
1164 let liberated_sig =
1166 self.interner().liberate_late_bound_regions(self.owner.into(), bound_sig);
1167 ClosureSignatures { bound_sig, liberated_sig }
1168 }
1169}