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};
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 = closure_args
277 .coroutine_closure_sig()
278 .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 .skip_binder();
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.obligations_for_self_ty(vid).into_iter().map(|obl| obl.predicate),
404 ),
405 TyKind::FnPtr(sig_tys, hdr) => match closure_kind {
406 ClosureKind::Closure => {
407 let expected_sig = sig_tys.with(hdr);
408 (Some(expected_sig), Some(rustc_type_ir::ClosureKind::Fn))
409 }
410 ClosureKind::OldCoroutine(_)
411 | ClosureKind::Coroutine { .. }
412 | ClosureKind::CoroutineClosure(_) => (None, None),
413 },
414 _ => (None, None),
415 }
416 }
417
418 fn deduce_closure_signature_from_predicates(
419 &mut self,
420 closure_expr: ExprId,
421 expected_ty: Ty<'db>,
422 closure_kind: ClosureKind,
423 predicates: impl DoubleEndedIterator<Item = Predicate<'db>>,
424 ) -> (Option<PolyFnSig<'db>>, Option<rustc_type_ir::ClosureKind>) {
425 let mut expected_sig = None;
426 let mut expected_kind = None;
427
428 for pred in rustc_type_ir::elaborate::elaborate(
429 self.interner(),
430 predicates.rev(),
434 )
435 .filter_only_self()
437 {
438 debug!(?pred);
439 let bound_predicate = pred.kind();
440
441 if expected_sig.is_none()
444 && let PredicateKind::Clause(ClauseKind::Projection(proj_predicate)) =
445 bound_predicate.skip_binder()
446 {
447 let inferred_sig = self.deduce_sig_from_projection(
448 closure_expr,
449 closure_kind,
450 bound_predicate.rebind(proj_predicate),
451 );
452
453 struct MentionsTy<'db> {
457 expected_ty: Ty<'db>,
458 }
459 impl<'db> TypeVisitor<DbInterner<'db>> for MentionsTy<'db> {
460 type Result = ControlFlow<()>;
461
462 fn visit_ty(&mut self, t: Ty<'db>) -> Self::Result {
463 if t == self.expected_ty {
464 ControlFlow::Break(())
465 } else {
466 t.super_visit_with(self)
467 }
468 }
469 }
470
471 if let Some(inferred_sig) = inferred_sig {
474 let generalized_fnptr_sig = self.table.next_ty_var(closure_expr.into());
492 let inferred_fnptr_sig = Ty::new_fn_ptr(self.interner(), inferred_sig);
493 _ = self
495 .table
496 .infer_ctxt
497 .at(&ObligationCause::new(closure_expr), self.table.param_env)
498 .eq(inferred_fnptr_sig, generalized_fnptr_sig)
499 .map(|infer_ok| self.table.register_infer_ok(infer_ok));
500
501 let resolved_sig = self.resolve_vars_if_possible(generalized_fnptr_sig);
502
503 if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
504 expected_sig = Some(resolved_sig.fn_sig(self.interner()));
505 }
506 } else if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
507 expected_sig = inferred_sig;
508 }
509 }
510
511 let trait_def_id = match bound_predicate.skip_binder() {
516 PredicateKind::Clause(ClauseKind::Projection(data)) => {
517 Some(data.projection_term.trait_def_id(self.interner()).0)
518 }
519 PredicateKind::Clause(ClauseKind::Trait(data)) => Some(data.def_id().0),
520 _ => None,
521 };
522
523 if let Some(trait_def_id) = trait_def_id {
524 let found_kind = match closure_kind {
525 ClosureKind::Closure | ClosureKind::CoroutineClosure(CoroutineKind::Gen) => {
526 self.fn_trait_kind_from_def_id(trait_def_id)
527 }
528 ClosureKind::CoroutineClosure(CoroutineKind::Async) => self
529 .async_fn_trait_kind_from_def_id(trait_def_id)
530 .or_else(|| self.fn_trait_kind_from_def_id(trait_def_id)),
531 _ => None,
532 };
533
534 if let Some(found_kind) = found_kind {
535 match (expected_kind, found_kind) {
537 (None, _) => expected_kind = Some(found_kind),
538 (
539 Some(rustc_type_ir::ClosureKind::FnMut),
540 rustc_type_ir::ClosureKind::Fn,
541 ) => expected_kind = Some(rustc_type_ir::ClosureKind::Fn),
542 (
543 Some(rustc_type_ir::ClosureKind::FnOnce),
544 rustc_type_ir::ClosureKind::Fn | rustc_type_ir::ClosureKind::FnMut,
545 ) => expected_kind = Some(found_kind),
546 _ => {}
547 }
548 }
549 }
550 }
551
552 (expected_sig, expected_kind)
553 }
554
555 fn deduce_sig_from_projection(
562 &mut self,
563 closure_expr: ExprId,
564 closure_kind: ClosureKind,
565 projection: PolyProjectionPredicate<'db>,
566 ) -> Option<PolyFnSig<'db>> {
567 let SolverDefId::TypeAliasId(def_id) = projection.item_def_id() else { unreachable!() };
568
569 match closure_kind {
572 ClosureKind::Closure if Some(def_id) == self.lang_items.FnOnceOutput => {
573 self.extract_sig_from_projection(projection)
574 }
575 ClosureKind::CoroutineClosure(CoroutineKind::Async)
576 if Some(def_id) == self.lang_items.AsyncFnOnceOutput =>
577 {
578 self.extract_sig_from_projection(projection)
579 }
580 ClosureKind::CoroutineClosure(CoroutineKind::Async)
584 if Some(def_id) == self.lang_items.FnOnceOutput =>
585 {
586 self.extract_sig_from_projection_and_future_bound(closure_expr, projection)
587 }
588 _ => None,
589 }
590 }
591
592 fn extract_sig_from_projection(
595 &self,
596 projection: PolyProjectionPredicate<'db>,
597 ) -> Option<PolyFnSig<'db>> {
598 let projection = self.resolve_vars_if_possible(projection);
599
600 let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1);
601 debug!(?arg_param_ty);
602
603 let TyKind::Tuple(input_tys) = arg_param_ty.kind() else {
604 return None;
605 };
606
607 let ret_param_ty = projection.skip_binder().term.expect_type();
609 debug!(?ret_param_ty);
610
611 let sig =
612 projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, ret_param_ty));
613
614 Some(sig)
615 }
616
617 fn extract_sig_from_projection_and_future_bound(
640 &mut self,
641 closure_expr: ExprId,
642 projection: PolyProjectionPredicate<'db>,
643 ) -> Option<PolyFnSig<'db>> {
644 let projection = self.resolve_vars_if_possible(projection);
645
646 let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1);
647 debug!(?arg_param_ty);
648
649 let TyKind::Tuple(input_tys) = arg_param_ty.kind() else {
650 return None;
651 };
652
653 let TyKind::Infer(rustc_type_ir::TyVar(return_vid)) =
659 projection.skip_binder().term.expect_type().kind()
660 else {
661 return None;
662 };
663
664 let mut return_ty = None;
666 for bound in self.table.obligations_for_self_ty(return_vid) {
667 if let PredicateKind::Clause(ClauseKind::Projection(ret_projection)) =
668 bound.predicate.kind().skip_binder()
669 && let ret_projection = bound.predicate.kind().rebind(ret_projection)
670 && let Some(ret_projection) = ret_projection.no_bound_vars()
671 && let TermId::TypeAliasId(assoc_type) = ret_projection.def_id().0
672 && Some(assoc_type) == self.lang_items.FutureOutput
673 {
674 return_ty = Some(ret_projection.term.expect_type());
675 break;
676 }
677 }
678
679 let return_ty = return_ty.unwrap_or_else(|| self.table.next_ty_var(closure_expr.into()));
694
695 let sig = projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, return_ty));
696
697 Some(sig)
698 }
699
700 fn sig_of_closure(
701 &mut self,
702 closure_expr: ExprId,
703 decl_inputs: &[PatId],
704 decl_input_tys: &[Option<TypeRefId>],
705 decl_output_ty: Option<TypeRefId>,
706 expected_sig: Option<PolyFnSig<'db>>,
707 closure_kind: ClosureKind,
708 ) -> ClosureSignatures<'db> {
709 if let Some(e) = expected_sig {
710 self.sig_of_closure_with_expectation(
711 closure_expr,
712 decl_inputs,
713 decl_input_tys,
714 decl_output_ty,
715 e,
716 closure_kind,
717 )
718 } else {
719 self.sig_of_closure_no_expectation(
720 closure_expr,
721 decl_input_tys,
722 decl_output_ty,
723 closure_kind,
724 )
725 }
726 }
727
728 fn sig_of_closure_no_expectation(
731 &mut self,
732 closure_expr: ExprId,
733 decl_inputs: &[Option<TypeRefId>],
734 decl_output: Option<TypeRefId>,
735 closure_kind: ClosureKind,
736 ) -> ClosureSignatures<'db> {
737 let bound_sig =
738 self.supplied_sig_of_closure(closure_expr, decl_inputs, decl_output, closure_kind);
739
740 self.closure_sigs(bound_sig)
741 }
742
743 fn sig_of_closure_with_expectation(
791 &mut self,
792 closure_expr: ExprId,
793 decl_inputs: &[PatId],
794 decl_input_tys: &[Option<TypeRefId>],
795 decl_output_ty: Option<TypeRefId>,
796 expected_sig: PolyFnSig<'db>,
797 closure_kind: ClosureKind,
798 ) -> ClosureSignatures<'db> {
799 if expected_sig.c_variadic() {
803 return self.sig_of_closure_no_expectation(
804 closure_expr,
805 decl_input_tys,
806 decl_output_ty,
807 closure_kind,
808 );
809 } else if expected_sig.skip_binder().inputs_and_output.len() != decl_input_tys.len() + 1 {
810 return self.sig_of_closure_with_mismatched_number_of_arguments(
811 decl_input_tys,
812 decl_output_ty,
813 );
814 }
815
816 assert!(!expected_sig.skip_binder().has_vars_bound_above(rustc_type_ir::INNERMOST));
820 let bound_sig = expected_sig.map_bound(|sig| {
821 self.interner().mk_fn_sig(
822 sig.inputs().iter().copied(),
823 sig.output(),
824 sig.c_variadic(),
825 Safety::Safe,
826 ExternAbi::RustCall,
827 )
828 });
829
830 let bound_sig = self.interner().anonymize_bound_vars(bound_sig);
834
835 let closure_sigs = self.closure_sigs(bound_sig);
836
837 match self.merge_supplied_sig_with_expectation(
843 closure_expr,
844 decl_inputs,
845 decl_input_tys,
846 decl_output_ty,
847 closure_sigs,
848 closure_kind,
849 ) {
850 Ok(infer_ok) => self.table.register_infer_ok(infer_ok),
851 Err(_) => self.sig_of_closure_no_expectation(
852 closure_expr,
853 decl_input_tys,
854 decl_output_ty,
855 closure_kind,
856 ),
857 }
858 }
859
860 fn sig_of_closure_with_mismatched_number_of_arguments(
861 &mut self,
862 decl_inputs: &[Option<TypeRefId>],
863 decl_output: Option<TypeRefId>,
864 ) -> ClosureSignatures<'db> {
865 let error_sig = self.error_sig_of_closure(decl_inputs, decl_output);
866
867 self.closure_sigs(error_sig)
868 }
869
870 fn merge_supplied_sig_with_expectation(
874 &mut self,
875 closure_expr: ExprId,
876 decl_inputs: &[PatId],
877 decl_input_tys: &[Option<TypeRefId>],
878 decl_output_ty: Option<TypeRefId>,
879 mut expected_sigs: ClosureSignatures<'db>,
880 closure_kind: ClosureKind,
881 ) -> InferResult<'db, ClosureSignatures<'db>> {
882 let supplied_sig = self.supplied_sig_of_closure(
887 closure_expr,
888 decl_input_tys,
889 decl_output_ty,
890 closure_kind,
891 );
892
893 debug!(?supplied_sig);
894
895 self.table.commit_if_ok(|table| {
910 let mut all_obligations = PredicateObligations::new();
911 let supplied_sig = table.infer_ctxt.instantiate_binder_with_fresh_vars(
912 closure_expr.into(),
913 BoundRegionConversionTime::FnCall,
914 supplied_sig,
915 );
916
917 for ((decl_input, supplied_ty), expected_ty) in iter::zip(
920 iter::zip(decl_inputs, supplied_sig.inputs().iter().copied()),
921 expected_sigs.liberated_sig.inputs().iter().copied(),
922 ) {
923 let cause = ObligationCause::new(*decl_input);
925 let InferOk { value: (), obligations } =
926 table.infer_ctxt.at(&cause, table.param_env).eq(expected_ty, supplied_ty)?;
927 all_obligations.extend(obligations);
928 }
929
930 let supplied_output_ty = supplied_sig.output();
931 let cause = ObligationCause::new(
932 decl_output_ty.map(Span::TypeRefId).unwrap_or(closure_expr.into()),
933 );
934 let InferOk { value: (), obligations } =
935 table
936 .infer_ctxt
937 .at(&cause, table.param_env)
938 .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
939 all_obligations.extend(obligations);
940
941 let inputs =
942 supplied_sig.inputs().iter().copied().map(|ty| table.resolve_vars_if_possible(ty));
943
944 expected_sigs.liberated_sig = table.interner().mk_fn_sig(
945 inputs,
946 supplied_output_ty,
947 expected_sigs.liberated_sig.c_variadic(),
948 Safety::Safe,
949 ExternAbi::RustCall,
950 );
951
952 Ok(InferOk { value: expected_sigs, obligations: all_obligations })
953 })
954 }
955
956 fn supplied_sig_of_closure(
961 &mut self,
962 closure_expr: ExprId,
963 decl_inputs: &[Option<TypeRefId>],
964 decl_output: Option<TypeRefId>,
965 closure_kind: ClosureKind,
966 ) -> PolyFnSig<'db> {
967 let interner = self.interner();
968
969 let supplied_return = match decl_output {
970 Some(output) => self.make_body_ty(output),
971 None => match closure_kind {
972 ClosureKind::Coroutine {
976 kind: CoroutineKind::Async,
977 source: CoroutineSource::Fn,
978 } => {
979 debug!("closure is async fn body");
980 self.deduce_future_output_from_obligations(closure_expr).unwrap_or_else(|| {
981 self.table.next_ty_var(closure_expr.into())
989 })
990 }
991 ClosureKind::Coroutine {
993 kind: CoroutineKind::Gen | CoroutineKind::AsyncGen,
994 ..
995 } => self.types.types.unit,
996
997 ClosureKind::Coroutine { kind: CoroutineKind::Async, .. }
1001 | ClosureKind::OldCoroutine(_)
1002 | ClosureKind::Closure
1003 | ClosureKind::CoroutineClosure(_) => self.table.next_ty_var(closure_expr.into()),
1004 },
1005 };
1006 let supplied_arguments = decl_inputs.iter().map(|&input| match input {
1008 Some(input) => self.make_body_ty(input),
1009 None => self.table.next_ty_var(closure_expr.into()),
1010 });
1011
1012 Binder::dummy(interner.mk_fn_sig(
1013 supplied_arguments,
1014 supplied_return,
1015 false,
1016 Safety::Safe,
1017 ExternAbi::RustCall,
1018 ))
1019 }
1020
1021 #[instrument(skip(self), level = "debug", ret)]
1028 fn deduce_future_output_from_obligations(&mut self, body_def_id: ExprId) -> Option<Ty<'db>> {
1029 let ret_coercion = self
1030 .return_coercion
1031 .as_ref()
1032 .unwrap_or_else(|| panic!("async fn coroutine outside of a fn"));
1033
1034 let ret_ty = ret_coercion.expected_ty();
1035 let ret_ty = self.table.resolve_vars_with_obligations(ret_ty);
1036
1037 let get_future_output = |predicate: Predicate<'db>| {
1038 let bound_predicate = predicate.kind();
1045 if let PredicateKind::Clause(ClauseKind::Projection(proj_predicate)) =
1046 bound_predicate.skip_binder()
1047 {
1048 self.deduce_future_output_from_projection(bound_predicate.rebind(proj_predicate))
1049 } else {
1050 None
1051 }
1052 };
1053
1054 let output_ty = match ret_ty.kind() {
1055 TyKind::Infer(InferTy::TyVar(ret_vid)) => self
1056 .table
1057 .obligations_for_self_ty(ret_vid)
1058 .into_iter()
1059 .find_map(|obligation| get_future_output(obligation.predicate))?,
1060 TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { .. }, .. }) => {
1061 return Some(self.types.types.error);
1062 }
1063 TyKind::Alias(AliasTy { kind: AliasTyKind::Opaque { def_id }, args, .. }) => def_id
1064 .0
1065 .predicates(self.db)
1066 .iter_instantiated_copied(self.interner(), &args)
1067 .map(Unnormalized::skip_norm_wip)
1068 .find_map(|p| get_future_output(p.as_predicate()))?,
1069 TyKind::Error(_) => return Some(ret_ty),
1070 _ => {
1071 panic!("invalid async fn coroutine return type: {ret_ty:?}")
1072 }
1073 };
1074
1075 Some(output_ty)
1076 }
1077
1078 fn deduce_future_output_from_projection(
1086 &self,
1087 predicate: PolyProjectionPredicate<'db>,
1088 ) -> Option<Ty<'db>> {
1089 debug!("deduce_future_output_from_projection(predicate={:?})", predicate);
1090
1091 let Some(predicate) = predicate.no_bound_vars() else {
1094 debug!("deduce_future_output_from_projection: has late-bound regions");
1095 return None;
1096 };
1097
1098 let trait_def_id = predicate.projection_term.trait_def_id(self.interner()).0;
1100 if Some(trait_def_id) != self.lang_items.Future {
1101 debug!("deduce_future_output_from_projection: not a future");
1102 return None;
1103 }
1104
1105 let output_assoc_item = self.lang_items.FutureOutput;
1108 if output_assoc_item.map(Into::into) != Some(predicate.def_id().0) {
1109 panic!(
1110 "projecting associated item `{:?}` from future, which is not Output `{:?}`",
1111 predicate.projection_term.kind(self.interner()),
1112 output_assoc_item,
1113 );
1114 }
1115
1116 let output_ty = self.resolve_vars_if_possible(predicate.term);
1120 debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
1121 Some(output_ty.expect_type())
1123 }
1124
1125 fn error_sig_of_closure(
1129 &mut self,
1130 decl_inputs: &[Option<TypeRefId>],
1131 decl_output: Option<TypeRefId>,
1132 ) -> PolyFnSig<'db> {
1133 let interner = self.interner();
1134 let err_ty = Ty::new_error(interner, ErrorGuaranteed);
1135
1136 if let Some(output) = decl_output {
1137 self.make_body_ty(output);
1138 }
1139 let supplied_arguments = decl_inputs.iter().map(|&input| match input {
1140 Some(input) => {
1141 self.make_body_ty(input);
1142 err_ty
1143 }
1144 None => err_ty,
1145 });
1146
1147 let result = Binder::dummy(interner.mk_fn_sig(
1148 supplied_arguments,
1149 err_ty,
1150 false,
1151 Safety::Safe,
1152 ExternAbi::RustCall,
1153 ));
1154
1155 debug!("supplied_sig_of_closure: result={:?}", result);
1156
1157 result
1158 }
1159
1160 fn closure_sigs(&self, bound_sig: PolyFnSig<'db>) -> ClosureSignatures<'db> {
1161 let liberated_sig =
1163 self.interner().liberate_late_bound_regions(self.owner.into(), bound_sig);
1164 ClosureSignatures { bound_sig, liberated_sig }
1165 }
1166}