|
|
|
@ -16,7 +16,7 @@ use rustc_errors::{ErrorGuaranteed, MultiSpan};
|
|
|
|
|
use rustc_hir as hir;
|
|
|
|
|
use rustc_hir::def_id::DefId;
|
|
|
|
|
use rustc_hir::LangItem;
|
|
|
|
|
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable};
|
|
|
|
|
use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable};
|
|
|
|
|
use rustc_span::symbol::{sym, Symbol};
|
|
|
|
|
use rustc_span::{Span, DUMMY_SP};
|
|
|
|
|
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
|
|
|
|
@ -30,7 +30,6 @@ use ty::util::{AsyncDropGlueMorphology, IntTypeExt};
|
|
|
|
|
use rustc_type_ir::TyKind::*;
|
|
|
|
|
use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind};
|
|
|
|
|
|
|
|
|
|
use super::fold::FnMutDelegate;
|
|
|
|
|
use super::GenericParamDefKind;
|
|
|
|
|
|
|
|
|
|
// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
|
|
|
|
@ -60,670 +59,14 @@ impl<'tcx> Article for TyKind<'tcx> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A closure can be modeled as a struct that looks like:
|
|
|
|
|
/// ```ignore (illustrative)
|
|
|
|
|
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
|
|
|
|
|
/// ```
|
|
|
|
|
/// where:
|
|
|
|
|
///
|
|
|
|
|
/// - 'l0...'li and T0...Tj are the generic parameters
|
|
|
|
|
/// in scope on the function that defined the closure,
|
|
|
|
|
/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This
|
|
|
|
|
/// is rather hackily encoded via a scalar type. See
|
|
|
|
|
/// `Ty::to_opt_closure_kind` for details.
|
|
|
|
|
/// - CS represents the *closure signature*, representing as a `fn()`
|
|
|
|
|
/// type. For example, `fn(u32, u32) -> u32` would mean that the closure
|
|
|
|
|
/// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait
|
|
|
|
|
/// specified above.
|
|
|
|
|
/// - U is a type parameter representing the types of its upvars, tupled up
|
|
|
|
|
/// (borrowed, if appropriate; that is, if a U field represents a by-ref upvar,
|
|
|
|
|
/// and the up-var has the type `Foo`, then that field of U will be `&Foo`).
|
|
|
|
|
///
|
|
|
|
|
/// So, for example, given this function:
|
|
|
|
|
/// ```ignore (illustrative)
|
|
|
|
|
/// fn foo<'a, T>(data: &'a mut T) {
|
|
|
|
|
/// do(|| data.count += 1)
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
/// the type of the closure would be something like:
|
|
|
|
|
/// ```ignore (illustrative)
|
|
|
|
|
/// struct Closure<'a, T, U>(...U);
|
|
|
|
|
/// ```
|
|
|
|
|
/// Note that the type of the upvar is not specified in the struct.
|
|
|
|
|
/// You may wonder how the impl would then be able to use the upvar,
|
|
|
|
|
/// if it doesn't know it's type? The answer is that the impl is
|
|
|
|
|
/// (conceptually) not fully generic over Closure but rather tied to
|
|
|
|
|
/// instances with the expected upvar types:
|
|
|
|
|
/// ```ignore (illustrative)
|
|
|
|
|
/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
|
|
|
|
|
/// ...
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
/// You can see that the *impl* fully specified the type of the upvar
|
|
|
|
|
/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
|
|
|
|
|
/// (Here, I am assuming that `data` is mut-borrowed.)
|
|
|
|
|
///
|
|
|
|
|
/// Now, the last question you may ask is: Why include the upvar types
|
|
|
|
|
/// in an extra type parameter? The reason for this design is that the
|
|
|
|
|
/// upvar types can reference lifetimes that are internal to the
|
|
|
|
|
/// creating function. In my example above, for example, the lifetime
|
|
|
|
|
/// `'b` represents the scope of the closure itself; this is some
|
|
|
|
|
/// subset of `foo`, probably just the scope of the call to the to
|
|
|
|
|
/// `do()`. If we just had the lifetime/type parameters from the
|
|
|
|
|
/// enclosing function, we couldn't name this lifetime `'b`. Note that
|
|
|
|
|
/// there can also be lifetimes in the types of the upvars themselves,
|
|
|
|
|
/// if one of them happens to be a reference to something that the
|
|
|
|
|
/// creating fn owns.
|
|
|
|
|
///
|
|
|
|
|
/// OK, you say, so why not create a more minimal set of parameters
|
|
|
|
|
/// that just includes the extra lifetime parameters? The answer is
|
|
|
|
|
/// primarily that it would be hard --- we don't know at the time when
|
|
|
|
|
/// we create the closure type what the full types of the upvars are,
|
|
|
|
|
/// nor do we know which are borrowed and which are not. In this
|
|
|
|
|
/// design, we can just supply a fresh type parameter and figure that
|
|
|
|
|
/// out later.
|
|
|
|
|
///
|
|
|
|
|
/// All right, you say, but why include the type parameters from the
|
|
|
|
|
/// original function then? The answer is that codegen may need them
|
|
|
|
|
/// when monomorphizing, and they may not appear in the upvars. A
|
|
|
|
|
/// closure could capture no variables but still make use of some
|
|
|
|
|
/// in-scope type parameter with a bound (e.g., if our example above
|
|
|
|
|
/// had an extra `U: Default`, and the closure called `U::default()`).
|
|
|
|
|
///
|
|
|
|
|
/// There is another reason. This design (implicitly) prohibits
|
|
|
|
|
/// closures from capturing themselves (except via a trait
|
|
|
|
|
/// object). This simplifies closure inference considerably, since it
|
|
|
|
|
/// means that when we infer the kind of a closure or its upvars, we
|
|
|
|
|
/// don't have to handle cycles where the decisions we make for
|
|
|
|
|
/// closure C wind up influencing the decisions we ought to make for
|
|
|
|
|
/// closure C (which would then require fixed point iteration to
|
|
|
|
|
/// handle). Plus it fixes an ICE. :P
|
|
|
|
|
///
|
|
|
|
|
/// ## Coroutines
|
|
|
|
|
///
|
|
|
|
|
/// Coroutines are handled similarly in `CoroutineArgs`. The set of
|
|
|
|
|
/// type parameters is similar, but `CK` and `CS` are replaced by the
|
|
|
|
|
/// following type parameters:
|
|
|
|
|
///
|
|
|
|
|
/// * `GS`: The coroutine's "resume type", which is the type of the
|
|
|
|
|
/// argument passed to `resume`, and the type of `yield` expressions
|
|
|
|
|
/// inside the coroutine.
|
|
|
|
|
/// * `GY`: The "yield type", which is the type of values passed to
|
|
|
|
|
/// `yield` inside the coroutine.
|
|
|
|
|
/// * `GR`: The "return type", which is the type of value returned upon
|
|
|
|
|
/// completion of the coroutine.
|
|
|
|
|
/// * `GW`: The "coroutine witness".
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
|
|
|
|
|
pub struct ClosureArgs<'tcx> {
|
|
|
|
|
/// Lifetime and type parameters from the enclosing function,
|
|
|
|
|
/// concatenated with a tuple containing the types of the upvars.
|
|
|
|
|
///
|
|
|
|
|
/// These are separated out because codegen wants to pass them around
|
|
|
|
|
/// when monomorphizing.
|
|
|
|
|
pub args: GenericArgsRef<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Struct returned by `split()`.
|
|
|
|
|
pub struct ClosureArgsParts<'tcx> {
|
|
|
|
|
/// This is the args of the typeck root.
|
|
|
|
|
pub parent_args: &'tcx [GenericArg<'tcx>],
|
|
|
|
|
/// Represents the maximum calling capability of the closure.
|
|
|
|
|
pub closure_kind_ty: Ty<'tcx>,
|
|
|
|
|
/// Captures the closure's signature. This closure signature is "tupled", and
|
|
|
|
|
/// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`.
|
|
|
|
|
pub closure_sig_as_fn_ptr_ty: Ty<'tcx>,
|
|
|
|
|
/// The upvars captured by the closure. Remains an inference variable
|
|
|
|
|
/// until the upvar analysis, which happens late in HIR typeck.
|
|
|
|
|
pub tupled_upvars_ty: Ty<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> ClosureArgs<'tcx> {
|
|
|
|
|
/// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args`
|
|
|
|
|
/// for the closure parent, alongside additional closure-specific components.
|
|
|
|
|
pub fn new(tcx: TyCtxt<'tcx>, parts: ClosureArgsParts<'tcx>) -> ClosureArgs<'tcx> {
|
|
|
|
|
ClosureArgs {
|
|
|
|
|
args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
|
|
|
|
|
parts.closure_kind_ty.into(),
|
|
|
|
|
parts.closure_sig_as_fn_ptr_ty.into(),
|
|
|
|
|
parts.tupled_upvars_ty.into(),
|
|
|
|
|
])),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Divides the closure args into their respective components.
|
|
|
|
|
/// The ordering assumed here must match that used by `ClosureArgs::new` above.
|
|
|
|
|
fn split(self) -> ClosureArgsParts<'tcx> {
|
|
|
|
|
match self.args[..] {
|
|
|
|
|
[ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
|
|
|
|
|
ClosureArgsParts {
|
|
|
|
|
parent_args,
|
|
|
|
|
closure_kind_ty: closure_kind_ty.expect_ty(),
|
|
|
|
|
closure_sig_as_fn_ptr_ty: closure_sig_as_fn_ptr_ty.expect_ty(),
|
|
|
|
|
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => bug!("closure args missing synthetics"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the generic parameters of the closure's parent.
|
|
|
|
|
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
|
|
|
|
self.split().parent_args
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns an iterator over the list of types of captured paths by the closure.
|
|
|
|
|
/// In case there was a type error in figuring out the types of the captured path, an
|
|
|
|
|
/// empty iterator is returned.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
|
|
|
|
|
match *self.tupled_upvars_ty().kind() {
|
|
|
|
|
TyKind::Error(_) => ty::List::empty(),
|
|
|
|
|
TyKind::Tuple(tys) => tys,
|
|
|
|
|
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
|
|
|
|
|
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the tuple type representing the upvars for this closure.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().tupled_upvars_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the closure kind for this closure; may return a type
|
|
|
|
|
/// variable during inference. To get the closure kind during
|
|
|
|
|
/// inference, use `infcx.closure_kind(args)`.
|
|
|
|
|
pub fn kind_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().closure_kind_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the `fn` pointer type representing the closure signature for this
|
|
|
|
|
/// closure.
|
|
|
|
|
// FIXME(eddyb) this should be unnecessary, as the shallowly resolved
|
|
|
|
|
// type is known at the time of the creation of `ClosureArgs`,
|
|
|
|
|
// see `rustc_hir_analysis::check::closure`.
|
|
|
|
|
pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().closure_sig_as_fn_ptr_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the closure kind for this closure; only usable outside
|
|
|
|
|
/// of an inference context, because in that context we know that
|
|
|
|
|
/// there are no type variables.
|
|
|
|
|
///
|
|
|
|
|
/// If you have an inference context, use `infcx.closure_kind()`.
|
|
|
|
|
pub fn kind(self) -> ty::ClosureKind {
|
|
|
|
|
self.kind_ty().to_opt_closure_kind().unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Extracts the signature from the closure.
|
|
|
|
|
pub fn sig(self) -> ty::PolyFnSig<'tcx> {
|
|
|
|
|
match *self.sig_as_fn_ptr_ty().kind() {
|
|
|
|
|
ty::FnPtr(sig) => sig,
|
|
|
|
|
ty => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn print_as_impl_trait(self) -> ty::print::PrintClosureAsImpl<'tcx> {
|
|
|
|
|
ty::print::PrintClosureAsImpl { closure: self }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
|
|
|
|
|
pub struct CoroutineClosureArgs<'tcx> {
|
|
|
|
|
pub args: GenericArgsRef<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// See docs for explanation of how each argument is used.
|
|
|
|
|
///
|
|
|
|
|
/// See [`CoroutineClosureSignature`] for how these arguments are put together
|
|
|
|
|
/// to make a callable [`FnSig`] suitable for typeck and borrowck.
|
|
|
|
|
pub struct CoroutineClosureArgsParts<'tcx> {
|
|
|
|
|
/// This is the args of the typeck root.
|
|
|
|
|
pub parent_args: &'tcx [GenericArg<'tcx>],
|
|
|
|
|
/// Represents the maximum calling capability of the closure.
|
|
|
|
|
pub closure_kind_ty: Ty<'tcx>,
|
|
|
|
|
/// Represents all of the relevant parts of the coroutine returned by this
|
|
|
|
|
/// coroutine-closure. This signature parts type will have the general
|
|
|
|
|
/// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where
|
|
|
|
|
/// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the
|
|
|
|
|
/// coroutine returned by the coroutine-closure.
|
|
|
|
|
///
|
|
|
|
|
/// Use `coroutine_closure_sig` to break up this type rather than using it
|
|
|
|
|
/// yourself.
|
|
|
|
|
pub signature_parts_ty: Ty<'tcx>,
|
|
|
|
|
/// The upvars captured by the closure. Remains an inference variable
|
|
|
|
|
/// until the upvar analysis, which happens late in HIR typeck.
|
|
|
|
|
pub tupled_upvars_ty: Ty<'tcx>,
|
|
|
|
|
/// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`.
|
|
|
|
|
/// This allows us to represent the binder of the self-captures of the closure.
|
|
|
|
|
///
|
|
|
|
|
/// For example, if the coroutine returned by the closure borrows `String`
|
|
|
|
|
/// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`,
|
|
|
|
|
/// while the `tupled_upvars_ty`, representing the by-move version of the same
|
|
|
|
|
/// captures, will be `(String,)`.
|
|
|
|
|
pub coroutine_captures_by_ref_ty: Ty<'tcx>,
|
|
|
|
|
/// Witness type returned by the generator produced by this coroutine-closure.
|
|
|
|
|
pub coroutine_witness_ty: Ty<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> CoroutineClosureArgs<'tcx> {
|
|
|
|
|
pub fn new(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
parts: CoroutineClosureArgsParts<'tcx>,
|
|
|
|
|
) -> CoroutineClosureArgs<'tcx> {
|
|
|
|
|
CoroutineClosureArgs {
|
|
|
|
|
args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
|
|
|
|
|
parts.closure_kind_ty.into(),
|
|
|
|
|
parts.signature_parts_ty.into(),
|
|
|
|
|
parts.tupled_upvars_ty.into(),
|
|
|
|
|
parts.coroutine_captures_by_ref_ty.into(),
|
|
|
|
|
parts.coroutine_witness_ty.into(),
|
|
|
|
|
])),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn split(self) -> CoroutineClosureArgsParts<'tcx> {
|
|
|
|
|
match self.args[..] {
|
|
|
|
|
[
|
|
|
|
|
ref parent_args @ ..,
|
|
|
|
|
closure_kind_ty,
|
|
|
|
|
signature_parts_ty,
|
|
|
|
|
tupled_upvars_ty,
|
|
|
|
|
coroutine_captures_by_ref_ty,
|
|
|
|
|
coroutine_witness_ty,
|
|
|
|
|
] => CoroutineClosureArgsParts {
|
|
|
|
|
parent_args,
|
|
|
|
|
closure_kind_ty: closure_kind_ty.expect_ty(),
|
|
|
|
|
signature_parts_ty: signature_parts_ty.expect_ty(),
|
|
|
|
|
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
|
|
|
|
|
coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(),
|
|
|
|
|
coroutine_witness_ty: coroutine_witness_ty.expect_ty(),
|
|
|
|
|
},
|
|
|
|
|
_ => bug!("closure args missing synthetics"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
|
|
|
|
self.split().parent_args
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
|
|
|
|
|
match self.tupled_upvars_ty().kind() {
|
|
|
|
|
TyKind::Error(_) => ty::List::empty(),
|
|
|
|
|
TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
|
|
|
|
|
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
|
|
|
|
|
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().tupled_upvars_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn kind_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().closure_kind_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn kind(self) -> ty::ClosureKind {
|
|
|
|
|
self.kind_ty().to_opt_closure_kind().unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn signature_parts_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().signature_parts_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn coroutine_closure_sig(self) -> Binder<'tcx, CoroutineClosureSignature<'tcx>> {
|
|
|
|
|
let interior = self.coroutine_witness_ty();
|
|
|
|
|
let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { bug!() };
|
|
|
|
|
sig.map_bound(|sig| {
|
|
|
|
|
let [resume_ty, tupled_inputs_ty] = *sig.inputs() else {
|
|
|
|
|
bug!();
|
|
|
|
|
};
|
|
|
|
|
let [yield_ty, return_ty] = **sig.output().tuple_fields() else { bug!() };
|
|
|
|
|
CoroutineClosureSignature {
|
|
|
|
|
interior,
|
|
|
|
|
tupled_inputs_ty,
|
|
|
|
|
resume_ty,
|
|
|
|
|
yield_ty,
|
|
|
|
|
return_ty,
|
|
|
|
|
c_variadic: sig.c_variadic,
|
|
|
|
|
safety: sig.safety,
|
|
|
|
|
abi: sig.abi,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn coroutine_captures_by_ref_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().coroutine_captures_by_ref_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn coroutine_witness_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().coroutine_witness_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn has_self_borrows(&self) -> bool {
|
|
|
|
|
match self.coroutine_captures_by_ref_ty().kind() {
|
|
|
|
|
ty::FnPtr(sig) => sig
|
|
|
|
|
.skip_binder()
|
|
|
|
|
.visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
|
|
|
|
|
.is_break(),
|
|
|
|
|
ty::Error(_) => true,
|
|
|
|
|
_ => bug!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will
|
|
|
|
|
/// detect only regions bound *at* the debruijn index.
|
|
|
|
|
struct HasRegionsBoundAt {
|
|
|
|
|
binder: ty::DebruijnIndex,
|
|
|
|
|
}
|
|
|
|
|
// FIXME: Could be optimized to not walk into components with no escaping bound vars.
|
|
|
|
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRegionsBoundAt {
|
|
|
|
|
type Result = ControlFlow<()>;
|
|
|
|
|
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
t: &ty::Binder<'tcx, T>,
|
|
|
|
|
) -> Self::Result {
|
|
|
|
|
self.binder.shift_in(1);
|
|
|
|
|
t.super_visit_with(self)?;
|
|
|
|
|
self.binder.shift_out(1);
|
|
|
|
|
ControlFlow::Continue(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
|
|
|
|
|
if let ty::ReBound(binder, _) = *r
|
|
|
|
|
&& self.binder == binder
|
|
|
|
|
{
|
|
|
|
|
ControlFlow::Break(())
|
|
|
|
|
} else {
|
|
|
|
|
ControlFlow::Continue(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
|
|
|
|
|
pub struct CoroutineClosureSignature<'tcx> {
|
|
|
|
|
pub interior: Ty<'tcx>,
|
|
|
|
|
pub tupled_inputs_ty: Ty<'tcx>,
|
|
|
|
|
pub resume_ty: Ty<'tcx>,
|
|
|
|
|
pub yield_ty: Ty<'tcx>,
|
|
|
|
|
pub return_ty: Ty<'tcx>,
|
|
|
|
|
|
|
|
|
|
// Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types
|
|
|
|
|
// never actually differ. But we save them rather than recreating them
|
|
|
|
|
// from scratch just for good measure.
|
|
|
|
|
/// Always false
|
|
|
|
|
pub c_variadic: bool,
|
|
|
|
|
/// Always [`hir::Safety::Safe`]
|
|
|
|
|
pub safety: hir::Safety,
|
|
|
|
|
/// Always [`abi::Abi::RustCall`]
|
|
|
|
|
pub abi: abi::Abi,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> CoroutineClosureSignature<'tcx> {
|
|
|
|
|
/// Construct a coroutine from the closure signature. Since a coroutine signature
|
|
|
|
|
/// is agnostic to the type of generator that is returned (by-ref/by-move),
|
|
|
|
|
/// the caller must specify what "flavor" of generator that they'd like to
|
|
|
|
|
/// create. Additionally, they must manually compute the upvars of the closure.
|
|
|
|
|
///
|
|
|
|
|
/// This helper is not really meant to be used directly except for early on
|
|
|
|
|
/// during typeck, when we want to put inference vars into the kind and upvars tys.
|
|
|
|
|
/// When the kind and upvars are known, use the other helper functions.
|
|
|
|
|
pub fn to_coroutine(
|
|
|
|
|
self,
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
parent_args: &'tcx [GenericArg<'tcx>],
|
|
|
|
|
coroutine_kind_ty: Ty<'tcx>,
|
|
|
|
|
coroutine_def_id: DefId,
|
|
|
|
|
tupled_upvars_ty: Ty<'tcx>,
|
|
|
|
|
) -> Ty<'tcx> {
|
|
|
|
|
let coroutine_args = ty::CoroutineArgs::new(
|
|
|
|
|
tcx,
|
|
|
|
|
ty::CoroutineArgsParts {
|
|
|
|
|
parent_args,
|
|
|
|
|
kind_ty: coroutine_kind_ty,
|
|
|
|
|
resume_ty: self.resume_ty,
|
|
|
|
|
yield_ty: self.yield_ty,
|
|
|
|
|
return_ty: self.return_ty,
|
|
|
|
|
witness: self.interior,
|
|
|
|
|
tupled_upvars_ty,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine
|
|
|
|
|
/// returned by that corresponding async fn trait.
|
|
|
|
|
///
|
|
|
|
|
/// This function expects the upvars to have been computed already, and doesn't check
|
|
|
|
|
/// that the `ClosureKind` is actually supported by the coroutine-closure.
|
|
|
|
|
pub fn to_coroutine_given_kind_and_upvars(
|
|
|
|
|
self,
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
parent_args: &'tcx [GenericArg<'tcx>],
|
|
|
|
|
coroutine_def_id: DefId,
|
|
|
|
|
goal_kind: ty::ClosureKind,
|
|
|
|
|
env_region: ty::Region<'tcx>,
|
|
|
|
|
closure_tupled_upvars_ty: Ty<'tcx>,
|
|
|
|
|
coroutine_captures_by_ref_ty: Ty<'tcx>,
|
|
|
|
|
) -> Ty<'tcx> {
|
|
|
|
|
let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind(
|
|
|
|
|
tcx,
|
|
|
|
|
goal_kind,
|
|
|
|
|
self.tupled_inputs_ty,
|
|
|
|
|
closure_tupled_upvars_ty,
|
|
|
|
|
coroutine_captures_by_ref_ty,
|
|
|
|
|
env_region,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
self.to_coroutine(
|
|
|
|
|
tcx,
|
|
|
|
|
parent_args,
|
|
|
|
|
Ty::from_coroutine_closure_kind(tcx, goal_kind),
|
|
|
|
|
coroutine_def_id,
|
|
|
|
|
tupled_upvars_ty,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Compute the tupled upvars that a coroutine-closure's output coroutine
|
|
|
|
|
/// would return for the given `ClosureKind`.
|
|
|
|
|
///
|
|
|
|
|
/// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref"
|
|
|
|
|
/// to return a set of upvars which are borrowed with the given `env_region`.
|
|
|
|
|
///
|
|
|
|
|
/// This ensures that the `AsyncFn::call` will return a coroutine whose upvars'
|
|
|
|
|
/// lifetimes are related to the lifetime of the borrow on the closure made for
|
|
|
|
|
/// the call. This allows borrowck to enforce the self-borrows correctly.
|
|
|
|
|
pub fn tupled_upvars_by_closure_kind(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
kind: ty::ClosureKind,
|
|
|
|
|
tupled_inputs_ty: Ty<'tcx>,
|
|
|
|
|
closure_tupled_upvars_ty: Ty<'tcx>,
|
|
|
|
|
coroutine_captures_by_ref_ty: Ty<'tcx>,
|
|
|
|
|
env_region: ty::Region<'tcx>,
|
|
|
|
|
) -> Ty<'tcx> {
|
|
|
|
|
match kind {
|
|
|
|
|
ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
|
|
|
|
|
let ty::FnPtr(sig) = *coroutine_captures_by_ref_ty.kind() else {
|
|
|
|
|
bug!();
|
|
|
|
|
};
|
|
|
|
|
let coroutine_captures_by_ref_ty = tcx.replace_escaping_bound_vars_uncached(
|
|
|
|
|
sig.output().skip_binder(),
|
|
|
|
|
FnMutDelegate {
|
|
|
|
|
consts: &mut |c, t| ty::Const::new_bound(tcx, ty::INNERMOST, c, t),
|
|
|
|
|
types: &mut |t| Ty::new_bound(tcx, ty::INNERMOST, t),
|
|
|
|
|
regions: &mut |_| env_region,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
Ty::new_tup_from_iter(
|
|
|
|
|
tcx,
|
|
|
|
|
tupled_inputs_ty
|
|
|
|
|
.tuple_fields()
|
|
|
|
|
.iter()
|
|
|
|
|
.chain(coroutine_captures_by_ref_ty.tuple_fields()),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
ty::ClosureKind::FnOnce => Ty::new_tup_from_iter(
|
|
|
|
|
tcx,
|
|
|
|
|
tupled_inputs_ty
|
|
|
|
|
.tuple_fields()
|
|
|
|
|
.iter()
|
|
|
|
|
.chain(closure_tupled_upvars_ty.tuple_fields()),
|
|
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// Similar to `ClosureArgs`; see the above documentation for more.
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
|
|
|
|
|
pub struct CoroutineArgs<'tcx> {
|
|
|
|
|
pub args: GenericArgsRef<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct CoroutineArgsParts<'tcx> {
|
|
|
|
|
/// This is the args of the typeck root.
|
|
|
|
|
pub parent_args: &'tcx [GenericArg<'tcx>],
|
|
|
|
|
|
|
|
|
|
/// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut`
|
|
|
|
|
/// implementations must be distinguished since the former takes the closure's
|
|
|
|
|
/// upvars by move, and the latter takes the closure's upvars by ref.
|
|
|
|
|
///
|
|
|
|
|
/// This field distinguishes these fields so that codegen can select the right
|
|
|
|
|
/// body for the coroutine. This has the same type representation as the closure
|
|
|
|
|
/// kind: `i8`/`i16`/`i32`.
|
|
|
|
|
///
|
|
|
|
|
/// For regular coroutines, this field will always just be `()`.
|
|
|
|
|
pub kind_ty: Ty<'tcx>,
|
|
|
|
|
|
|
|
|
|
pub resume_ty: Ty<'tcx>,
|
|
|
|
|
pub yield_ty: Ty<'tcx>,
|
|
|
|
|
pub return_ty: Ty<'tcx>,
|
|
|
|
|
|
|
|
|
|
/// The interior type of the coroutine.
|
|
|
|
|
/// Represents all types that are stored in locals
|
|
|
|
|
/// in the coroutine's body.
|
|
|
|
|
pub witness: Ty<'tcx>,
|
|
|
|
|
|
|
|
|
|
/// The upvars captured by the closure. Remains an inference variable
|
|
|
|
|
/// until the upvar analysis, which happens late in HIR typeck.
|
|
|
|
|
pub tupled_upvars_ty: Ty<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
/// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
|
|
|
|
|
/// for the coroutine parent, alongside additional coroutine-specific components.
|
|
|
|
|
pub fn new(tcx: TyCtxt<'tcx>, parts: CoroutineArgsParts<'tcx>) -> CoroutineArgs<'tcx> {
|
|
|
|
|
CoroutineArgs {
|
|
|
|
|
args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
|
|
|
|
|
parts.kind_ty.into(),
|
|
|
|
|
parts.resume_ty.into(),
|
|
|
|
|
parts.yield_ty.into(),
|
|
|
|
|
parts.return_ty.into(),
|
|
|
|
|
parts.witness.into(),
|
|
|
|
|
parts.tupled_upvars_ty.into(),
|
|
|
|
|
])),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Divides the coroutine args into their respective components.
|
|
|
|
|
/// The ordering assumed here must match that used by `CoroutineArgs::new` above.
|
|
|
|
|
fn split(self) -> CoroutineArgsParts<'tcx> {
|
|
|
|
|
match self.args[..] {
|
|
|
|
|
[
|
|
|
|
|
ref parent_args @ ..,
|
|
|
|
|
kind_ty,
|
|
|
|
|
resume_ty,
|
|
|
|
|
yield_ty,
|
|
|
|
|
return_ty,
|
|
|
|
|
witness,
|
|
|
|
|
tupled_upvars_ty,
|
|
|
|
|
] => CoroutineArgsParts {
|
|
|
|
|
parent_args,
|
|
|
|
|
kind_ty: kind_ty.expect_ty(),
|
|
|
|
|
resume_ty: resume_ty.expect_ty(),
|
|
|
|
|
yield_ty: yield_ty.expect_ty(),
|
|
|
|
|
return_ty: return_ty.expect_ty(),
|
|
|
|
|
witness: witness.expect_ty(),
|
|
|
|
|
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
|
|
|
|
|
},
|
|
|
|
|
_ => bug!("coroutine args missing synthetics"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the generic parameters of the coroutine's parent.
|
|
|
|
|
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
|
|
|
|
self.split().parent_args
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the kind of the coroutine. See docs on the `kind_ty` field.
|
|
|
|
|
pub fn kind_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().kind_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// This describes the types that can be contained in a coroutine.
|
|
|
|
|
/// It will be a type variable initially and unified in the last stages of typeck of a body.
|
|
|
|
|
/// It contains a tuple of all the types that could end up on a coroutine frame.
|
|
|
|
|
/// The state transformation MIR pass may only produce layouts which mention types
|
|
|
|
|
/// in this tuple. Upvars are not counted here.
|
|
|
|
|
pub fn witness(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().witness
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns an iterator over the list of types of captured paths by the coroutine.
|
|
|
|
|
/// In case there was a type error in figuring out the types of the captured path, an
|
|
|
|
|
/// empty iterator is returned.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
|
|
|
|
|
match *self.tupled_upvars_ty().kind() {
|
|
|
|
|
TyKind::Error(_) => ty::List::empty(),
|
|
|
|
|
TyKind::Tuple(tys) => tys,
|
|
|
|
|
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
|
|
|
|
|
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the tuple type representing the upvars for this coroutine.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().tupled_upvars_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the type representing the resume type of the coroutine.
|
|
|
|
|
pub fn resume_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().resume_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the type representing the yield type of the coroutine.
|
|
|
|
|
pub fn yield_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().yield_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the type representing the return type of the coroutine.
|
|
|
|
|
pub fn return_ty(self) -> Ty<'tcx> {
|
|
|
|
|
self.split().return_ty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the "coroutine signature", which consists of its resume, yield
|
|
|
|
|
/// and return types.
|
|
|
|
|
pub fn sig(self) -> GenSig<'tcx> {
|
|
|
|
|
let parts = self.split();
|
|
|
|
|
ty::GenSig {
|
|
|
|
|
resume_ty: parts.resume_ty,
|
|
|
|
|
yield_ty: parts.yield_ty,
|
|
|
|
|
return_ty: parts.return_ty,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
#[extension(pub trait CoroutineArgsExt<'tcx>)]
|
|
|
|
|
impl<'tcx> ty::CoroutineArgs<TyCtxt<'tcx>> {
|
|
|
|
|
/// Coroutine has not been resumed yet.
|
|
|
|
|
pub const UNRESUMED: usize = 0;
|
|
|
|
|
const UNRESUMED: usize = 0;
|
|
|
|
|
/// Coroutine has returned or is completed.
|
|
|
|
|
pub const RETURNED: usize = 1;
|
|
|
|
|
const RETURNED: usize = 1;
|
|
|
|
|
/// Coroutine has been poisoned.
|
|
|
|
|
pub const POISONED: usize = 2;
|
|
|
|
|
const POISONED: usize = 2;
|
|
|
|
|
|
|
|
|
|
const UNRESUMED_NAME: &'static str = "Unresumed";
|
|
|
|
|
const RETURNED_NAME: &'static str = "Returned";
|
|
|
|
@ -731,7 +74,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
|
|
|
|
|
/// The valid variant indices of this coroutine.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
|
|
|
|
|
fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
|
|
|
|
|
// FIXME requires optimized MIR
|
|
|
|
|
FIRST_VARIANT
|
|
|
|
|
..tcx.coroutine_layout(def_id, tcx.types.unit).unwrap().variant_fields.next_index()
|
|
|
|
@ -740,7 +83,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
/// The discriminant for the given variant. Panics if the `variant_index` is
|
|
|
|
|
/// out of range.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn discriminant_for_variant(
|
|
|
|
|
fn discriminant_for_variant(
|
|
|
|
|
&self,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
@ -755,7 +98,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
/// The set of all discriminants for the coroutine, enumerated with their
|
|
|
|
|
/// variant indices.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn discriminants(
|
|
|
|
|
fn discriminants(
|
|
|
|
|
self,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
@ -767,7 +110,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
|
|
|
|
|
/// Calls `f` with a reference to the name of the enumerator for the given
|
|
|
|
|
/// variant `v`.
|
|
|
|
|
pub fn variant_name(v: VariantIdx) -> Cow<'static, str> {
|
|
|
|
|
fn variant_name(v: VariantIdx) -> Cow<'static, str> {
|
|
|
|
|
match v.as_usize() {
|
|
|
|
|
Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME),
|
|
|
|
|
Self::RETURNED => Cow::from(Self::RETURNED_NAME),
|
|
|
|
@ -778,7 +121,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
|
|
|
|
|
/// The type of the state discriminant used in the coroutine type.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
|
|
|
|
fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
|
|
|
|
tcx.types.u32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -789,7 +132,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
/// The locals are grouped by their variant number. Note that some locals may
|
|
|
|
|
/// be repeated in multiple variants.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn state_tys(
|
|
|
|
|
fn state_tys(
|
|
|
|
|
self,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
@ -805,7 +148,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|
|
|
|
/// This is the types of the fields of a coroutine which are not stored in a
|
|
|
|
|
/// variant.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
|
|
|
|
|
fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
|
|
|
|
|
self.upvar_tys()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -859,7 +202,7 @@ impl<'tcx> UpvarArgs<'tcx> {
|
|
|
|
|
///
|
|
|
|
|
/// When the inline const is instantiated, `R` is instantiated as the actual inferred
|
|
|
|
|
/// type of the constant. The reason that `R` is represented as an extra type parameter
|
|
|
|
|
/// is the same reason that [`ClosureArgs`] have `CS` and `U` as type parameters:
|
|
|
|
|
/// is the same reason that [`ty::ClosureArgs`] have `CS` and `U` as type parameters:
|
|
|
|
|
/// inline const can reference lifetimes that are internal to the creating function.
|
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
|
pub struct InlineConstArgs<'tcx> {
|
|
|
|
@ -938,13 +281,6 @@ impl BoundVariableKind {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
|
|
|
|
|
pub struct GenSig<'tcx> {
|
|
|
|
|
pub resume_ty: Ty<'tcx>,
|
|
|
|
|
pub yield_ty: Ty<'tcx>,
|
|
|
|
|
pub return_ty: Ty<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
|
|
|
|
|
pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>;
|
|
|
|
|
|
|
|
|
@ -1451,6 +787,41 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
|
|
|
|
|
) -> Self {
|
|
|
|
|
Ty::new_alias(interner, kind, alias_ty)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_coroutine(
|
|
|
|
|
interner: TyCtxt<'tcx>,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
args: ty::GenericArgsRef<'tcx>,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Ty::new_coroutine(interner, def_id, args)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_tup_from_iter<It, T>(interner: TyCtxt<'tcx>, iter: It) -> T::Output
|
|
|
|
|
where
|
|
|
|
|
It: Iterator<Item = T>,
|
|
|
|
|
T: CollectAndApply<Self, Self>,
|
|
|
|
|
{
|
|
|
|
|
Ty::new_tup_from_iter(interner, iter)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn tuple_fields(self) -> &'tcx ty::List<Ty<'tcx>> {
|
|
|
|
|
self.tuple_fields()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
|
|
|
|
|
self.to_opt_closure_kind()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn from_closure_kind(interner: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Self {
|
|
|
|
|
Ty::from_closure_kind(interner, kind)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn from_coroutine_closure_kind(
|
|
|
|
|
interner: TyCtxt<'tcx>,
|
|
|
|
|
kind: rustc_type_ir::ClosureKind,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Ty::from_coroutine_closure_kind(interner, kind)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Type utilities
|
|
|
|
@ -2169,8 +1540,8 @@ impl<'tcx> Ty<'tcx> {
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// After upvar analysis, you should instead use [`ClosureArgs::kind()`]
|
|
|
|
|
/// or [`CoroutineClosureArgs::kind()`] to assert that the `ClosureKind`
|
|
|
|
|
/// After upvar analysis, you should instead use [`ty::ClosureArgs::kind()`]
|
|
|
|
|
/// or [`ty::CoroutineClosureArgs::kind()`] to assert that the `ClosureKind`
|
|
|
|
|
/// has been constrained instead of manually calling this method.
|
|
|
|
|
///
|
|
|
|
|
/// ```rust,ignore (snippet of compiler code)
|
|
|
|
|