Enum hir::mir::TerminatorKind

pub enum TerminatorKind {
Show 14 variants Goto { target: Idx<BasicBlock>, }, SwitchInt { discr: Operand, targets: SwitchTargets, }, UnwindResume, Abort, Return, Unreachable, Drop { place: Place, target: Idx<BasicBlock>, unwind: Option<Idx<BasicBlock>>, }, DropAndReplace { place: Place, value: Operand, target: Idx<BasicBlock>, unwind: Option<Idx<BasicBlock>>, }, Call { func: Operand, args: Box<[Operand]>, destination: Place, target: Option<Idx<BasicBlock>>, cleanup: Option<Idx<BasicBlock>>, from_hir_call: bool, }, Assert { cond: Operand, expected: bool, target: Idx<BasicBlock>, cleanup: Option<Idx<BasicBlock>>, }, Yield { value: Operand, resume: Idx<BasicBlock>, resume_arg: Place, drop: Option<Idx<BasicBlock>>, }, CoroutineDrop, FalseEdge { real_target: Idx<BasicBlock>, imaginary_target: Idx<BasicBlock>, }, FalseUnwind { real_target: Idx<BasicBlock>, unwind: Option<Idx<BasicBlock>>, },
}

Variants§

§

Goto

Block has one successor; we continue execution there.

Fields

§target: Idx<BasicBlock>
§

SwitchInt

Switches based on the computed value.

First, evaluates the discr operand. The type of the operand must be a signed or unsigned integer, char, or bool, and must match the given type. Then, if the list of switch targets contains the computed value, continues execution at the associated basic block. Otherwise, continues execution at the “otherwise” basic block.

Target values may not appear more than once.

Fields

§discr: Operand

The discriminant value being tested.

§

UnwindResume

Indicates that the landing pad is finished and that the process should continue unwinding.

Like a return, this marks the end of this invocation of the function.

Only permitted in cleanup blocks. Resume is not permitted with -C unwind=abort after deaggregation runs.

§

Abort

Indicates that the landing pad is finished and that the process should abort.

Used to prevent unwinding for foreign items or with -C unwind=abort. Only permitted in cleanup blocks.

§

Return

Returns from the function.

Like function calls, the exact semantics of returns in Rust are unclear. Returning very likely at least assigns the value currently in the return place (_0) to the place specified in the associated Call terminator in the calling function, as if assigned via dest = move _0. It might additionally do other things, like have side-effects in the aliasing model.

If the body is a coroutine body, this has slightly different semantics; it instead causes a CoroutineState::Returned(_0) to be created (as if by an Aggregate rvalue) and assigned to the return place.

§

Unreachable

Indicates a terminator that can never be reached.

Executing this terminator is UB.

§

Drop

The behavior of this statement differs significantly before and after drop elaboration. After drop elaboration, Drop executes the drop glue for the specified place, after which it continues execution/unwinds at the given basic blocks. It is possible that executing drop glue is special - this would be part of Rust’s memory model. (FIXME: due we have an issue tracking if drop glue has any interesting semantics in addition to those of a function call?)

Drop before drop elaboration is a conditional execution of the drop glue. Specifically, the Drop will be executed if…

Needs clarification: End of that sentence. This in effect should document the exact behavior of drop elaboration. The following sounds vaguely right, but I’m not quite sure:

The drop glue is executed if, among all statements executed within this Body, an assignment to the place or one of its “parents” occurred more recently than a move out of it. This does not consider indirect assignments.

Fields

§place: Place
§target: Idx<BasicBlock>
§unwind: Option<Idx<BasicBlock>>
§

DropAndReplace

Drops the place and assigns a new value to it.

This first performs the exact same operation as the pre drop-elaboration Drop terminator; it then additionally assigns the value to the place as if by an assignment statement. This assignment occurs both in the unwind and the regular code paths. The semantics are best explained by the elaboration:

BB0 {
  DropAndReplace(P <- V, goto BB1, unwind BB2)
}

becomes

BB0 {
  Drop(P, goto BB1, unwind BB2)
}
BB1 {
  // P is now uninitialized
  P <- V
}
BB2 {
  // P is now uninitialized -- its dtor panicked
  P <- V
}

Disallowed after drop elaboration.

Fields

§place: Place
§value: Operand
§target: Idx<BasicBlock>
§unwind: Option<Idx<BasicBlock>>
§

Call

Roughly speaking, evaluates the func operand and the arguments, and starts execution of the referred to function. The operand types must match the argument types of the function. The return place type must match the return type. The type of the func operand must be callable, meaning either a function pointer, a function type, or a closure type.

