[][src]Struct rustc_middle::mir::LocalDecl

pub struct LocalDecl<'tcx> {
    pub mutability: Mutability,
    pub local_info: Option<Box<LocalInfo<'tcx>>>,
    pub internal: bool,
    pub is_block_tail: Option<BlockTailInfo>,
    pub ty: Ty<'tcx>,
    pub user_ty: Option<Box<UserTypeProjections>>,
    pub source_info: SourceInfo,
}

A MIR local.

This can be a binding declared by the user, a temporary inserted by the compiler, a function argument, or the return place.

Fields

mutability: Mutability

Whether this is a mutable binding (i.e., let x or let mut x).

Temporaries and the return place are always mutable.

local_info: Option<Box<LocalInfo<'tcx>>>internal: bool

true if this is an internal local.

These locals are not based on types in the source code and are only used for a few desugarings at the moment.

The generator transformation will sanity check the locals which are live across a suspension point against the type components of the generator which type checking knows are live across a suspension point. We need to flag drop flags to avoid triggering this check as they are introduced after typeck.

This should be sound because the drop flags are fully algebraic, and therefore don't affect the OIBIT or outlives properties of the generator.

is_block_tail: Option<BlockTailInfo>

If this local is a temporary and is_block_tail is Some, then it is a temporary created for evaluation of some subexpression of some block's tail expression (with no intervening statement context).

ty: Ty<'tcx>

The type of this local.

user_ty: Option<Box<UserTypeProjections>>

If the user manually ascribed a type to this variable, e.g., via let x: T, then we carry that type here. The MIR borrow checker needs this information since it can affect region inference.

source_info: SourceInfo

The syntactic (i.e., not visibility) source scope the local is defined in. If the local was defined in a let-statement, this is within the let-statement, rather than outside of it.

This is needed because the visibility source scope of locals within a let-statement is weird.

The reason is that we want the local to be within the let-statement for lint purposes, but we want the local to be after the let-statement for names-in-scope purposes.

That's it, if we have a let-statement like the one in this function:

fn foo(x: &str) {
    #[allow(unused_mut)]
    let mut x: u32 = { // <- one unused mut
        let mut y: u32 = x.parse().unwrap();
        y + 2
    };
    drop(x);
}

Then, from a lint point of view, the declaration of x: u32 (and y: u32) are within the #[allow(unused_mut)] scope - the lint scopes are the same as the AST/HIR nesting.

However, from a name lookup point of view, the scopes look more like as if the let-statements were match expressions:

fn foo(x: &str) {
    match {
        match x.parse().unwrap() {
            y => y + 2
        }
    } {
        x => drop(x)
    };
}

We care about the name-lookup scopes for debuginfo - if the debuginfo instruction pointer is at the call to x.parse(), we want x to refer to x: &str, but if it is at the call to drop(x), we want it to refer to x: u32.

To allow both uses to work, we need to have more than a single scope for a local. We have the source_info.scope represent the "syntactic" lint scope (with a variable being under its let block) while the var_debug_info.source_info.scope represents the "local variable" scope (where the "rest" of a block is under all prior let-statements).

The end result looks like this:

ROOT SCOPE
 │{ argument x: &str }
 │
 │ │{ #[allow(unused_mut)] } // This is actually split into 2 scopes
 │ │                         // in practice because I'm lazy.
 │ │
 │ │← x.source_info.scope
 │ │← `x.parse().unwrap()`
 │ │
 │ │ │← y.source_info.scope
 │ │
 │ │ │{ let y: u32 }
 │ │ │
 │ │ │← y.var_debug_info.source_info.scope
 │ │ │← `y + 2`
 │
 │ │{ let x: u32 }
 │ │← x.var_debug_info.source_info.scope
 │ │← `drop(x)` // This accesses `x: u32`.

Implementations

impl<'tcx> LocalDecl<'tcx>[src]

pub fn can_be_made_mutable(&self) -> bool[src]

Returns true only if local is a binding that can itself be made mutable via the addition of the mut keyword, namely something like the occurrences of x in:

  • fn foo(x: Type) { ... },
  • let x = ...,
  • or match ... { C(x) => ... }

pub fn is_nonref_binding(&self) -> bool[src]

Returns true if local is definitely not a ref ident or ref mut ident binding. (Such bindings cannot be made into mutable bindings, but the inverse does not necessarily hold).

pub fn is_user_variable(&self) -> bool[src]

Returns true if this variable is a named variable or function parameter declared by the user.

pub fn is_ref_for_guard(&self) -> bool[src]

Returns true if this is a reference to a variable bound in a match expression that is used to access said variable for the guard of the match arm.

pub fn is_ref_to_static(&self) -> bool[src]

Returns Some if this is a reference to a static item that is used to access that static.

pub fn is_ref_to_thread_local(&self) -> bool[src]

Returns Some if this is a reference to a thread-local static item that is used to access that static.

pub fn from_compiler_desugaring(&self) -> bool[src]

Returns true is the local is from a compiler desugaring, e.g., __next from a for loop.

pub fn new(ty: Ty<'tcx>, span: Span) -> Self[src]

Creates a new LocalDecl for a temporary: mutable, non-internal.

pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self[src]

Like LocalDecl::new, but takes a SourceInfo instead of a Span.

pub fn internal(self) -> Self[src]

Converts self into same LocalDecl except tagged as internal.

pub fn immutable(self) -> Self[src]

Converts self into same LocalDecl except tagged as immutable.

pub fn block_tail(self, info: BlockTailInfo) -> Self[src]

Converts self into same LocalDecl except tagged as internal temporary.

Trait Implementations

impl<'tcx> Clone for LocalDecl<'tcx>[src]

impl<'tcx> Debug for LocalDecl<'tcx>[src]

impl<'tcx, __D: TyDecoder<'tcx>> Decodable<__D> for LocalDecl<'tcx>[src]

impl<'tcx, __E: TyEncoder<'tcx>> Encodable<__E> for LocalDecl<'tcx>[src]

impl<'tcx, '__ctx> HashStable<StableHashingContext<'__ctx>> for LocalDecl<'tcx>[src]

impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx>[src]

Auto Trait Implementations

impl<'tcx> !RefUnwindSafe for LocalDecl<'tcx>

impl<'tcx> !Send for LocalDecl<'tcx>

impl<'tcx> !Sync for LocalDecl<'tcx>

impl<'tcx> Unpin for LocalDecl<'tcx>

impl<'tcx> !UnwindSafe for LocalDecl<'tcx>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<'a, T> Captures<'a> for T where
    T: ?Sized
[src]

impl<Ctxt, T> DepNodeParams<Ctxt> for T where
    Ctxt: DepContext,
    T: HashStable<<Ctxt as DepContext>::StableHashingContext> + Debug
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> MaybeResult<T> for T[src]

type Error = !

impl<'tcx, T> Subst<'tcx> for T where
    T: TypeFoldable<'tcx>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> WithConstness for T[src]