Skip to main content

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, FnSigKind, 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                fn_sig_kind: hdr.fn_sig_kind,
311            }
312        })
313    }
314
315    pub fn coroutine_captures_by_ref_ty(self) -> I::Ty {
316        self.split().coroutine_captures_by_ref_ty
317    }
318
319    pub fn has_self_borrows(&self) -> bool {
320        match self.coroutine_captures_by_ref_ty().kind() {
321            ty::FnPtr(sig_tys, _) => sig_tys
322                .skip_binder()
323                .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
324                .is_break(),
325            ty::Error(_) => true,
326            _ => ::core::panicking::panic("explicit panic")panic!(),
327        }
328    }
329}
330
331/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will
332/// detect only regions bound *at* the debruijn index.
333struct HasRegionsBoundAt {
334    binder: ty::DebruijnIndex,
335}
336// FIXME: Could be optimized to not walk into components with no escaping bound vars.
337impl<I: Interner> TypeVisitor<I> for HasRegionsBoundAt {
338    type Result = ControlFlow<()>;
339    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
340        self.binder.shift_in(1);
341        t.super_visit_with(self)?;
342        self.binder.shift_out(1);
343        ControlFlow::Continue(())
344    }
345
346    fn visit_region(&mut self, r: I::Region) -> Self::Result {
347        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)
348        {
349            ControlFlow::Break(())
350        } else {
351            ControlFlow::Continue(())
352        }
353    }
354}
355
356#[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,
                fn_sig_kind: ref __field_fn_sig_kind } => {
                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, "fn_sig_kind",
                    __field_fn_sig_kind);
                ::core::fmt::DebugStruct::finish(&mut __builder)
            }
        }
    }
}#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)]
357#[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, .. } => {
                        {
                            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);
                                }
                            }
                        }
                    }
                }
                <__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,
                            fn_sig_kind: __binding_4 } => {
                            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)?,
                                fn_sig_kind: __binding_4,
                            }
                        }
                    })
            }
            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,
                        fn_sig_kind: __binding_4 } => {
                        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),
                            fn_sig_kind: __binding_4,
                        }
                    }
                }
            }
        }
    };TypeFoldable_Generic)]
