rustc_type_ir/ty_kind/
closure.rs

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