mir.rs - source
Description: Source of the Rust file `library/core/src/intrinsics/mir.rs`.

#
core/intrinsics/
mir.rs

    1//! Rustc internal tooling for hand-writing MIR.
    2//!
    3//! If for some reasons you are not writing rustc tests and have found yourself considering using
    4//! this feature, turn back. This is *exceptionally* unstable. There is no attempt at all to make
    5//! anything work besides those things which the rustc test suite happened to need. If you make a
    6//! typo you'll probably ICE. Really, this is not the solution to your problems. Consider instead
    7//! supporting the [stable MIR project group](https://github.com/rust-lang/project-stable-mir).
    8//!
    9//! The documentation for this module describes how to use this feature. If you are interested in
    10//! hacking on the implementation, most of that documentation lives at
    11//! `rustc_mir_build/src/build/custom/mod.rs`.
    12//!
    13//! Typical usage will look like this:
    14//!
    15//! ```rust
    16//! #![feature(core_intrinsics, custom_mir)]
    17//! #![allow(internal_features)]
    18//!
    19//! use core::intrinsics::mir::*;
    20//!
    21//! #[custom_mir(dialect = "built")]
    22//! pub fn simple(x: i32) -> i32 {
    23//!     mir! {
    24//!         let temp2: i32;
    25//!
    26//!         {
    27//!             let temp1 = x;
    28//!             Goto(my_second_block)
    29//!         }
    30//!
    31//!         my_second_block = {
    32//!             temp2 = Move(temp1);
    33//!             RET = temp2;
    34//!             Return()
    35//!         }
    36//!     }
    37//! }
    38//! ```
    39//!
    40//! The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
    41//! attribute only works on functions - there is no way to insert custom MIR into the middle of
    42//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
    43//! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
    44//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
    45//! "runtime", phase = "optimized")]` if you don't.
    46//!
    47//! [dialect docs]:
    48//!     https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
    49//!
    50//! The input to the [`mir!`] macro is:
    51//!
    52//!  - An optional return type annotation in the form of `type RET = ...;`. This may be required
    53//!    if the compiler cannot infer the type of RET.
    54//!  - A possibly empty list of local declarations. Locals can also be declared inline on
    55//!    assignments via `let`. Type inference generally works. Shadowing does not.
    56//!  - A list of basic blocks. The first of these is the start block and is where execution begins.
    57//!    All blocks other than the start block need to be given a name, so that they can be referred
    58//!    to later.
    59//!     - Each block is a list of semicolon terminated statements, followed by a terminator. The
    60//!       syntax for the various statements and terminators is designed to be as similar as possible
    61//!       to the syntax for analogous concepts in native Rust. See below for a list.
    62//!
    63//! # Examples
    64//!
    65//! ```rust
    66//! #![feature(core_intrinsics, custom_mir)]
    67//! #![allow(internal_features)]
    68//! #![allow(unused_assignments)]
    69//!
    70//! use core::intrinsics::mir::*;
    71//!
    72//! #[custom_mir(dialect = "built")]
    73//! pub fn choose_load(a: &i32, b: &i32, c: bool) -> i32 {
    74//!     mir! {
    75//!         {
    76//!             match c {
    77//!                 true => t,
    78//!                 _ => f,
    79//!             }
    80//!         }
    81//!
    82//!         t = {
    83//!             let temp = a;
    84//!             Goto(load_and_exit)
    85//!         }
    86//!
    87//!         f = {
    88//!             temp = b;
    89//!             Goto(load_and_exit)
    90//!         }
    91//!
    92//!         load_and_exit = {
    93//!             RET = *temp;
    94//!             Return()
    95//!         }
    96//!     }
    97//! }
    98//!
    99//! #[custom_mir(dialect = "built")]
    100//! fn unwrap_unchecked<T>(opt: Option<T>) -> T {
    101//!     mir! {
    102//!         {
    103//!             RET = Move(Field(Variant(opt, 1), 0));
    104//!             Return()
    105//!         }
    106//!     }
    107//! }
    108//!
    109//! #[custom_mir(dialect = "runtime", phase = "optimized")]
    110//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
    111//!     mir! {
    112//!         let _unused;
    113//!         let popped;
    114//!
    115//!         {
    116//!             Call(_unused = Vec::push(v, value), ReturnTo(pop), UnwindContinue())
    117//!         }
    118//!
    119//!         pop = {
    120//!             Call(popped = Vec::pop(v), ReturnTo(drop), UnwindContinue())
    121//!         }
    122//!
    123//!         drop = {
    124//!             Drop(popped, ReturnTo(ret), UnwindContinue())
    125//!         }
    126//!
    127//!         ret = {
    128//!             Return()
    129//!         }
    130//!     }
    131//! }
    132//!
    133//! #[custom_mir(dialect = "runtime", phase = "optimized")]
    134//! fn annotated_return_type() -> (i32, bool) {
    135//!     mir! {
    136//!         type RET = (i32, bool);
    137//!         {
    138//!             RET.0 = 1;
    139//!             RET.1 = true;
    140//!             Return()
    141//!         }
    142//!     }
    143//! }
    144//! ```
    145//!
    146//! We can also set off compilation failures that happen in sufficiently late stages of the
    147//! compiler:
    148//!
    149//! ```rust,compile_fail
    150//! #![feature(core_intrinsics, custom_mir)]
    151//!
    152//! extern crate core;
    153//! use core::intrinsics::mir::*;
    154//!
    155//! #[custom_mir(dialect = "built")]
    156//! fn borrow_error(should_init: bool) -> i32 {
    157//!     mir! {
    158//!         let temp: i32;
    159//!
    160//!         {
    161//!             match should_init {
    162//!                 true => init,
    163//!                 _ => use_temp,
    164//!             }
    165//!         }
    166//!
    167//!         init = {
    168//!             temp = 0;
    169//!             Goto(use_temp)
    170//!         }
    171//!
    172//!         use_temp = {
    173//!             RET = temp;
    174//!             Return()
    175//!         }
    176//!     }
    177//! }
    178//! ```
    179//!
    180//! ```text
    181//! error[E0381]: used binding is possibly-uninitialized
    182//!   --> test.rs:24:13
    183//!    |
    184//! 8  | /     mir! {
    185//! 9  | |         let temp: i32;
    186//! 10 | |
    187//! 11 | |         {
    188//! ...  |
    189//! 19 | |             temp = 0;
    190//!    | |             -------- binding initialized here in some conditions
    191//! ...  |
    192//! 24 | |             RET = temp;
    193//!    | |             ^^^^^^^^^^ value used here but it is possibly-uninitialized
    194//! 25 | |             Return()
    195//! 26 | |         }
    196//! 27 | |     }
    197//!    | |_____- binding declared here but left uninitialized
    198//!
    199//! error: aborting due to 1 previous error
    200//!
    201//! For more information about this error, try `rustc --explain E0381`.
    202//! ```
    203//!
    204//! # Syntax
    205//!
    206//! The lists below are an exhaustive description of how various MIR constructs can be created.
    207//! Anything missing from the list should be assumed to not be supported, PRs welcome.
    208//!
    209//! #### Locals
    210//!
    211//!  - The `_0` return local can always be accessed via `RET`.
    212//!  - Arguments can be accessed via their regular name.
    213//!  - All other locals need to be declared with `let` somewhere and then can be accessed by name.
    214//!
    215//! #### Places
    216//!  - Locals implicitly convert to places.
    217//!  - Field accesses, derefs, and indexing work normally.
    218//!  - Fields in variants can be accessed via the [`Variant`] and [`Field`] associated functions,
    219//!    see their documentation for details.
    220//!
    221//! #### Operands
    222//!  - Places implicitly convert to `Copy` operands.
    223//!  - `Move` operands can be created via [`Move`].
    224//!  - Const blocks, literals, named constants, and const params all just work.
    225//!  - [`Static`] and [`StaticMut`] can be used to create `&T` and `*mut T`s to statics. These are
    226//!    constants in MIR and the only way to access statics.
    227//!
    228//! #### Statements
    229//!  - Assign statements work via normal Rust assignment.
    230//!  - [`Retag`], [`StorageLive`], [`StorageDead`] statements have an associated function.
    231//!
    232//! #### Rvalues
    233//!
    234//!  - Operands implicitly convert to `Use` rvalues.
    235//!  - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
    236//!  - [`CastTransmute`], [`CastPtrToPtr`], [`CastUnsize`], and [`Discriminant`]
    237//!    have associated functions.
    238//!  - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
    239//!  - The binary operation `Offset` can be created via [`Offset`].
    240//!  - Checked binary operations are represented by wrapping the associated binop in [`Checked`].
    241//!  - Array repetition syntax (`[foo; 10]`) creates the associated rvalue.
    242//!
    243//! #### Terminators
    244//!
    245//!  - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions.
    246//!  - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
    247//!     - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
    248//!       otherwise branch.
    249//!  - [`Call`] has an associated function as well, with special syntax:
    250//!    `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`.
    251//!  - [`TailCall`] does not have a return destination or next block, so its syntax is just
    252//!    `TailCall(function(arg1, arg2, ...))`.
    253//!
    254//! #### Debuginfo
    255//!
    256//! Debuginfo associates source code variable names (of variables that may not exist any more) with
    257//! MIR expressions that indicate where the value of that variable is stored. The syntax to do so
    258//! is:
    259//! ```text
    260//! debug source_var_name => expression;
    261//! ```
    262//! Both places and constants are supported in the `expression`.
    263//!
    264//! ```rust
    265//! #![allow(internal_features)]
    266//! #![feature(core_intrinsics, custom_mir)]
    267//!
    268//! use core::intrinsics::mir::*;
    269//!
    270//! #[custom_mir(dialect = "built")]
    271//! fn debuginfo(arg: Option<&i32>) {
    272//!     mir!(
    273//!         // Debuginfo for a source variable `plain_local` that just duplicates `arg`.
    274//!         debug plain_local => arg;
    275//!         // Debuginfo for a source variable `projection` that can be computed by dereferencing
    276//!         // a field of `arg`.
    277//!         debug projection => *Field::<&i32>(Variant(arg, 1), 0);
    278//!         // Debuginfo for a source variable `constant` that always holds the value `5`.
    279//!         debug constant => 5_usize;
    280//!         {
    281//!             Return()
    282//!         }
    283//!     )
    284//! }
    285//! ```
    286
    287#![unstable(
    288    feature = "custom_mir",
    289    reason = "MIR is an implementation detail and extremely unstable",
    290    issue = "none"
    291)]
    292#![allow(unused_variables, non_snake_case, missing_debug_implementations)]
    293
    294/// Type representing basic blocks.
    295///
    296/// All terminators will have this type as a return type. It helps achieve some type safety.
    297#[rustc_diagnostic_item = "mir_basic_block"]
    298pub enum BasicBlock {
    299    /// A non-cleanup basic block.
    300    Normal,
    301    /// A basic block that lies on an unwind path.
    302    Cleanup,
    303}
    304
    305/// The reason we are terminating the process during unwinding.
    306#[rustc_diagnostic_item = "mir_unwind_terminate_reason"]
    307pub enum UnwindTerminateReason {
    308    /// Unwinding is just not possible given the ABI of this function.
    309    Abi,
    310    /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was
    311    /// triggered by the drop glue.
    312    InCleanup,
    313}
    314
    315pub use UnwindTerminateReason::{Abi as ReasonAbi, InCleanup as ReasonInCleanup};
    316
    317macro_rules! define {
    318    ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => {
    319        #[rustc_diagnostic_item = $name]
    320        #[inline]
    321        $( #[ $meta ] )*
    322        pub fn $($sig)* { panic!() }
    323    }
    324}
    325
    326// Unwind actions
    327pub struct UnwindActionArg;
    328define!(
    329    "mir_unwind_continue",
    330    /// An unwind action that continues unwinding.
    331    fn UnwindContinue() -> UnwindActionArg
    332);
    333define!(
    334    "mir_unwind_unreachable",
    335    /// An unwind action that triggers undefined behavior.
    336    fn UnwindUnreachable() -> UnwindActionArg
    337);
    338define!(
    339    "mir_unwind_terminate",
    340    /// An unwind action that terminates the execution.
    341    ///
    342    /// `UnwindTerminate` can also be used as a terminator.
    343    fn UnwindTerminate(reason: UnwindTerminateReason) -> UnwindActionArg
    344);
    345define!(
    346    "mir_unwind_cleanup",
    347    /// An unwind action that continues execution in a given basic block.
    348    fn UnwindCleanup(goto: BasicBlock) -> UnwindActionArg
    349);
    350
    351// Return destination for `Call`
    352pub struct ReturnToArg;
    353define!("mir_return_to", fn ReturnTo(goto: BasicBlock) -> ReturnToArg);
    354
    355// Terminators
    356define!("mir_return", fn Return() -> BasicBlock);
    357define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
    358define!("mir_unreachable", fn Unreachable() -> BasicBlock);
    359define!("mir_drop",
    360    /// Drop the contents of a place.
    361    ///
    362    /// The first argument must be a place.
    363    ///
    364    /// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
    365    /// will be jumped to after the destructor returns.
    366    ///
    367    /// The third argument describes what happens on unwind. It can be one of:
    368    /// - [`UnwindContinue`]
    369    /// - [`UnwindUnreachable`]
    370    /// - [`UnwindTerminate`]
    371    /// - [`UnwindCleanup`]
    372    fn Drop<T>(place: T, goto: ReturnToArg, unwind_action: UnwindActionArg)
    373);
    374define!("mir_call",
    375    /// Call a function.
    376    ///
    377    /// The first argument must be of the form `ret_val = fun(arg1, arg2, ...)`.
    378    ///
    379    /// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
    380    /// will be jumped to after the function returns.
    381    ///
    382    /// The third argument describes what happens on unwind. It can be one of:
    383    /// - [`UnwindContinue`]
    384    /// - [`UnwindUnreachable`]
    385    /// - [`UnwindTerminate`]
    386    /// - [`UnwindCleanup`]
    387    fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg)
    388);
    389define!("mir_tail_call",
    390    /// Call a function.
    391    ///
    392    /// The argument must be of the form `fun(arg1, arg2, ...)`.
    393    fn TailCall<T>(call: T)
    394);
    395define!("mir_unwind_resume",
    396    /// A terminator that resumes the unwinding.
    397    fn UnwindResume()
    398);
    399
    400define!("mir_storage_live", fn StorageLive<T>(local: T));
    401define!("mir_storage_dead", fn StorageDead<T>(local: T));
    402define!("mir_assume", fn Assume(operand: bool));
    403define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
    404define!(
    405    "mir_ptr_metadata",
    406    fn PtrMetadata<P: ?Sized>(place: *const P) -> <P as ::core::ptr::Pointee>::Metadata
    407);
    408define!("mir_retag", fn Retag<T>(place: T));
    409define!("mir_move", fn Move<T>(place: T) -> T);
    410define!("mir_static", fn Static<T>(s: T) -> &'static T);
    411define!("mir_static_mut", fn StaticMut<T>(s: T) -> *mut T);
    412define!(
    413    "mir_discriminant",
    414    /// Gets the discriminant of a place.
    415    fn Discriminant<T>(place: T) -> <T as ::core::marker::DiscriminantKind>::Discriminant
    416);
    417define!("mir_set_discriminant", fn SetDiscriminant<T>(place: T, index: u32));
    418define!("mir_offset", fn Offset<T, U>(ptr: T, count: U) -> T);
    419define!(
    420    "mir_field",
    421    /// Access the field with the given index of some place.
    422    ///
    423    /// This only makes sense to use in conjunction with [`Variant`]. If the type you are looking to
    424    /// access the field of does not have variants, you can use normal field projection syntax.
    425    ///
    426    /// There is no proper way to do a place projection to a variant in Rust, and so these two
    427    /// functions are a workaround. You can access a field of a variant via `Field(Variant(place,
    428    /// var_idx), field_idx)`, where `var_idx` and `field_idx` are appropriate literals. Some
    429    /// caveats:
    430    ///
    431    ///  - The return type of `Variant` is always `()`. Don't worry about that, the correct MIR will
    432    ///    still be generated.
    433    ///  - In some situations, the return type of `Field` cannot be inferred. You may need to
    434    ///    annotate it on the function in these cases.
    435    ///  - Since `Field` is a function call which is not a place expression, using this on the left
    436    ///    hand side of an expression is rejected by the compiler. [`place!`] is a macro provided to
    437    ///    work around that issue. Wrap the left hand side of an assignment in the macro to convince
    438    ///    the compiler that it's ok.
    439    ///
    440    /// # Examples
    441    ///
    442    /// ```rust
    443    /// #![allow(internal_features)]
    444    /// #![feature(custom_mir, core_intrinsics)]
    445    ///
    446    /// use core::intrinsics::mir::*;
    447    ///
    448    /// #[custom_mir(dialect = "built")]
    449    /// fn unwrap_deref(opt: Option<&i32>) -> i32 {
    450    ///     mir! {
    451    ///         {
    452    ///             RET = *Field::<&i32>(Variant(opt, 1), 0);
    453    ///             Return()
    454    ///         }
    455    ///     }
    456    /// }
    457    ///
    458    /// #[custom_mir(dialect = "built")]
    459    /// fn set(opt: &mut Option<i32>) {
    460    ///     mir! {
    461    ///         {
    462    ///             place!(Field(Variant(*opt, 1), 0)) = 5;
    463    ///             Return()
    464    ///         }
    465    ///     }
    466    /// }
    467    /// ```
    468    fn Field<F>(place: (), field: u32) -> F
    469);
    470define!(
    471    "mir_variant",
    472    /// Adds a variant projection with the given index to the place.
    473    ///
    474    /// See [`Field`] for documentation.
    475    fn Variant<T>(place: T, index: u32) -> ()
    476);
    477define!(
    478    "mir_cast_transmute",
    479    /// Emits a `CastKind::Transmute` cast.
    480    ///
    481    /// Needed to test the UB when `sizeof(T) != sizeof(U)`, which can't be
    482    /// generated via the normal `mem::transmute`.
    483    fn CastTransmute<T, U>(operand: T) -> U
    484);
    485define!(
    486    "mir_cast_ptr_to_ptr",
    487    /// Emits a `CastKind::PtrToPtr` cast.
    488    ///
    489    /// This allows bypassing normal validation to generate strange casts.
    490    fn CastPtrToPtr<T, U>(operand: T) -> U
    491);
    492define!(
    493    "mir_cast_unsize",
    494    /// Emits a `CastKind::PointerCoercion(Unsize)` cast.
    495    ///
    496    /// This allows bypassing normal validation to generate strange casts.
    497    fn CastUnsize<T, U>(operand: T) -> U
    498);
    499define!(
    500    "mir_make_place",
    501    #[doc(hidden)]
    502    fn __internal_make_place<T>(place: T) -> *mut T
    503);
    504define!(
    505    "mir_debuginfo",
    506    #[doc(hidden)]
    507    fn __debuginfo<T>(name: &'static str, s: T)
    508);
    509
    510/// Macro for generating custom MIR.
    511///
    512/// See the module documentation for syntax details. This macro is not magic - it only transforms
    513/// your MIR into something that is easier to parse in the compiler.
    514#[rustc_macro_transparency = "transparent"]
    515pub macro mir {
    516    {
    517        $(type RET = $ret_ty:ty ;)?
    518        $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
    519        $(debug $dbg_name:ident => $dbg_data:expr ;)*
    520
    521        {
    522            $($entry:tt)*
    523        }
    524
    525        $(
    526            $block_name:ident $(($block_cleanup:ident))? = {
    527                $($block:tt)*
    528            }
    529        )*
    530    } => {{
    531        // First, we declare all basic blocks.
    532        __internal_declare_basic_blocks!($(
    533            $block_name $(($block_cleanup))?
    534        )*);
    535        {
    536            // Now all locals
    537            #[allow(non_snake_case)]
    538            let RET $(: $ret_ty)?;
    539            $(
    540                let $local_decl $(: $local_decl_ty)? ;
    541            )*
    542            ::core::intrinsics::mir::__internal_extract_let!($($entry)*);
    543            $(
    544                ::core::intrinsics::mir::__internal_extract_let!($($block)*);
    545            )*
    546
    547            {
    548                // Now debuginfo
    549                $(
    550                    __debuginfo(stringify!($dbg_name), $dbg_data);
    551                )*
    552
    553                {
    554                    // Finally, the contents of the basic blocks
    555                    ::core::intrinsics::mir::__internal_remove_let!({
    556                        {}
    557                        { $($entry)* }
    558                    });
    559                    $(
    560                        ::core::intrinsics::mir::__internal_remove_let!({
    561                            {}
    562                            { $($block)* }
    563                        });
    564                    )*
    565
    566                    RET
    567                }
    568            }
    569        }
    570    }}
    571}
    572
    573/// Helper macro that allows you to treat a value expression like a place expression.
    574///
    575/// See the documentation on [`Variant`] for why this is necessary and how to use it.
    576pub macro place($e:expr) {
    577    (*::core::intrinsics::mir::__internal_make_place($e))
    578}
    579
    580/// Helper macro that extracts the `let` declarations out of a bunch of statements.
    581///
    582/// This macro is written using the "statement muncher" strategy. Each invocation parses the first
    583/// statement out of the input, does the appropriate thing with it, and then recursively calls the
    584/// same macro on the remainder of the input.
    585#[doc(hidden)]
    586pub macro __internal_extract_let {
    587    // If it's a `let` like statement, keep the `let`
    588    (
    589        let $var:ident $(: $ty:ty)? = $expr:expr; $($rest:tt)*
    590    ) => {
    591        let $var $(: $ty)?;
    592        ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
    593    },
    594    // Due to #86730, we have to handle const blocks separately
    595    (
    596        let $var:ident $(: $ty:ty)? = const $block:block; $($rest:tt)*
    597    ) => {
    598        let $var $(: $ty)?;
    599        ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
    600    },
    601    // Otherwise, output nothing
    602    (
    603        $stmt:stmt; $($rest:tt)*
    604    ) => {
    605        ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
    606    },
    607    (
    608        $expr:expr
    609    ) => {}
    610}
    611
    612/// Helper macro that removes the `let` declarations from a bunch of statements.
    613///
    614/// Because expression position macros cannot expand to statements + expressions, we need to be
    615/// slightly creative here. The general strategy is also statement munching as above, but the output
    616/// of the macro is "stored" in the subsequent macro invocation. Easiest understood via example:
    617/// ```text
    618/// invoke!(
    619///     {
    620///         {
    621///             x = 5;
    622///         }
    623///         {
    624///             let d = e;
    625///             Call()
    626///         }
    627///     }
    628/// )
    629/// ```
    630/// becomes
    631/// ```text
    632/// invoke!(
    633///     {
    634///         {
    635///             x = 5;
    636///             d = e;
    637///         }
    638///         {
    639///             Call()
    640///         }
    641///     }
    642/// )
    643/// ```
    644#[doc(hidden)]
    645pub macro __internal_remove_let {
    646    // If it's a `let` like statement, remove the `let`
    647    (
    648        {
    649            {
    650                $($already_parsed:tt)*
    651            }
    652            {
    653                let $var:ident $(: $ty:ty)? = $expr:expr;
    654                $($rest:tt)*
    655            }
    656        }
    657    ) => { ::core::intrinsics::mir::__internal_remove_let!(
    658        {
    659            {
    660                $($already_parsed)*
    661                $var = $expr;
    662            }
    663            {
    664                $($rest)*
    665            }
    666        }
    667    )},
    668    // Due to #86730 , we have to handle const blocks separately
    669    (
    670        {
    671            {
    672                $($already_parsed:tt)*
    673            }
    674            {
    675                let $var:ident $(: $ty:ty)? = const $block:block;
    676                $($rest:tt)*
    677            }
    678        }
    679    ) => { ::core::intrinsics::mir::__internal_remove_let!(
    680        {
    681            {
    682                $($already_parsed)*
    683                $var = const $block;
    684            }
    685            {
    686                $($rest)*
    687            }
    688        }
    689    )},
    690    // Otherwise, keep going
    691    (
    692        {
    693            {
    694                $($already_parsed:tt)*
    695            }
    696            {
    697                $stmt:stmt;
    698                $($rest:tt)*
    699            }
    700        }
    701    ) => { ::core::intrinsics::mir::__internal_remove_let!(
    702        {
    703            {
    704                $($already_parsed)*
    705                $stmt;
    706            }
    707            {
    708                $($rest)*
    709            }
    710        }
    711    )},
    712    (
    713        {
    714            {
    715                $($already_parsed:tt)*
    716            }
    717            {
    718                $expr:expr
    719            }
    720        }
    721    ) => {
    722        {
    723            $($already_parsed)*
    724            $expr
    725        }
    726    },
    727}
    728
    729/// Helper macro that declares the basic blocks.
    730#[doc(hidden)]
    731pub macro __internal_declare_basic_blocks {
    732    () => {},
    733    ($name:ident (cleanup) $($rest:tt)*) => {
    734        let $name = ::core::intrinsics::mir::BasicBlock::Cleanup;
    735        __internal_declare_basic_blocks!($($rest)*)
    736    },
    737    ($name:ident $($rest:tt)*) => {
    738        let $name = ::core::intrinsics::mir::BasicBlock::Normal;
    739        __internal_declare_basic_blocks!($($rest)*)
    740    },
    741}