358pub struct CoroutineClosureSignature<I: Interner> {
359    pub tupled_inputs_ty: I::Ty,
360    pub resume_ty: I::Ty,
361    pub yield_ty: I::Ty,
362    pub return_ty: I::Ty,
363
364    // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types
365    // never actually differ. But we save them rather than recreating them
366    // from scratch just for good measure.
367    /// Always safe, RustCall, non-c-variadic
368    #[type_visitable(ignore)]
369    #[type_foldable(identity)]
370    pub fn_sig_kind: FnSigKind<I>,
371}
372
373impl<I: Interner> Eq for CoroutineClosureSignature<I> {}
374
375impl<I: Interner> CoroutineClosureSignature<I> {
376    /// Construct a coroutine from the closure signature. Since a coroutine signature
377    /// is agnostic to the type of generator that is returned (by-ref/by-move),
378    /// the caller must specify what "flavor" of generator that they'd like to
379    /// create. Additionally, they must manually compute the upvars of the closure.
380    ///
381    /// This helper is not really meant to be used directly except for early on
382    /// during typeck, when we want to put inference vars into the kind and upvars tys.
383    /// When the kind and upvars are known, use the other helper functions.
384    pub fn to_coroutine(
385        self,
386        cx: I,
387        parent_args: I::GenericArgsSlice,
388        coroutine_kind_ty: I::Ty,
389        coroutine_def_id: I::CoroutineId,
390        tupled_upvars_ty: I::Ty,
391    ) -> I::Ty {
392        let coroutine_args = ty::CoroutineArgs::new(
393            cx,
394            ty::CoroutineArgsParts {
395                parent_args,
396                kind_ty: coroutine_kind_ty,
397                resume_ty: self.resume_ty,
398                yield_ty: self.yield_ty,
399                return_ty: self.return_ty,
400                tupled_upvars_ty,
401            },
402        );
403
404        Ty::new_coroutine(cx, coroutine_def_id, coroutine_args.args)
405    }
406
407    /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine
408    /// returned by that corresponding async fn trait.
409    ///
410    /// This function expects the upvars to have been computed already, and doesn't check
411    /// that the `ClosureKind` is actually supported by the coroutine-closure.
412    pub fn to_coroutine_given_kind_and_upvars(
413        self,
414        cx: I,
415        parent_args: I::GenericArgsSlice,
416        coroutine_def_id: I::CoroutineId,
417        goal_kind: ty::ClosureKind,
418        env_region: I::Region,
419        closure_tupled_upvars_ty: I::Ty,
420        coroutine_captures_by_ref_ty: I::Ty,
421    ) -> I::Ty {
422        let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind(
423            cx,
424            goal_kind,
425            self.tupled_inputs_ty,
426            closure_tupled_upvars_ty,
427            coroutine_captures_by_ref_ty,
428            env_region,
429        );
430
431        self.to_coroutine(
432            cx,
433            parent_args,
434            Ty::from_coroutine_closure_kind(cx, goal_kind),
435            coroutine_def_id,
436            tupled_upvars_ty,
437        )
438    }
439
440    /// Compute the tupled upvars that a coroutine-closure's output coroutine
441    /// would return for the given `ClosureKind`.
442    ///
443    /// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref"
444    /// to return a set of upvars which are borrowed with the given `env_region`.
445    ///
446    /// This ensures that the `AsyncFn::call` will return a coroutine whose upvars'
447    /// lifetimes are related to the lifetime of the borrow on the closure made for
448    /// the call. This allows borrowck to enforce the self-borrows correctly.
449    pub fn tupled_upvars_by_closure_kind(
450        cx: I,
451        kind: ty::ClosureKind,
452        tupled_inputs_ty: I::Ty,
453        closure_tupled_upvars_ty: I::Ty,
454        coroutine_captures_by_ref_ty: I::Ty,
455        env_region: I::Region,
456    ) -> I::Ty {
457        match kind {
458            ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
459                let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else {
460                    ::core::panicking::panic("explicit panic");panic!();
461                };
462                let coroutine_captures_by_ref_ty =
463                    sig_tys.output().skip_binder().fold_with(&mut FoldEscapingRegions {
464                        interner: cx,
465                        region: env_region,
466                        debruijn: ty::INNERMOST,
467                        cache: Default::default(),
468                    });
469                Ty::new_tup_from_iter(
470                    cx,
471                    tupled_inputs_ty
472                        .tuple_fields()
473                        .iter()
474                        .chain(coroutine_captures_by_ref_ty.tuple_fields().iter()),
475                )
476            }
477            ty::ClosureKind::FnOnce => Ty::new_tup_from_iter(
478                cx,
479                tupled_inputs_ty
480                    .tuple_fields()
481                    .iter()
482                    .chain(closure_tupled_upvars_ty.tuple_fields().iter()),
483            ),
484        }
485    }
486}
487
488/// Instantiates a `for<'env> ...` binder with a specific region.
489// FIXME(async_closures): Get rid of this in favor of `BoundVarReplacerDelegate`
490// when that is uplifted.
491struct FoldEscapingRegions<I: Interner> {
492    interner: I,
493    debruijn: ty::DebruijnIndex,
494    region: I::Region,
495
496    // Depends on `debruijn` because we may have types with regions of different
497    // debruijn depths depending on the binders we've entered.
498    cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>,
499}
500
501impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
502    fn cx(&self) -> I {
503        self.interner
504    }
505
506    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
507        if !t.has_vars_bound_at_or_above(self.debruijn) {
508            t
509        } else if let Some(&t) = self.cache.get(&(self.debruijn, t)) {
510            t
511        } else {
512            let res = t.super_fold_with(self);
513            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));
514            res
515        }
516    }
517
518    fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
519    where
520        T: TypeFoldable<I>,
521    {
522        self.debruijn.shift_in(1);
523        let result = t.super_fold_with(self);
524        self.debruijn.shift_out(1);
525        result
526    }
527
528    fn fold_region(&mut self, r: <I as Interner>::Region) -> <I as Interner>::Region {
529        if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind() {
530            if !(debruijn <= self.debruijn) {
    {
        ::core::panicking::panic_fmt(format_args!("cannot instantiate binder with escaping bound vars"));
    }
};assert!(
531                debruijn <= self.debruijn,
532                "cannot instantiate binder with escaping bound vars"
533            );
534            if self.debruijn == debruijn {
535                shift_region(self.interner, self.region, self.debruijn.as_u32())
536            } else {
537                r
538            }
539        } else {
540            r
541        }
542    }
543}
544
545#[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)]
546#[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)]
547pub struct GenSig<I: Interner> {
548    pub resume_ty: I::Ty,
549    pub yield_ty: I::Ty,
550    pub return_ty: I::Ty,
551}
552
553impl<I: Interner> Eq for GenSig<I> {}
554/// Similar to `ClosureArgs`; see the above documentation for more.
555#[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)]
556#[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)]
557pub struct CoroutineArgs<I: Interner> {
558    pub args: I::GenericArgs,
559}
560
561impl<I: Interner> Eq for CoroutineArgs<I> {}
562
563pub struct CoroutineArgsParts<I: Interner> {
564    /// This is the args of the typeck root.
565    pub parent_args: I::GenericArgsSlice,
566
567    /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut`
568    /// implementations must be distinguished since the former takes the closure's
569    /// upvars by move, and the latter takes the closure's upvars by ref.
570    ///
571    /// This field distinguishes these fields so that codegen can select the right
572    /// body for the coroutine. This has the same type representation as the closure
573    /// kind: `i8`/`i16`/`i32`.
574    ///
575    /// For regular coroutines, this field will always just be `()`.
576    pub kind_ty: I::Ty,
577
578    pub resume_ty: I::Ty,
579    pub yield_ty: I::Ty,
580    pub return_ty: I::Ty,
581
582    /// The upvars captured by the closure. Remains an inference variable
583    /// until the upvar analysis, which happens late in HIR typeck.
584    pub tupled_upvars_ty: I::Ty,
585}
586
587impl<I: Interner> CoroutineArgs<I> {
588    /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
589    /// for the coroutine parent, alongside additional coroutine-specific components.
590    pub fn new(cx: I, parts: CoroutineArgsParts<I>) -> CoroutineArgs<I> {
591        CoroutineArgs {
592            args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
593                parts.kind_ty.into(),
594                parts.resume_ty.into(),
595                parts.yield_ty.into(),
596                parts.return_ty.into(),
597                parts.tupled_upvars_ty.into(),
598            ])),
599        }
600    }
601
602    /// Divides the coroutine args into their respective components.
603    /// The ordering assumed here must match that used by `CoroutineArgs::new` above.
604    fn split(self) -> CoroutineArgsParts<I> {
605        self.args.split_coroutine_args()
606    }
607
608    /// Returns the generic parameters of the coroutine's parent.
609    pub fn parent_args(self) -> I::GenericArgsSlice {
610        self.split().parent_args
611    }
612
613    // Returns the kind of the coroutine. See docs on the `kind_ty` field.
614    pub fn kind_ty(self) -> I::Ty {
615        self.split().kind_ty
616    }
617
618    /// Returns an iterator over the list of types of captured paths by the coroutine.
619    /// In case there was a type error in figuring out the types of the captured path, an
620    /// empty iterator is returned.
621    #[inline]
622    pub fn upvar_tys(self) -> I::Tys {
623        match self.tupled_upvars_ty().kind() {
624            ty::Error(_) => Default::default(),
625            ty::Tuple(tys) => tys,
626            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"),
627            ty => {
    ::core::panicking::panic_fmt(format_args!("Unexpected representation of upvar types tuple {0:?}",
            ty));
}panic!("Unexpected representation of upvar types tuple {:?}", ty),
628        }
629    }
630
631    /// Returns the tuple type representing the upvars for this coroutine.
632    #[inline]
633    pub fn tupled_upvars_ty(self) -> I::Ty {
634        self.split().tupled_upvars_ty
635    }
636
637    /// Returns the type representing the resume type of the coroutine.
638    pub fn resume_ty(self) -> I::Ty {
639        self.split().resume_ty
640    }
641
642    /// Returns the type representing the yield type of the coroutine.
643    pub fn yield_ty(self) -> I::Ty {
644        self.split().yield_ty
645    }
646
647    /// Returns the type representing the return type of the coroutine.
648    pub fn return_ty(self) -> I::Ty {
649        self.split().return_ty
650    }
651
652    /// Returns the "coroutine signature", which consists of its resume, yield
653    /// and return types.
654    pub fn sig(self) -> GenSig<I> {
655        let parts = self.split();
656        GenSig { resume_ty: parts.resume_ty, yield_ty: parts.yield_ty, return_ty: parts.return_ty }
657    }
658}