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 c_variadic: hdr.c_variadic,
311 safety: hdr.safety,
312 abi: hdr.abi,
313 }
314 })
315 }
316317pub fn coroutine_captures_by_ref_ty(self) -> I::Ty {
318self.split().coroutine_captures_by_ref_ty
319 }
320321pub fn has_self_borrows(&self) -> bool {
322match self.coroutine_captures_by_ref_ty().kind() {
323 ty::FnPtr(sig_tys, _) => sig_tys324 .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}
332333/// 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 {
340type Result = ControlFlow<()>;
341fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
342self.binder.shift_in(1);
343t.super_visit_with(self)?;
344self.binder.shift_out(1);
345 ControlFlow::Continue(())
346 }
347348fn visit_region(&mut self, r: I::Region) -> Self::Result {
349if #[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}
357358#[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> {
361pub tupled_inputs_ty: I::Ty,
362pub resume_ty: I::Ty,
363pub yield_ty: I::Ty,
364pub return_ty: I::Ty,
365366// 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
370pub c_variadic: bool,
371/// Always `Normal` (safe)
372#[type_visitable(ignore)]
373 #[type_foldable(identity)]
374pub safety: I::Safety,
375/// Always `RustCall`
376#[type_visitable(ignore)]
377 #[type_foldable(identity)]
378pub abi: I::Abi,
379}
380381impl<I: Interner> Eqfor CoroutineClosureSignature<I> {}
382383impl<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.
392pub fn to_coroutine(
393self,
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 {
400let coroutine_args = ty::CoroutineArgs::new(
401cx,
402 ty::CoroutineArgsParts {
403parent_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,
408tupled_upvars_ty,
409 },
410 );
411412 Ty::new_coroutine(cx, coroutine_def_id, coroutine_args.args)
413 }
414415/// 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.
420pub fn to_coroutine_given_kind_and_upvars(
421self,
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 {
430let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind(
431cx,
432goal_kind,
433self.tupled_inputs_ty,
434closure_tupled_upvars_ty,
435coroutine_captures_by_ref_ty,
436env_region,
437 );
438439self.to_coroutine(
440cx,
441parent_args,
442 Ty::from_coroutine_closure_kind(cx, goal_kind),
443coroutine_def_id,
444tupled_upvars_ty,
445 )
446 }
447448/// 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.
457pub 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 {
465match kind {
466 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
467let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else {
468::core::panicking::panic("explicit panic");panic!();
469 };
470let coroutine_captures_by_ref_ty =
471sig_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(
478cx,
479tupled_inputs_ty480 .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(
486cx,
487tupled_inputs_ty488 .tuple_fields()
489 .iter()
490 .chain(closure_tupled_upvars_ty.tuple_fields().iter()),
491 ),
492 }
493 }
494}
495496/// 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,
503504// Depends on `debruijn` because we may have types with regions of different
505 // debruijn depths depending on the binders we've entered.
506cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>,
507}
508509impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
510fn cx(&self) -> I {
511self.interner
512 }
513514fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
515if !t.has_vars_bound_at_or_above(self.debruijn) {
516t517 } else if let Some(&t) = self.cache.get(&(self.debruijn, t)) {
518t519 } else {
520let res = t.super_fold_with(self);
521if !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));
522res523 }
524 }
525526fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
527where
528T: TypeFoldable<I>,
529 {
530self.debruijn.shift_in(1);
531let result = t.super_fold_with(self);
532self.debruijn.shift_out(1);
533result534 }
535536fn fold_region(&mut self, r: <I as Interner>::Region) -> <I as Interner>::Region {
537if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind() {
538if !(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);
542if self.debruijn == debruijn {
543shift_region(self.interner, self.region, self.debruijn.as_u32())
544 } else {
545r546 }
547 } else {
548r549 }
550 }
551}
552553#[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> {
556pub resume_ty: I::Ty,
557pub yield_ty: I::Ty,
558pub return_ty: I::Ty,
559}
560561impl<I: Interner> Eqfor 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> {
566pub args: I::GenericArgs,
567}
568569impl<I: Interner> Eqfor CoroutineArgs<I> {}
570571pub struct CoroutineArgsParts<I: Interner> {
572/// This is the args of the typeck root.
573pub parent_args: I::GenericArgsSlice,
574575/// 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 `()`.
584pub kind_ty: I::Ty,
585586pub resume_ty: I::Ty,
587pub yield_ty: I::Ty,
588pub return_ty: I::Ty,
589590/// The upvars captured by the closure. Remains an inference variable
591 /// until the upvar analysis, which happens late in HIR typeck.
592pub tupled_upvars_ty: I::Ty,
593}
594595impl<I: Interner> CoroutineArgs<I> {
596/// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
597 /// for the coroutine parent, alongside additional coroutine-specific components.
598pub fn new(cx: I, parts: CoroutineArgsParts<I>) -> CoroutineArgs<I> {
599CoroutineArgs {
600 args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
601parts.kind_ty.into(),
602parts.resume_ty.into(),
603parts.yield_ty.into(),
604parts.return_ty.into(),
605parts.tupled_upvars_ty.into(),
606 ])),
607 }
608 }
609610/// Divides the coroutine args into their respective components.
611 /// The ordering assumed here must match that used by `CoroutineArgs::new` above.
612fn split(self) -> CoroutineArgsParts<I> {
613self.args.split_coroutine_args()
614 }
615616/// Returns the generic parameters of the coroutine's parent.
617pub fn parent_args(self) -> I::GenericArgsSlice {
618self.split().parent_args
619 }
620621// Returns the kind of the coroutine. See docs on the `kind_ty` field.
622pub fn kind_ty(self) -> I::Ty {
623self.split().kind_ty
624 }
625626/// 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]
630pub fn upvar_tys(self) -> I::Tys {
631match 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 }
638639/// Returns the tuple type representing the upvars for this coroutine.
640#[inline]
641pub fn tupled_upvars_ty(self) -> I::Ty {
642self.split().tupled_upvars_ty
643 }
644645/// Returns the type representing the resume type of the coroutine.
646pub fn resume_ty(self) -> I::Ty {
647self.split().resume_ty
648 }
649650/// Returns the type representing the yield type of the coroutine.
651pub fn yield_ty(self) -> I::Ty {
652self.split().yield_ty
653 }
654655/// Returns the type representing the return type of the coroutine.
656pub fn return_ty(self) -> I::Ty {
657self.split().return_ty
658 }
659660/// Returns the "coroutine signature", which consists of its resume, yield
661 /// and return types.
662pub fn sig(self) -> GenSig<I> {
663let parts = self.split();
664GenSig { resume_ty: parts.resume_ty, yield_ty: parts.yield_ty, return_ty: parts.return_ty }
665 }
666}