Needs clarification: The exact semantics of this. Current backends rely on move operands not aliasing the return place. It is unclear how this is justified in MIR, see #71117.

Fields

§func: Operand

The function that’s being called.

§args: Box<[Operand]>

Arguments the function is called with. These are owned by the callee, which is free to modify them. This allows the memory occupied by “by-value” arguments to be reused across function calls without duplicating the contents.

§destination: Place

Where the returned value will be written

§target: Option<Idx<BasicBlock>>

Where to go after this call returns. If none, the call necessarily diverges.

§cleanup: Option<Idx<BasicBlock>>

Cleanups to be done if the call unwinds.

§from_hir_call: bool

true if this is from a call in HIR rather than from an overloaded operator. True for overloaded function call.

§

Assert

Evaluates the operand, which must have type bool. If it is not equal to expected, initiates a panic. Initiating a panic corresponds to a Call terminator with some unspecified constant as the function to call, all the operands stored in the AssertMessage as parameters, and None for the destination. Keep in mind that the cleanup path is not necessarily executed even in the case of a panic, for example in -C panic=abort. If the assertion does not fail, execution continues at the specified basic block.

Fields

§cond: Operand
§expected: bool
§target: Idx<BasicBlock>
§cleanup: Option<Idx<BasicBlock>>
§

Yield

Marks a suspend point.

Like Return terminators in coroutine bodies, this computes value and then a CoroutineState::Yielded(value) as if by Aggregate rvalue. That value is then assigned to the return place of the function calling this one, and execution continues in the calling function. When next invoked with the same first argument, execution of this function continues at the resume basic block, with the second argument written to the resume_arg place. If the coroutine is dropped before then, the drop basic block is invoked.

Not permitted in bodies that are not coroutine bodies, or after coroutine lowering.

Needs clarification: What about the evaluation order of the resume_arg and value?

Fields

§value: Operand

The value to return.

§resume: Idx<BasicBlock>

Where to resume to.

§resume_arg: Place

The place to store the resume argument in.

§drop: Option<Idx<BasicBlock>>

Cleanup to be done if the coroutine is dropped at this suspend point.

§

CoroutineDrop

Indicates the end of dropping a coroutine.

Semantically just a return (from the coroutines drop glue). Only permitted in the same situations as yield.

Needs clarification: Is that even correct? The coroutine drop code is always confusing to me, because it’s not even really in the current body.

Needs clarification: Are there type system constraints on these terminators? Should there be a “block type” like cleanup blocks for them?

§

FalseEdge

A block where control flow only ever takes one real path, but borrowck needs to be more conservative.

At runtime this is semantically just a goto.

Disallowed after drop elaboration.

Fields

§real_target: Idx<BasicBlock>

The target normal control flow will take.

§imaginary_target: Idx<BasicBlock>

A block control flow could conceptually jump to, but won’t in practice.

§

FalseUnwind

A terminator for blocks that only take one path in reality, but where we reserve the right to unwind in borrowck, even if it won’t happen in practice. This can arise in infinite loops with no function calls for example.

At runtime this is semantically just a goto.

Disallowed after drop elaboration.

Fields

§real_target: Idx<BasicBlock>

The target normal control flow will take.

§unwind: Option<Idx<BasicBlock>>

The imaginary cleanup block link. This particular path will never be taken in practice, but in order to avoid fragility we want to always consider it in borrowck. We don’t want to accept programs which pass borrowck only when panic=abort or some assertions are disabled due to release vs. debug mode builds. This needs to be an Option because of the remove_noop_landing_pads and abort_unwinding_calls passes.

Trait Implementations§

§

impl Clone for TerminatorKind

§

fn clone(&self) -> TerminatorKind

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for TerminatorKind

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl PartialEq for TerminatorKind

§

fn eq(&self, other: &TerminatorKind) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl Eq for TerminatorKind

§

impl StructuralPartialEq for TerminatorKind

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Cast for T

§

fn cast<U>(self, interner: <U as HasInterner>::Interner) -> U
where Self: CastTo<U>, U: HasInterner,

Cast a value to type U using CastTo.
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> IntoBox<dyn Any> for T
where T: Any,

§

fn into_box(self) -> Box<dyn Any>

Convert self into the appropriate boxed form.
§

impl<T> IntoBox<dyn Any + Send> for T
where T: Any + Send,

§

fn into_box(self) -> Box<dyn Any + Send>

Convert self into the appropriate boxed form.
§

impl<T> IntoBox<dyn Any + Sync + Send> for T
where T: Any + Send + Sync,

§

fn into_box(self) -> Box<dyn Any + Sync + Send>

Convert self into the appropriate boxed form.
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<T> ToOwned for T
where T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

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

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

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