Struct rustc::ty::ClosureSubsts
[−]
[src]
pub struct ClosureSubsts<'tcx> { pub substs: &'tcx Substs<'tcx>, }
rustc_private
)A closure can be modeled as a struct that looks like:
struct Closure<'l0...'li, T0...Tj, U0...Uk> { upvar0: U0, ... upvark: Uk }
where 'l0...'li and T0...Tj are the lifetime and type parameters in scope on the function that defined the closure, and U0...Uk are type parameters representing the types of its upvars (borrowed, if appropriate).
So, for example, given this function:
fn foo<'a, T>(data: &'a mut T) { do(|| data.count += 1) }
the type of the closure would be something like:
struct Closure<'a, T, U0> { data: U0 }
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:
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
as extra type parameters? 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 extent of the closure itself; this is some
subset of foo
, probably just the extent 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 trans 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
Fields
substs: &'tcx Substs<'tcx>
rustc_private
)Lifetime and type parameters from the enclosing function, concatenated with the types of the upvars.
These are separated out because trans wants to pass them around when monomorphizing.
Methods
impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx>
[src]
fn upvar_tys(self,
def_id: DefId,
tcx: TyCtxt<'a, 'gcx, 'acx>)
-> impl Iterator<Item=Ty<'tcx>> + 'tcx
def_id: DefId,
tcx: TyCtxt<'a, 'gcx, 'acx>)
-> impl Iterator<Item=Ty<'tcx>> + 'tcx
rustc_private
)Trait Implementations
impl<'gcx> TransNormalize<'gcx> for ClosureSubsts<'gcx>
[src]
fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self
rustc_private
)impl<'tcx> Relate<'tcx> for ClosureSubsts<'tcx>
[src]
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ClosureSubsts<'tcx>,
b: &ClosureSubsts<'tcx>)
-> RelateResult<'tcx, ClosureSubsts<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a + 'tcx, 'tcx: 'a
a: &ClosureSubsts<'tcx>,
b: &ClosureSubsts<'tcx>)
-> RelateResult<'tcx, ClosureSubsts<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a + 'tcx, 'tcx: 'a
rustc_private
)impl<'a, 'tcx> Lift<'tcx> for ClosureSubsts<'a>
[src]
type Lifted = ClosureSubsts<'tcx>
rustc_private
)fn lift_to_tcx<'b, 'gcx>(&self,
tcx: TyCtxt<'b, 'gcx, 'tcx>)
-> Option<Self::Lifted>
tcx: TyCtxt<'b, 'gcx, 'tcx>)
-> Option<Self::Lifted>
rustc_private
)impl<'tcx> TypeFoldable<'tcx> for ClosureSubsts<'tcx>
[src]
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self,
folder: &mut F)
-> Self
folder: &mut F)
-> Self
rustc_private
)fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool
rustc_private
)fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self,
folder: &mut F)
-> Self
folder: &mut F)
-> Self
rustc_private
)fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool
rustc_private
)fn has_regions_escaping_depth(&self, depth: u32) -> bool
rustc_private
)fn has_escaping_regions(&self) -> bool
rustc_private
)fn has_type_flags(&self, flags: TypeFlags) -> bool
rustc_private
)fn has_projection_types(&self) -> bool
rustc_private
)fn references_error(&self) -> bool
rustc_private
)fn has_param_types(&self) -> bool
rustc_private
)fn has_self_ty(&self) -> bool
rustc_private
)fn has_infer_types(&self) -> bool
rustc_private
)fn needs_infer(&self) -> bool
rustc_private
)fn needs_subst(&self) -> bool
rustc_private
)fn has_re_skol(&self) -> bool
rustc_private
)fn has_closure_types(&self) -> bool
rustc_private
)fn has_erasable_regions(&self) -> bool
rustc_private
)fn is_normalized_for_trans(&self) -> bool
rustc_private
)fn is_global(&self) -> bool
rustc_private
)Indicates whether this value references only 'global' types/lifetimes that are the same regardless of what fn we are in. This is used for caching. Errs on the side of returning false. Read more
impl<'tcx> Copy for ClosureSubsts<'tcx>
[src]
impl<'tcx> Clone for ClosureSubsts<'tcx>
[src]
fn clone(&self) -> ClosureSubsts<'tcx>
Returns a copy of the value. Read more
fn clone_from(&mut self, source: &Self)
1.0.0
Performs copy-assignment from source
. Read more
impl<'tcx> PartialEq for ClosureSubsts<'tcx>
[src]
fn eq(&self, __arg_0: &ClosureSubsts<'tcx>) -> bool
This method tests for self
and other
values to be equal, and is used by ==
. Read more
fn ne(&self, __arg_0: &ClosureSubsts<'tcx>) -> bool
This method tests for !=
.
impl<'tcx> Eq for ClosureSubsts<'tcx>
[src]
impl<'tcx> Hash for ClosureSubsts<'tcx>
[src]
fn hash<__H: Hasher>(&self, __arg_0: &mut __H)
Feeds this value into the state given, updating the hasher as necessary.
fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher
1.3.0
Feeds a slice of this type into the state provided.
impl<'tcx> Debug for ClosureSubsts<'tcx>
[src]
impl<'tcx> Encodable for ClosureSubsts<'tcx>
[src]
fn encode<__S: Encoder>(&self, __arg_0: &mut __S) -> Result<(), __S::Error>
🔬 This is a nightly-only experimental API. (rustc_private
)
deprecated in favor of rustc-serialize on crates.io
impl<'tcx> Decodable for ClosureSubsts<'tcx>
[src]
fn decode<__D: Decoder>(__arg_0: &mut __D)
-> Result<ClosureSubsts<'tcx>, __D::Error>
-> Result<ClosureSubsts<'tcx>, __D::Error>
🔬 This is a nightly-only experimental API. (rustc_private
)
deprecated in favor of rustc-serialize on crates.io