1use std::ops::ControlFlow;
23use derive_where::derive_where;
4use rustc_type_ir_macros::{
5GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic,
6};
78use crate::data_structures::DelayedMap;
9use crate::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region};
10use crate::inherent::*;
11use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
12use crate::{selfas ty, Interner};
1314/// 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.
114pub args: I::GenericArgs,
115}
116117impl<I: Interner> Eqfor ClosureArgs<I> {}
118119/// Struct returned by `split()`.
120pub struct ClosureArgsParts<I: Interner> {
121/// This is the args of the typeck root.
122pub parent_args: I::GenericArgsSlice,
123/// Represents the maximum calling capability of the closure.
124pub 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`.
127pub 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.
130pub tupled_upvars_ty: I::Ty,
131}
132133impl<I: Interner> ClosureArgs<I> {
134/// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args`
135 /// for the closure parent, alongside additional closure-specific components.
136pub fn new(cx: I, parts: ClosureArgsParts<I>) -> ClosureArgs<I> {
137ClosureArgs {
138 args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
139parts.closure_kind_ty.into(),
140parts.closure_sig_as_fn_ptr_ty.into(),
141parts.tupled_upvars_ty.into(),
142 ])),
143 }
144 }
145146/// Divides the closure args into their respective components.
147 /// The ordering assumed here must match that used by `ClosureArgs::new` above.
148fn split(self) -> ClosureArgsParts<I> {
149self.args.split_closure_args()
150 }
151152/// Returns the generic parameters of the closure's parent.
153pub fn parent_args(self) -> I::GenericArgsSlice {
154self.split().parent_args
155 }
156157/// 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]
161pub fn upvar_tys(self) -> I::Tys {
162match 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 }
169170/// Returns the tuple type representing the upvars for this closure.
171#[inline]
172pub fn tupled_upvars_ty(self) -> I::Ty {
173self.split().tupled_upvars_ty
174 }
175176/// 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)`.
179pub fn kind_ty(self) -> I::Ty {
180self.split().closure_kind_ty
181 }
182183/// 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`.
188pub fn sig_as_fn_ptr_ty(self) -> I::Ty {
189self.split().closure_sig_as_fn_ptr_ty
190 }
191192/// 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()`.
197pub fn kind(self) -> ty::ClosureKind {
198self.kind_ty().to_opt_closure_kind().unwrap()
199 }
200201/// Extracts the signature from the closure.
202pub fn sig(self) -> ty::Binder<I, ty::FnSig<I>> {
203match 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}
209210#[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> {
213pub args: I::GenericArgs,
214}
215216impl<I: Interner> Eqfor CoroutineClosureArgs<I> {}
217218/// 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.
224pub parent_args: I::GenericArgsSlice,
225/// Represents the maximum calling capability of the closure.
226pub 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.
235pub 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.
238pub 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,)`.
246pub coroutine_captures_by_ref_ty: I::Ty,
247}
248249impl<I: Interner> CoroutineClosureArgs<I> {
250pub fn new(cx: I, parts: CoroutineClosureArgsParts<I>) -> CoroutineClosureArgs<I> {
251CoroutineClosureArgs {
252 args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
253parts.closure_kind_ty.into(),
254parts.signature_parts_ty.into(),
255parts.tupled_upvars_ty.into(),
256parts.coroutine_captures_by_ref_ty.into(),
257 ])),
258 }
259 }
260261fn split(self) -> CoroutineClosureArgsParts<I> {
262self.args.split_coroutine_closure_args()
263 }
264265pub fn parent_args(self) -> I::GenericArgsSlice {
266self.split().parent_args
267 }
268269#[inline]
270pub fn upvar_tys(self) -> I::Tys {
271match 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 }
278279#[inline]
280pub fn tupled_upvars_ty(self) -> I::Ty {
281self.split().tupled_upvars_ty
282 }
283284pub fn kind_ty(self) -> I::Ty {
285self.split().closure_kind_ty
286 }
287288pub fn kind(self) -> ty::ClosureKind {
289self.kind_ty().to_opt_closure_kind().unwrap()
290 }
291292pub fn signature_parts_ty(self) -> I::Ty {
293self.split().signature_parts_ty
294 }
295296pub fn coroutine_closure_sig(self) -> ty::Binder<I, CoroutineClosureSignature<I>> {
297let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { ::core::panicking::panic("explicit panic")panic!() };
298sig_tys.map_bound(|sig_tys| {
299let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else {
300::core::panicking::panic("explicit panic");panic!();
301 };
302let [yield_ty, return_ty] = *sig_tys.output().tuple_fields().as_slice() else {
303::core::panicking::panic("explicit panic")panic!()304 };
305CoroutineClosureSignature {
306tupled_inputs_ty,
307resume_ty,
308yield_ty,
309return_ty,
310 fn_sig_kind: hdr.fn_sig_kind,
311 }
312 })
313 }
314315pub fn coroutine_captures_by_ref_ty(self) -> I::Ty {
316self.split().coroutine_captures_by_ref_ty
317 }
318319pub fn has_self_borrows(&self) -> bool {
320match self.coroutine_captures_by_ref_ty().kind() {
321 ty::FnPtr(sig_tys, _) => sig_tys322 .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}
330331/// 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 {
338type Result = ControlFlow<()>;
339fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
340self.binder.shift_in(1);
341t.super_visit_with(self)?;
342self.binder.shift_out(1);
343 ControlFlow::Continue(())
344 }
345346fn visit_region(&mut self, r: I::Region) -> Self::Result {
347if #[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}
355356#[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> {
359pub tupled_inputs_ty: I::Ty,
360pub resume_ty: I::Ty,
361pub yield_ty: I::Ty,
362pub return_ty: I::Ty,
363364// 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)]
370pub fn_sig_kind: I::FSigKind,
371}
372373impl<I: Interner> Eqfor CoroutineClosureSignature<I> {}
374375impl<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.
384pub fn to_coroutine(
385self,
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 {
392let coroutine_args = ty::CoroutineArgs::new(
393cx,
394 ty::CoroutineArgsParts {
395parent_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,
400tupled_upvars_ty,
401 },
402 );
403404 Ty::new_coroutine(cx, coroutine_def_id, coroutine_args.args)
405 }
406407/// 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.
412pub fn to_coroutine_given_kind_and_upvars(
413self,
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 {
422let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind(
423cx,
424goal_kind,
425self.tupled_inputs_ty,
426closure_tupled_upvars_ty,
427coroutine_captures_by_ref_ty,
428env_region,
429 );
430431self.to_coroutine(
432cx,
433parent_args,
434 Ty::from_coroutine_closure_kind(cx, goal_kind),
435coroutine_def_id,
436tupled_upvars_ty,
437 )
438 }
439440/// 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.
449pub 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 {
457match kind {
458 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
459let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else {
460::core::panicking::panic("explicit panic");panic!();
461 };
462let coroutine_captures_by_ref_ty =
463sig_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(
470cx,
471tupled_inputs_ty472 .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(
478cx,
479tupled_inputs_ty480 .tuple_fields()
481 .iter()
482 .chain(closure_tupled_upvars_ty.tuple_fields().iter()),
483 ),
484 }
485 }
486}
487488/// 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,
495496// Depends on `debruijn` because we may have types with regions of different
497 // debruijn depths depending on the binders we've entered.
498cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>,
499}
500501impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
502fn cx(&self) -> I {
503self.interner
504 }
505506fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
507if !t.has_vars_bound_at_or_above(self.debruijn) {
508t509 } else if let Some(&t) = self.cache.get(&(self.debruijn, t)) {
510t511 } else {
512let res = t.super_fold_with(self);
513if !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));
514res515 }
516 }
517518fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
519where
520T: TypeFoldable<I>,
521 {
522self.debruijn.shift_in(1);
523let result = t.super_fold_with(self);
524self.debruijn.shift_out(1);
525result526 }
527528fn fold_region(&mut self, r: <I as Interner>::Region) -> <I as Interner>::Region {
529if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind() {
530if !(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);
534if self.debruijn == debruijn {
535shift_region(self.interner, self.region, self.debruijn.as_u32())
536 } else {
537r538 }
539 } else {
540r541 }
542 }
543}
544545#[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> {
548pub resume_ty: I::Ty,
549pub yield_ty: I::Ty,
550pub return_ty: I::Ty,
551}
552553impl<I: Interner> Eqfor 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> {
558pub args: I::GenericArgs,
559}
560561impl<I: Interner> Eqfor CoroutineArgs<I> {}
562563pub struct CoroutineArgsParts<I: Interner> {
564/// This is the args of the typeck root.
565pub parent_args: I::GenericArgsSlice,
566567/// 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 `()`.
576pub kind_ty: I::Ty,
577578pub resume_ty: I::Ty,
579pub yield_ty: I::Ty,
580pub return_ty: I::Ty,
581582/// The upvars captured by the closure. Remains an inference variable
583 /// until the upvar analysis, which happens late in HIR typeck.
584pub tupled_upvars_ty: I::Ty,
585}
586587impl<I: Interner> CoroutineArgs<I> {
588/// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
589 /// for the coroutine parent, alongside additional coroutine-specific components.
590pub fn new(cx: I, parts: CoroutineArgsParts<I>) -> CoroutineArgs<I> {
591CoroutineArgs {
592 args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
593parts.kind_ty.into(),
594parts.resume_ty.into(),
595parts.yield_ty.into(),
596parts.return_ty.into(),
597parts.tupled_upvars_ty.into(),
598 ])),
599 }
600 }
601602/// Divides the coroutine args into their respective components.
603 /// The ordering assumed here must match that used by `CoroutineArgs::new` above.
604fn split(self) -> CoroutineArgsParts<I> {
605self.args.split_coroutine_args()
606 }
607608/// Returns the generic parameters of the coroutine's parent.
609pub fn parent_args(self) -> I::GenericArgsSlice {
610self.split().parent_args
611 }
612613// Returns the kind of the coroutine. See docs on the `kind_ty` field.
614pub fn kind_ty(self) -> I::Ty {
615self.split().kind_ty
616 }
617618/// 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]
622pub fn upvar_tys(self) -> I::Tys {
623match 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 }
630631/// Returns the tuple type representing the upvars for this coroutine.
632#[inline]
633pub fn tupled_upvars_ty(self) -> I::Ty {
634self.split().tupled_upvars_ty
635 }
636637/// Returns the type representing the resume type of the coroutine.
638pub fn resume_ty(self) -> I::Ty {
639self.split().resume_ty
640 }
641642/// Returns the type representing the yield type of the coroutine.
643pub fn yield_ty(self) -> I::Ty {
644self.split().yield_ty
645 }
646647/// Returns the type representing the return type of the coroutine.
648pub fn return_ty(self) -> I::Ty {
649self.split().return_ty
650 }
651652/// Returns the "coroutine signature", which consists of its resume, yield
653 /// and return types.
654pub fn sig(self) -> GenSig<I> {
655let parts = self.split();
656GenSig { resume_ty: parts.resume_ty, yield_ty: parts.yield_ty, return_ty: parts.return_ty }
657 }
658}