Skip to main content

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