rustc_type_ir/ty_kind/
closure.rs

1use std::ops::ControlFlow;
2
3use derive_where::derive_where;
4use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
5
6use crate::data_structures::DelayedMap;
7use crate::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region};
8use crate::inherent::*;
9use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
10use crate::{self as ty, Interner};
11
12/// A closure can be modeled as a struct that looks like:
13/// ```ignore (illustrative)
14/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
15/// ```
16/// where:
17///
18/// - 'l0...'li and T0...Tj are the generic parameters
19///   in scope on the function that defined the closure,
20/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This
21///   is rather hackily encoded via a scalar type. See
22///   `Ty::to_opt_closure_kind` for details.
23/// - CS represents the *closure signature*, representing as a `fn()`
24///   type. For example, `fn(u32, u32) -> u32` would mean that the closure
25///   implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait
26///   specified above.
27/// - U is a type parameter representing the types of its upvars, tupled up
28///   (borrowed, if appropriate; that is, if a U field represents a by-ref upvar,
29///    and the up-var has the type `Foo`, then that field of U will be `&Foo`).
30///
31/// So, for example, given this function:
32/// ```ignore (illustrative)
33/// fn foo<'a, T>(data: &'a mut T) {
34///      do(|| data.count += 1)
35/// }
36/// ```
37/// the type of the closure would be something like:
38/// ```ignore (illustrative)
39/// struct Closure<'a, T, U>(...U);
40/// ```
41/// Note that the type of the upvar is not specified in the struct.
42/// You may wonder how the impl would then be able to use the upvar,
43/// if it doesn't know it's type? The answer is that the impl is
44/// (conceptually) not fully generic over Closure but rather tied to
45/// instances with the expected upvar types:
46/// ```ignore (illustrative)
47/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
48///     ...
49/// }
50/// ```
51/// You can see that the *impl* fully specified the type of the upvar
52/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
53/// (Here, I am assuming that `data` is mut-borrowed.)
54///
55/// Now, the last question you may ask is: Why include the upvar types
56/// in an extra type parameter? The reason for this design is that the
57/// upvar types can reference lifetimes that are internal to the
58/// creating function. In my example above, for example, the lifetime
59/// `'b` represents the scope of the closure itself; this is some
60/// subset of `foo`, probably just the scope of the call to the to
61/// `do()`. If we just had the lifetime/type parameters from the
62/// enclosing function, we couldn't name this lifetime `'b`. Note that
63/// there can also be lifetimes in the types of the upvars themselves,
64/// if one of them happens to be a reference to something that the
65/// creating fn owns.
66///
67/// OK, you say, so why not create a more minimal set of parameters
68/// that just includes the extra lifetime parameters? The answer is
69/// primarily that it would be hard --- we don't know at the time when
70/// we create the closure type what the full types of the upvars are,
71/// nor do we know which are borrowed and which are not. In this
72/// design, we can just supply a fresh type parameter and figure that
73/// out later.
74///
75/// All right, you say, but why include the type parameters from the
76/// original function then? The answer is that codegen may need them
77/// when monomorphizing, and they may not appear in the upvars. A
78/// closure could capture no variables but still make use of some
79/// in-scope type parameter with a bound (e.g., if our example above
80/// had an extra `U: Default`, and the closure called `U::default()`).
81///
82/// There is another reason. This design (implicitly) prohibits
83/// closures from capturing themselves (except via a trait
84/// object). This simplifies closure inference considerably, since it
85/// means that when we infer the kind of a closure or its upvars, we
86/// don't have to handle cycles where the decisions we make for
87/// closure C wind up influencing the decisions we ought to make for
88/// closure C (which would then require fixed point iteration to
89/// handle). Plus it fixes an ICE. :P
90///
91/// ## Coroutines
92///
93/// Coroutines are handled similarly in `CoroutineArgs`. The set of
94/// type parameters is similar, but `CK` and `CS` are replaced by the
95/// following type parameters:
96///
97/// * `GS`: The coroutine's "resume type", which is the type of the
98///   argument passed to `resume`, and the type of `yield` expressions
99///   inside the coroutine.
100/// * `GY`: The "yield type", which is the type of values passed to
101///   `yield` inside the coroutine.
102/// * `GR`: The "return type", which is the type of value returned upon
103///   completion of the coroutine.
104/// * `GW`: The "coroutine witness".
105#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
106#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
107pub struct ClosureArgs<I: Interner> {
108    /// Lifetime and type parameters from the enclosing function,
109    /// concatenated with a tuple containing the types of the upvars.
110    ///
111    /// These are separated out because codegen wants to pass them around
112    /// when monomorphizing.
113    pub args: I::GenericArgs,
114}
115
116/// Struct returned by `split()`.
117pub struct ClosureArgsParts<I: Interner> {
118    /// This is the args of the typeck root.
119    pub parent_args: I::GenericArgsSlice,
120    /// Represents the maximum calling capability of the closure.
121    pub closure_kind_ty: I::Ty,
122    /// Captures the closure's signature. This closure signature is "tupled", and
123    /// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`.
124    pub closure_sig_as_fn_ptr_ty: I::Ty,
125    /// The upvars captured by the closure. Remains an inference variable
126    /// until the upvar analysis, which happens late in HIR typeck.
127    pub tupled_upvars_ty: I::Ty,
128}
129
130impl<I: Interner> ClosureArgs<I> {
131    /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args`
132    /// for the closure parent, alongside additional closure-specific components.
133    pub fn new(cx: I, parts: ClosureArgsParts<I>) -> ClosureArgs<I> {
134        ClosureArgs {
135            args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
136                parts.closure_kind_ty.into(),
137                parts.closure_sig_as_fn_ptr_ty.into(),
138                parts.tupled_upvars_ty.into(),
139            ])),
140        }
141    }
142
143    /// Divides the closure args into their respective components.
144    /// The ordering assumed here must match that used by `ClosureArgs::new` above.
145    fn split(self) -> ClosureArgsParts<I> {
146        self.args.split_closure_args()
147    }
148
149    /// Returns the generic parameters of the closure's parent.
150    pub fn parent_args(self) -> I::GenericArgsSlice {
151        self.split().parent_args
152    }
153
154    /// Returns an iterator over the list of types of captured paths by the closure.
155    /// In case there was a type error in figuring out the types of the captured path, an
156    /// empty iterator is returned.
157    #[inline]
158    pub fn upvar_tys(self) -> I::Tys {
159        match self.tupled_upvars_ty().kind() {
160            ty::Error(_) => Default::default(),
161            ty::Tuple(tys) => tys,
162            ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"),
163            ty => panic!("Unexpected representation of upvar types tuple {:?}", ty),
164        }
165    }
166
167    /// Returns the tuple type representing the upvars for this closure.
168    #[inline]
169    pub fn tupled_upvars_ty(self) -> I::Ty {
170        self.split().tupled_upvars_ty
171    }
172
173    /// Returns the closure kind for this closure; may return a type
174    /// variable during inference. To get the closure kind during
175    /// inference, use `infcx.closure_kind(args)`.
176    pub fn kind_ty(self) -> I::Ty {
177        self.split().closure_kind_ty
178    }
179
180    /// Returns the `fn` pointer type representing the closure signature for this
181    /// closure.
182    // FIXME(eddyb) this should be unnecessary, as the shallowly resolved
183    // type is known at the time of the creation of `ClosureArgs`,
184    // see `rustc_hir_analysis::check::closure`.
185    pub fn sig_as_fn_ptr_ty(self) -> I::Ty {
186        self.split().closure_sig_as_fn_ptr_ty
187    }
188
189    /// Returns the closure kind for this closure; only usable outside
190    /// of an inference context, because in that context we know that
191    /// there are no type variables.
192    ///
193    /// If you have an inference context, use `infcx.closure_kind()`.
194    pub fn kind(self) -> ty::ClosureKind {
195        self.kind_ty().to_opt_closure_kind().unwrap()
196    }
197
198    /// Extracts the signature from the closure.
199    pub fn sig(self) -> ty::Binder<I, ty::FnSig<I>> {
200        match self.sig_as_fn_ptr_ty().kind() {
201            ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
202            ty => panic!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"),
203        }
204    }
205}
206
207#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
208#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
209pub struct CoroutineClosureArgs<I: Interner> {
210    pub args: I::GenericArgs,
211}
212
213/// See docs for explanation of how each argument is used.
214///
215/// See [`CoroutineClosureSignature`] for how these arguments are put together
216/// to make a callable [`ty::FnSig`] suitable for typeck and borrowck.
217pub struct CoroutineClosureArgsParts<I: Interner> {
218    /// This is the args of the typeck root.
219    pub parent_args: I::GenericArgsSlice,
220    /// Represents the maximum calling capability of the closure.
221    pub closure_kind_ty: I::Ty,
222    /// Represents all of the relevant parts of the coroutine returned by this
223    /// coroutine-closure. This signature parts type will have the general
224    /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where
225    /// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the
226    /// coroutine returned by the coroutine-closure.
227    ///
228    /// Use `coroutine_closure_sig` to break up this type rather than using it
229    /// yourself.
230    pub signature_parts_ty: I::Ty,
231    /// The upvars captured by the closure. Remains an inference variable
232    /// until the upvar analysis, which happens late in HIR typeck.
233    pub tupled_upvars_ty: I::Ty,
234    /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`.
235    /// This allows us to represent the binder of the self-captures of the closure.
236    ///
237    /// For example, if the coroutine returned by the closure borrows `String`
238    /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`,
239    /// while the `tupled_upvars_ty`, representing the by-move version of the same
240    /// captures, will be `(String,)`.
241    pub coroutine_captures_by_ref_ty: I::Ty,
242    /// Witness type returned by the generator produced by this coroutine-closure.
243    pub coroutine_witness_ty: I::Ty,
244}
245
246impl<I: Interner> CoroutineClosureArgs<I> {
247    pub fn new(cx: I, parts: CoroutineClosureArgsParts<I>) -> CoroutineClosureArgs<I> {
248        CoroutineClosureArgs {
249            args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
250                parts.closure_kind_ty.into(),
251                parts.signature_parts_ty.into(),
252                parts.tupled_upvars_ty.into(),
253                parts.coroutine_captures_by_ref_ty.into(),
254                parts.coroutine_witness_ty.into(),
255            ])),
256        }
257    }
258
259    fn split(self) -> CoroutineClosureArgsParts<I> {
260        self.args.split_coroutine_closure_args()
261    }
262
263    pub fn parent_args(self) -> I::GenericArgsSlice {
264        self.split().parent_args
265    }
266
267    #[inline]
268    pub fn upvar_tys(self) -> I::Tys {
269        match self.tupled_upvars_ty().kind() {
270            ty::Error(_) => Default::default(),
271            ty::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
272            ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"),
273            ty => panic!("Unexpected representation of upvar types tuple {:?}", ty),
274        }
275    }
276
277    #[inline]
278    pub fn tupled_upvars_ty(self) -> I::Ty {
279        self.split().tupled_upvars_ty
280    }
281
282    pub fn kind_ty(self) -> I::Ty {
283        self.split().closure_kind_ty
284    }
285
286    pub fn kind(self) -> ty::ClosureKind {
287        self.kind_ty().to_opt_closure_kind().unwrap()
288    }
289
290    pub fn signature_parts_ty(self) -> I::Ty {
291        self.split().signature_parts_ty
292    }
293
294    pub fn coroutine_closure_sig(self) -> ty::Binder<I, CoroutineClosureSignature<I>> {
295        let interior = self.coroutine_witness_ty();
296        let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { panic!() };
297        sig_tys.map_bound(|sig_tys| {
298            let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else {
299                panic!();
300            };
301            let [yield_ty, return_ty] = *sig_tys.output().tuple_fields().as_slice() else {
302                panic!()
303            };
304            CoroutineClosureSignature {
305                interior,
306                tupled_inputs_ty,
307                resume_ty,
308                yield_ty,
309                return_ty,
310                c_variadic: hdr.c_variadic,
311                safety: hdr.safety,
312                abi: hdr.abi,
313            }
314        })
315    }
316
317    pub fn coroutine_captures_by_ref_ty(self) -> I::Ty {
318        self.split().coroutine_captures_by_ref_ty
319    }
320
321    pub fn coroutine_witness_ty(self) -> I::Ty {
322        self.split().coroutine_witness_ty
323    }
324
325    pub fn has_self_borrows(&self) -> bool {
326        match self.coroutine_captures_by_ref_ty().kind() {
327            ty::FnPtr(sig_tys, _) => sig_tys
328                .skip_binder()
329                .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
330                .is_break(),
331            ty::Error(_) => true,
332            _ => panic!(),
333        }
334    }
335}
336
337/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will
338/// detect only regions bound *at* the debruijn index.
339struct HasRegionsBoundAt {
340    binder: ty::DebruijnIndex,
341}
342// FIXME: Could be optimized to not walk into components with no escaping bound vars.
343impl<I: Interner> TypeVisitor<I> for HasRegionsBoundAt {
344    type Result = ControlFlow<()>;
345    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
346        self.binder.shift_in(1);
347        t.super_visit_with(self)?;
348        self.binder.shift_out(1);
349        ControlFlow::Continue(())
350    }
351
352    fn visit_region(&mut self, r: I::Region) -> Self::Result {
353        if matches!(r.kind(), ty::ReBound(binder, _) if self.binder == binder) {
354            ControlFlow::Break(())
355        } else {
356            ControlFlow::Continue(())
357        }
358    }
359}
360
361#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
362#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
363pub struct CoroutineClosureSignature<I: Interner> {
364    pub interior: I::Ty,
365    pub tupled_inputs_ty: I::Ty,
366    pub resume_ty: I::Ty,
367    pub yield_ty: I::Ty,
368    pub return_ty: I::Ty,
369
370    // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types
371    // never actually differ. But we save them rather than recreating them
372    // from scratch just for good measure.
373    /// Always false
374    pub c_variadic: bool,
375    /// Always `Normal` (safe)
376    #[type_visitable(ignore)]
377    #[type_foldable(identity)]
378    pub safety: I::Safety,
379    /// Always `RustCall`
380    #[type_visitable(ignore)]
381    #[type_foldable(identity)]
382    pub abi: I::Abi,
383}
384
385impl<I: Interner> CoroutineClosureSignature<I> {
386    /// Construct a coroutine from the closure signature. Since a coroutine signature
387    /// is agnostic to the type of generator that is returned (by-ref/by-move),
388    /// the caller must specify what "flavor" of generator that they'd like to
389    /// create. Additionally, they must manually compute the upvars of the closure.
390    ///
391    /// This helper is not really meant to be used directly except for early on
392    /// during typeck, when we want to put inference vars into the kind and upvars tys.
393    /// When the kind and upvars are known, use the other helper functions.
394    pub fn to_coroutine(
395        self,
396        cx: I,
397        parent_args: I::GenericArgsSlice,
398        coroutine_kind_ty: I::Ty,
399        coroutine_def_id: I::DefId,
400        tupled_upvars_ty: I::Ty,
401    ) -> I::Ty {
402        let coroutine_args = ty::CoroutineArgs::new(
403            cx,
404            ty::CoroutineArgsParts {
405                parent_args,
406                kind_ty: coroutine_kind_ty,
407                resume_ty: self.resume_ty,
408                yield_ty: self.yield_ty,
409                return_ty: self.return_ty,
410                witness: self.interior,
411                tupled_upvars_ty,
412            },
413        );
414
415        Ty::new_coroutine(cx, coroutine_def_id, coroutine_args.args)
416    }
417
418    /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine
419    /// returned by that corresponding async fn trait.
420    ///
421    /// This function expects the upvars to have been computed already, and doesn't check
422    /// that the `ClosureKind` is actually supported by the coroutine-closure.
423    pub fn to_coroutine_given_kind_and_upvars(
424        self,
425        cx: I,
426        parent_args: I::GenericArgsSlice,
427        coroutine_def_id: I::DefId,
428        goal_kind: ty::ClosureKind,
429        env_region: I::Region,
430        closure_tupled_upvars_ty: I::Ty,
431        coroutine_captures_by_ref_ty: I::Ty,
432    ) -> I::Ty {
433        let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind(
434            cx,
435            goal_kind,
436            self.tupled_inputs_ty,
437            closure_tupled_upvars_ty,
438            coroutine_captures_by_ref_ty,
439            env_region,
440        );
441
442        self.to_coroutine(
443            cx,
444            parent_args,
445            Ty::from_coroutine_closure_kind(cx, goal_kind),
446            coroutine_def_id,
447            tupled_upvars_ty,
448        )
449    }
450
451    /// Compute the tupled upvars that a coroutine-closure's output coroutine
452    /// would return for the given `ClosureKind`.
453    ///
454    /// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref"
455    /// to return a set of upvars which are borrowed with the given `env_region`.
456    ///
457    /// This ensures that the `AsyncFn::call` will return a coroutine whose upvars'
458    /// lifetimes are related to the lifetime of the borrow on the closure made for
459    /// the call. This allows borrowck to enforce the self-borrows correctly.
460    pub fn tupled_upvars_by_closure_kind(
461        cx: I,
462        kind: ty::ClosureKind,
463        tupled_inputs_ty: I::Ty,
464        closure_tupled_upvars_ty: I::Ty,
465        coroutine_captures_by_ref_ty: I::Ty,
466        env_region: I::Region,
467    ) -> I::Ty {
468        match kind {
469            ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
470                let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else {
471                    panic!();
472                };
473                let coroutine_captures_by_ref_ty =
474                    sig_tys.output().skip_binder().fold_with(&mut FoldEscapingRegions {
475                        interner: cx,
476                        region: env_region,
477                        debruijn: ty::INNERMOST,
478                        cache: Default::default(),
479                    });
480                Ty::new_tup_from_iter(
481                    cx,
482                    tupled_inputs_ty
483                        .tuple_fields()
484                        .iter()
485                        .chain(coroutine_captures_by_ref_ty.tuple_fields().iter()),
486                )
487            }
488            ty::ClosureKind::FnOnce => Ty::new_tup_from_iter(
489                cx,
490                tupled_inputs_ty
491                    .tuple_fields()
492                    .iter()
493                    .chain(closure_tupled_upvars_ty.tuple_fields().iter()),
494            ),
495        }
496    }
497}
498
499/// Instantiates a `for<'env> ...` binder with a specific region.
500// FIXME(async_closures): Get rid of this in favor of `BoundVarReplacerDelegate`
501// when that is uplifted.
502struct FoldEscapingRegions<I: Interner> {
503    interner: I,
504    debruijn: ty::DebruijnIndex,
505    region: I::Region,
506
507    // Depends on `debruijn` because we may have types with regions of different
508    // debruijn depths depending on the binders we've entered.
509    cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>,
510}
511
512impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
513    fn cx(&self) -> I {
514        self.interner
515    }
516
517    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
518        if !t.has_vars_bound_at_or_above(self.debruijn) {
519            t
520        } else if let Some(&t) = self.cache.get(&(self.debruijn, t)) {
521            t
522        } else {
523            let res = t.super_fold_with(self);
524            assert!(self.cache.insert((self.debruijn, t), res));
525            res
526        }
527    }
528
529    fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
530    where
531        T: TypeFoldable<I>,
532    {
533        self.debruijn.shift_in(1);
534        let result = t.super_fold_with(self);
535        self.debruijn.shift_out(1);
536        result
537    }
538
539    fn fold_region(&mut self, r: <I as Interner>::Region) -> <I as Interner>::Region {
540        if let ty::ReBound(debruijn, _) = r.kind() {
541            assert!(
542                debruijn <= self.debruijn,
543                "cannot instantiate binder with escaping bound vars"
544            );
545            if self.debruijn == debruijn {
546                shift_region(self.interner, self.region, self.debruijn.as_u32())
547            } else {
548                r
549            }
550        } else {
551            r
552        }
553    }
554}
555
556#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
557#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
558pub struct GenSig<I: Interner> {
559    pub resume_ty: I::Ty,
560    pub yield_ty: I::Ty,
561    pub return_ty: I::Ty,
562}
563
564/// Similar to `ClosureArgs`; see the above documentation for more.
565#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
566#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
567pub struct CoroutineArgs<I: Interner> {
568    pub args: I::GenericArgs,
569}
570
571pub struct CoroutineArgsParts<I: Interner> {
572    /// This is the args of the typeck root.
573    pub parent_args: I::GenericArgsSlice,
574
575    /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut`
576    /// implementations must be distinguished since the former takes the closure's
577    /// upvars by move, and the latter takes the closure's upvars by ref.
578    ///
579    /// This field distinguishes these fields so that codegen can select the right
580    /// body for the coroutine. This has the same type representation as the closure
581    /// kind: `i8`/`i16`/`i32`.
582    ///
583    /// For regular coroutines, this field will always just be `()`.
584    pub kind_ty: I::Ty,
585
586    pub resume_ty: I::Ty,
587    pub yield_ty: I::Ty,
588    pub return_ty: I::Ty,
589
590    /// The interior type of the coroutine.
591    /// Represents all types that are stored in locals
592    /// in the coroutine's body.
593    pub witness: I::Ty,
594
595    /// The upvars captured by the closure. Remains an inference variable
596    /// until the upvar analysis, which happens late in HIR typeck.
597    pub tupled_upvars_ty: I::Ty,
598}
599
600impl<I: Interner> CoroutineArgs<I> {
601    /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
602    /// for the coroutine parent, alongside additional coroutine-specific components.
603    pub fn new(cx: I, parts: CoroutineArgsParts<I>) -> CoroutineArgs<I> {
604        CoroutineArgs {
605            args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
606                parts.kind_ty.into(),
607                parts.resume_ty.into(),
608                parts.yield_ty.into(),
609                parts.return_ty.into(),
610                parts.witness.into(),
611                parts.tupled_upvars_ty.into(),
612            ])),
613        }
614    }
615
616    /// Divides the coroutine args into their respective components.
617    /// The ordering assumed here must match that used by `CoroutineArgs::new` above.
618    fn split(self) -> CoroutineArgsParts<I> {
619        self.args.split_coroutine_args()
620    }
621
622    /// Returns the generic parameters of the coroutine's parent.
623    pub fn parent_args(self) -> I::GenericArgsSlice {
624        self.split().parent_args
625    }
626
627    // Returns the kind of the coroutine. See docs on the `kind_ty` field.
628    pub fn kind_ty(self) -> I::Ty {
629        self.split().kind_ty
630    }
631
632    /// This describes the types that can be contained in a coroutine.
633    /// It will be a type variable initially and unified in the last stages of typeck of a body.
634    /// It contains a tuple of all the types that could end up on a coroutine frame.
635    /// The state transformation MIR pass may only produce layouts which mention types
636    /// in this tuple. Upvars are not counted here.
637    pub fn witness(self) -> I::Ty {
638        self.split().witness
639    }
640
641    /// Returns an iterator over the list of types of captured paths by the coroutine.
642    /// In case there was a type error in figuring out the types of the captured path, an
643    /// empty iterator is returned.
644    #[inline]
645    pub fn upvar_tys(self) -> I::Tys {
646        match self.tupled_upvars_ty().kind() {
647            ty::Error(_) => Default::default(),
648            ty::Tuple(tys) => tys,
649            ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"),
650            ty => panic!("Unexpected representation of upvar types tuple {:?}", ty),
651        }
652    }
653
654    /// Returns the tuple type representing the upvars for this coroutine.
655    #[inline]
656    pub fn tupled_upvars_ty(self) -> I::Ty {
657        self.split().tupled_upvars_ty
658    }
659
660    /// Returns the type representing the resume type of the coroutine.
661    pub fn resume_ty(self) -> I::Ty {
662        self.split().resume_ty
663    }
664
665    /// Returns the type representing the yield type of the coroutine.
666    pub fn yield_ty(self) -> I::Ty {
667        self.split().yield_ty
668    }
669
670    /// Returns the type representing the return type of the coroutine.
671    pub fn return_ty(self) -> I::Ty {
672        self.split().return_ty
673    }
674
675    /// Returns the "coroutine signature", which consists of its resume, yield
676    /// and return types.
677    pub fn sig(self) -> GenSig<I> {
678        let parts = self.split();
679        GenSig { resume_ty: parts.resume_ty, yield_ty: parts.yield_ty, return_ty: parts.return_ty }
680    }
681}