rustc_middle/mir/
mod.rs

1//! MIR datatypes and passes. See the [rustc dev guide] for more info.
2//!
3//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
4
5use std::borrow::Cow;
6use std::fmt::{self, Debug, Formatter};
7use std::ops::{Index, IndexMut};
8use std::{iter, mem};
9
10pub use basic_blocks::BasicBlocks;
11use either::Either;
12use polonius_engine::Atom;
13use rustc_abi::{FieldIdx, VariantIdx};
14pub use rustc_ast::Mutability;
15use rustc_data_structures::captures::Captures;
16use rustc_data_structures::fx::{FxHashMap, FxHashSet};
17use rustc_data_structures::graph::dominators::Dominators;
18use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
19use rustc_hir::def::{CtorKind, Namespace};
20use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
21use rustc_hir::{
22    self as hir, BindingMode, ByRef, CoroutineDesugaring, CoroutineKind, HirId, ImplicitSelfKind,
23};
24use rustc_index::bit_set::DenseBitSet;
25use rustc_index::{Idx, IndexSlice, IndexVec};
26use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
27use rustc_serialize::{Decodable, Encodable};
28use rustc_span::source_map::Spanned;
29use rustc_span::{DUMMY_SP, Span, Symbol};
30use tracing::{debug, trace};
31
32pub use self::query::*;
33use self::visit::TyContext;
34use crate::mir::interpret::{AllocRange, Scalar};
35use crate::mir::visit::MirVisitable;
36use crate::ty::codec::{TyDecoder, TyEncoder};
37use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
38use crate::ty::visit::TypeVisitableExt;
39use crate::ty::{
40    self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv,
41    UserTypeAnnotationIndex,
42};
43
44mod basic_blocks;
45mod consts;
46pub mod coverage;
47mod generic_graph;
48pub mod generic_graphviz;
49pub mod graphviz;
50pub mod interpret;
51pub mod mono;
52pub mod pretty;
53mod query;
54mod statement;
55mod syntax;
56pub mod tcx;
57mod terminator;
58
59pub mod traversal;
60pub mod visit;
61
62pub use consts::*;
63use pretty::pretty_print_const_value;
64pub use statement::*;
65pub use syntax::*;
66pub use terminator::*;
67
68pub use self::generic_graph::graphviz_safe_def_name;
69pub use self::graphviz::write_mir_graphviz;
70pub use self::pretty::{
71    PassWhere, create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty,
72};
73
74/// Types for locals
75pub type LocalDecls<'tcx> = IndexSlice<Local, LocalDecl<'tcx>>;
76
77pub trait HasLocalDecls<'tcx> {
78    fn local_decls(&self) -> &LocalDecls<'tcx>;
79}
80
81impl<'tcx> HasLocalDecls<'tcx> for IndexVec<Local, LocalDecl<'tcx>> {
82    #[inline]
83    fn local_decls(&self) -> &LocalDecls<'tcx> {
84        self
85    }
86}
87
88impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
89    #[inline]
90    fn local_decls(&self) -> &LocalDecls<'tcx> {
91        self
92    }
93}
94
95impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
96    #[inline]
97    fn local_decls(&self) -> &LocalDecls<'tcx> {
98        &self.local_decls
99    }
100}
101
102impl MirPhase {
103    /// Gets the index of the current MirPhase within the set of all `MirPhase`s.
104    ///
105    /// FIXME(JakobDegen): Return a `(usize, usize)` instead.
106    pub fn phase_index(&self) -> usize {
107        const BUILT_PHASE_COUNT: usize = 1;
108        const ANALYSIS_PHASE_COUNT: usize = 2;
109        match self {
110            MirPhase::Built => 1,
111            MirPhase::Analysis(analysis_phase) => {
112                1 + BUILT_PHASE_COUNT + (*analysis_phase as usize)
113            }
114            MirPhase::Runtime(runtime_phase) => {
115                1 + BUILT_PHASE_COUNT + ANALYSIS_PHASE_COUNT + (*runtime_phase as usize)
116            }
117        }
118    }
119
120    /// Parses an `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
121    pub fn parse(dialect: String, phase: Option<String>) -> Self {
122        match &*dialect.to_ascii_lowercase() {
123            "built" => {
124                assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR");
125                MirPhase::Built
126            }
127            "analysis" => Self::Analysis(AnalysisPhase::parse(phase)),
128            "runtime" => Self::Runtime(RuntimePhase::parse(phase)),
129            _ => bug!("Unknown MIR dialect: '{}'", dialect),
130        }
131    }
132}
133
134impl AnalysisPhase {
135    pub fn parse(phase: Option<String>) -> Self {
136        let Some(phase) = phase else {
137            return Self::Initial;
138        };
139
140        match &*phase.to_ascii_lowercase() {
141            "initial" => Self::Initial,
142            "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
143            _ => bug!("Unknown analysis phase: '{}'", phase),
144        }
145    }
146}
147
148impl RuntimePhase {
149    pub fn parse(phase: Option<String>) -> Self {
150        let Some(phase) = phase else {
151            return Self::Initial;
152        };
153
154        match &*phase.to_ascii_lowercase() {
155            "initial" => Self::Initial,
156            "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
157            "optimized" => Self::Optimized,
158            _ => bug!("Unknown runtime phase: '{}'", phase),
159        }
160    }
161}
162
163/// Where a specific `mir::Body` comes from.
164#[derive(Copy, Clone, Debug, PartialEq, Eq)]
165#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
166pub struct MirSource<'tcx> {
167    pub instance: InstanceKind<'tcx>,
168
169    /// If `Some`, this is a promoted rvalue within the parent function.
170    pub promoted: Option<Promoted>,
171}
172
173impl<'tcx> MirSource<'tcx> {
174    pub fn item(def_id: DefId) -> Self {
175        MirSource { instance: InstanceKind::Item(def_id), promoted: None }
176    }
177
178    pub fn from_instance(instance: InstanceKind<'tcx>) -> Self {
179        MirSource { instance, promoted: None }
180    }
181
182    #[inline]
183    pub fn def_id(&self) -> DefId {
184        self.instance.def_id()
185    }
186}
187
188/// Additional information carried by a MIR body when it is lowered from a coroutine.
189/// This information is modified as it is lowered during the `StateTransform` MIR pass,
190/// so not all fields will be active at a given time. For example, the `yield_ty` is
191/// taken out of the field after yields are turned into returns, and the `coroutine_drop`
192/// body is only populated after the state transform pass.
193#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
194pub struct CoroutineInfo<'tcx> {
195    /// The yield type of the function. This field is removed after the state transform pass.
196    pub yield_ty: Option<Ty<'tcx>>,
197
198    /// The resume type of the function. This field is removed after the state transform pass.
199    pub resume_ty: Option<Ty<'tcx>>,
200
201    /// Coroutine drop glue. This field is populated after the state transform pass.
202    pub coroutine_drop: Option<Body<'tcx>>,
203
204    /// The layout of a coroutine. This field is populated after the state transform pass.
205    pub coroutine_layout: Option<CoroutineLayout<'tcx>>,
206
207    /// If this is a coroutine then record the type of source expression that caused this coroutine
208    /// to be created.
209    pub coroutine_kind: CoroutineKind,
210}
211
212impl<'tcx> CoroutineInfo<'tcx> {
213    // Sets up `CoroutineInfo` for a pre-coroutine-transform MIR body.
214    pub fn initial(
215        coroutine_kind: CoroutineKind,
216        yield_ty: Ty<'tcx>,
217        resume_ty: Ty<'tcx>,
218    ) -> CoroutineInfo<'tcx> {
219        CoroutineInfo {
220            coroutine_kind,
221            yield_ty: Some(yield_ty),
222            resume_ty: Some(resume_ty),
223            coroutine_drop: None,
224            coroutine_layout: None,
225        }
226    }
227}
228
229/// Some item that needs to monomorphize successfully for a MIR body to be considered well-formed.
230#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, HashStable, TyEncodable, TyDecodable)]
231#[derive(TypeFoldable, TypeVisitable)]
232pub enum MentionedItem<'tcx> {
233    /// A function that gets called. We don't necessarily know its precise type yet, since it can be
234    /// hidden behind a generic.
235    Fn(Ty<'tcx>),
236    /// A type that has its drop shim called.
237    Drop(Ty<'tcx>),
238    /// Unsizing casts might require vtables, so we have to record them.
239    UnsizeCast { source_ty: Ty<'tcx>, target_ty: Ty<'tcx> },
240    /// A closure that is coerced to a function pointer.
241    Closure(Ty<'tcx>),
242}
243
244/// The lowered representation of a single function.
245#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
246pub struct Body<'tcx> {
247    /// A list of basic blocks. References to basic block use a newtyped index type [`BasicBlock`]
248    /// that indexes into this vector.
249    pub basic_blocks: BasicBlocks<'tcx>,
250
251    /// Records how far through the "desugaring and optimization" process this particular
252    /// MIR has traversed. This is particularly useful when inlining, since in that context
253    /// we instantiate the promoted constants and add them to our promoted vector -- but those
254    /// promoted items have already been optimized, whereas ours have not. This field allows
255    /// us to see the difference and forego optimization on the inlined promoted items.
256    pub phase: MirPhase,
257
258    /// How many passses we have executed since starting the current phase. Used for debug output.
259    pub pass_count: usize,
260
261    pub source: MirSource<'tcx>,
262
263    /// A list of source scopes; these are referenced by statements
264    /// and used for debuginfo. Indexed by a `SourceScope`.
265    pub source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
266
267    /// Additional information carried by a MIR body when it is lowered from a coroutine.
268    ///
269    /// Note that the coroutine drop shim, any promoted consts, and other synthetic MIR
270    /// bodies that come from processing a coroutine body are not typically coroutines
271    /// themselves, and should probably set this to `None` to avoid carrying redundant
272    /// information.
273    pub coroutine: Option<Box<CoroutineInfo<'tcx>>>,
274
275    /// Declarations of locals.
276    ///
277    /// The first local is the return value pointer, followed by `arg_count`
278    /// locals for the function arguments, followed by any user-declared
279    /// variables and temporaries.
280    pub local_decls: IndexVec<Local, LocalDecl<'tcx>>,
281
282    /// User type annotations.
283    pub user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
284
285    /// The number of arguments this function takes.
286    ///
287    /// Starting at local 1, `arg_count` locals will be provided by the caller
288    /// and can be assumed to be initialized.
289    ///
290    /// If this MIR was built for a constant, this will be 0.
291    pub arg_count: usize,
292
293    /// Mark an argument local (which must be a tuple) as getting passed as
294    /// its individual components at the LLVM level.
295    ///
296    /// This is used for the "rust-call" ABI.
297    pub spread_arg: Option<Local>,
298
299    /// Debug information pertaining to user variables, including captures.
300    pub var_debug_info: Vec<VarDebugInfo<'tcx>>,
301
302    /// A span representing this MIR, for error reporting.
303    pub span: Span,
304
305    /// Constants that are required to evaluate successfully for this MIR to be well-formed.
306    /// We hold in this field all the constants we are not able to evaluate yet.
307    /// `None` indicates that the list has not been computed yet.
308    ///
309    /// This is soundness-critical, we make a guarantee that all consts syntactically mentioned in a
310    /// function have successfully evaluated if the function ever gets executed at runtime.
311    pub required_consts: Option<Vec<ConstOperand<'tcx>>>,
312
313    /// Further items that were mentioned in this function and hence *may* become monomorphized,
314    /// depending on optimizations. We use this to avoid optimization-dependent compile errors: the
315    /// collector recursively traverses all "mentioned" items and evaluates all their
316    /// `required_consts`.
317    /// `None` indicates that the list has not been computed yet.
318    ///
319    /// This is *not* soundness-critical and the contents of this list are *not* a stable guarantee.
320    /// All that's relevant is that this set is optimization-level-independent, and that it includes
321    /// everything that the collector would consider "used". (For example, we currently compute this
322    /// set after drop elaboration, so some drop calls that can never be reached are not considered
323    /// "mentioned".) See the documentation of `CollectionMode` in
324    /// `compiler/rustc_monomorphize/src/collector.rs` for more context.
325    pub mentioned_items: Option<Vec<Spanned<MentionedItem<'tcx>>>>,
326
327    /// Does this body use generic parameters. This is used for the `ConstEvaluatable` check.
328    ///
329    /// Note that this does not actually mean that this body is not computable right now.
330    /// The repeat count in the following example is polymorphic, but can still be evaluated
331    /// without knowing anything about the type parameter `T`.
332    ///
333    /// ```rust
334    /// fn test<T>() {
335    ///     let _ = [0; std::mem::size_of::<*mut T>()];
336    /// }
337    /// ```
338    ///
339    /// **WARNING**: Do not change this flags after the MIR was originally created, even if an optimization
340    /// removed the last mention of all generic params. We do not want to rely on optimizations and
341    /// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this.
342    pub is_polymorphic: bool,
343
344    /// The phase at which this MIR should be "injected" into the compilation process.
345    ///
346    /// Everything that comes before this `MirPhase` should be skipped.
347    ///
348    /// This is only `Some` if the function that this body comes from was annotated with `rustc_custom_mir`.
349    pub injection_phase: Option<MirPhase>,
350
351    pub tainted_by_errors: Option<ErrorGuaranteed>,
352
353    /// Coverage information collected from THIR/MIR during MIR building,
354    /// to be used by the `InstrumentCoverage` pass.
355    ///
356    /// Only present if coverage is enabled and this function is eligible.
357    /// Boxed to limit space overhead in non-coverage builds.
358    #[type_foldable(identity)]
359    #[type_visitable(ignore)]
360    pub coverage_info_hi: Option<Box<coverage::CoverageInfoHi>>,
361
362    /// Per-function coverage information added by the `InstrumentCoverage`
363    /// pass, to be used in conjunction with the coverage statements injected
364    /// into this body's blocks.
365    ///
366    /// If `-Cinstrument-coverage` is not active, or if an individual function
367    /// is not eligible for coverage, then this should always be `None`.
368    #[type_foldable(identity)]
369    #[type_visitable(ignore)]
370    pub function_coverage_info: Option<Box<coverage::FunctionCoverageInfo>>,
371}
372
373impl<'tcx> Body<'tcx> {
374    pub fn new(
375        source: MirSource<'tcx>,
376        basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
377        source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
378        local_decls: IndexVec<Local, LocalDecl<'tcx>>,
379        user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
380        arg_count: usize,
381        var_debug_info: Vec<VarDebugInfo<'tcx>>,
382        span: Span,
383        coroutine: Option<Box<CoroutineInfo<'tcx>>>,
384        tainted_by_errors: Option<ErrorGuaranteed>,
385    ) -> Self {
386        // We need `arg_count` locals, and one for the return place.
387        assert!(
388            local_decls.len() > arg_count,
389            "expected at least {} locals, got {}",
390            arg_count + 1,
391            local_decls.len()
392        );
393
394        let mut body = Body {
395            phase: MirPhase::Built,
396            pass_count: 0,
397            source,
398            basic_blocks: BasicBlocks::new(basic_blocks),
399            source_scopes,
400            coroutine,
401            local_decls,
402            user_type_annotations,
403            arg_count,
404            spread_arg: None,
405            var_debug_info,
406            span,
407            required_consts: None,
408            mentioned_items: None,
409            is_polymorphic: false,
410            injection_phase: None,
411            tainted_by_errors,
412            coverage_info_hi: None,
413            function_coverage_info: None,
414        };
415        body.is_polymorphic = body.has_non_region_param();
416        body
417    }
418
419    /// Returns a partially initialized MIR body containing only a list of basic blocks.
420    ///
421    /// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
422    /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
423    /// crate.
424    pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
425        let mut body = Body {
426            phase: MirPhase::Built,
427            pass_count: 0,
428            source: MirSource::item(CRATE_DEF_ID.to_def_id()),
429            basic_blocks: BasicBlocks::new(basic_blocks),
430            source_scopes: IndexVec::new(),
431            coroutine: None,
432            local_decls: IndexVec::new(),
433            user_type_annotations: IndexVec::new(),
434            arg_count: 0,
435            spread_arg: None,
436            span: DUMMY_SP,
437            required_consts: None,
438            mentioned_items: None,
439            var_debug_info: Vec::new(),
440            is_polymorphic: false,
441            injection_phase: None,
442            tainted_by_errors: None,
443            coverage_info_hi: None,
444            function_coverage_info: None,
445        };
446        body.is_polymorphic = body.has_non_region_param();
447        body
448    }
449
450    #[inline]
451    pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
452        self.basic_blocks.as_mut()
453    }
454
455    pub fn typing_env(&self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
456        match self.phase {
457            // FIXME(#132279): we should reveal the opaques defined in the body during analysis.
458            MirPhase::Built | MirPhase::Analysis(_) => TypingEnv {
459                typing_mode: ty::TypingMode::non_body_analysis(),
460                param_env: tcx.param_env(self.source.def_id()),
461            },
462            MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()),
463        }
464    }
465
466    #[inline]
467    pub fn local_kind(&self, local: Local) -> LocalKind {
468        let index = local.as_usize();
469        if index == 0 {
470            debug_assert!(
471                self.local_decls[local].mutability == Mutability::Mut,
472                "return place should be mutable"
473            );
474
475            LocalKind::ReturnPointer
476        } else if index < self.arg_count + 1 {
477            LocalKind::Arg
478        } else {
479            LocalKind::Temp
480        }
481    }
482
483    /// Returns an iterator over all user-declared mutable locals.
484    #[inline]
485    pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + Captures<'tcx> + 'a {
486        (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
487            let local = Local::new(index);
488            let decl = &self.local_decls[local];
489            (decl.is_user_variable() && decl.mutability.is_mut()).then_some(local)
490        })
491    }
492
493    /// Returns an iterator over all user-declared mutable arguments and locals.
494    #[inline]
495    pub fn mut_vars_and_args_iter<'a>(
496        &'a self,
497    ) -> impl Iterator<Item = Local> + Captures<'tcx> + 'a {
498        (1..self.local_decls.len()).filter_map(move |index| {
499            let local = Local::new(index);
500            let decl = &self.local_decls[local];
501            if (decl.is_user_variable() || index < self.arg_count + 1)
502                && decl.mutability == Mutability::Mut
503            {
504                Some(local)
505            } else {
506                None
507            }
508        })
509    }
510
511    /// Returns an iterator over all function arguments.
512    #[inline]
513    pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
514        (1..self.arg_count + 1).map(Local::new)
515    }
516
517    /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
518    /// locals that are neither arguments nor the return place).
519    #[inline]
520    pub fn vars_and_temps_iter(
521        &self,
522    ) -> impl DoubleEndedIterator<Item = Local> + ExactSizeIterator {
523        (self.arg_count + 1..self.local_decls.len()).map(Local::new)
524    }
525
526    #[inline]
527    pub fn drain_vars_and_temps<'a>(&'a mut self) -> impl Iterator<Item = LocalDecl<'tcx>> + 'a {
528        self.local_decls.drain(self.arg_count + 1..)
529    }
530
531    /// Returns the source info associated with `location`.
532    pub fn source_info(&self, location: Location) -> &SourceInfo {
533        let block = &self[location.block];
534        let stmts = &block.statements;
535        let idx = location.statement_index;
536        if idx < stmts.len() {
537            &stmts[idx].source_info
538        } else {
539            assert_eq!(idx, stmts.len());
540            &block.terminator().source_info
541        }
542    }
543
544    pub fn span_for_ty_context(&self, ty_context: TyContext) -> Span {
545        match ty_context {
546            TyContext::UserTy(span) => span,
547            TyContext::ReturnTy(source_info)
548            | TyContext::LocalDecl { source_info, .. }
549            | TyContext::YieldTy(source_info)
550            | TyContext::ResumeTy(source_info) => source_info.span,
551            TyContext::Location(loc) => self.source_info(loc).span,
552        }
553    }
554
555    /// Returns the return type; it always return first element from `local_decls` array.
556    #[inline]
557    pub fn return_ty(&self) -> Ty<'tcx> {
558        self.local_decls[RETURN_PLACE].ty
559    }
560
561    /// Returns the return type; it always return first element from `local_decls` array.
562    #[inline]
563    pub fn bound_return_ty(&self) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
564        ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty)
565    }
566
567    /// Gets the location of the terminator for the given block.
568    #[inline]
569    pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
570        Location { block: bb, statement_index: self[bb].statements.len() }
571    }
572
573    pub fn stmt_at(&self, location: Location) -> Either<&Statement<'tcx>, &Terminator<'tcx>> {
574        let Location { block, statement_index } = location;
575        let block_data = &self.basic_blocks[block];
576        block_data
577            .statements
578            .get(statement_index)
579            .map(Either::Left)
580            .unwrap_or_else(|| Either::Right(block_data.terminator()))
581    }
582
583    #[inline]
584    pub fn yield_ty(&self) -> Option<Ty<'tcx>> {
585        self.coroutine.as_ref().and_then(|coroutine| coroutine.yield_ty)
586    }
587
588    #[inline]
589    pub fn resume_ty(&self) -> Option<Ty<'tcx>> {
590        self.coroutine.as_ref().and_then(|coroutine| coroutine.resume_ty)
591    }
592
593    /// Prefer going through [`TyCtxt::coroutine_layout`] rather than using this directly.
594    #[inline]
595    pub fn coroutine_layout_raw(&self) -> Option<&CoroutineLayout<'tcx>> {
596        self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_layout.as_ref())
597    }
598
599    #[inline]
600    pub fn coroutine_drop(&self) -> Option<&Body<'tcx>> {
601        self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_drop.as_ref())
602    }
603
604    #[inline]
605    pub fn coroutine_kind(&self) -> Option<CoroutineKind> {
606        self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind)
607    }
608
609    #[inline]
610    pub fn should_skip(&self) -> bool {
611        let Some(injection_phase) = self.injection_phase else {
612            return false;
613        };
614        injection_phase > self.phase
615    }
616
617    #[inline]
618    pub fn is_custom_mir(&self) -> bool {
619        self.injection_phase.is_some()
620    }
621
622    /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the
623    /// discriminant in monomorphization, we return the discriminant bits and the
624    /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator.
625    fn try_const_mono_switchint<'a>(
626        tcx: TyCtxt<'tcx>,
627        instance: Instance<'tcx>,
628        block: &'a BasicBlockData<'tcx>,
629    ) -> Option<(u128, &'a SwitchTargets)> {
630        // There are two places here we need to evaluate a constant.
631        let eval_mono_const = |constant: &ConstOperand<'tcx>| {
632            // FIXME(#132279): what is this, why are we using an empty environment here.
633            let typing_env = ty::TypingEnv::fully_monomorphized();
634            let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions(
635                tcx,
636                typing_env,
637                crate::ty::EarlyBinder::bind(constant.const_),
638            );
639            mono_literal.try_eval_bits(tcx, typing_env)
640        };
641
642        let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else {
643            return None;
644        };
645
646        // If this is a SwitchInt(const _), then we can just evaluate the constant and return.
647        let discr = match discr {
648            Operand::Constant(constant) => {
649                let bits = eval_mono_const(constant)?;
650                return Some((bits, targets));
651            }
652            Operand::Move(place) | Operand::Copy(place) => place,
653        };
654
655        // MIR for `if false` actually looks like this:
656        // _1 = const _
657        // SwitchInt(_1)
658        //
659        // And MIR for if intrinsics::ub_checks() looks like this:
660        // _1 = UbChecks()
661        // SwitchInt(_1)
662        //
663        // So we're going to try to recognize this pattern.
664        //
665        // If we have a SwitchInt on a non-const place, we find the most recent statement that
666        // isn't a storage marker. If that statement is an assignment of a const to our
667        // discriminant place, we evaluate and return the const, as if we've const-propagated it
668        // into the SwitchInt.
669
670        let last_stmt = block.statements.iter().rev().find(|stmt| {
671            !matches!(stmt.kind, StatementKind::StorageDead(_) | StatementKind::StorageLive(_))
672        })?;
673
674        let (place, rvalue) = last_stmt.kind.as_assign()?;
675
676        if discr != place {
677            return None;
678        }
679
680        match rvalue {
681            Rvalue::NullaryOp(NullOp::UbChecks, _) => Some((tcx.sess.ub_checks() as u128, targets)),
682            Rvalue::Use(Operand::Constant(constant)) => {
683                let bits = eval_mono_const(constant)?;
684                Some((bits, targets))
685            }
686            _ => None,
687        }
688    }
689
690    /// For a `Location` in this scope, determine what the "caller location" at that point is. This
691    /// is interesting because of inlining: the `#[track_caller]` attribute of inlined functions
692    /// must be honored. Falls back to the `tracked_caller` value for `#[track_caller]` functions,
693    /// or the function's scope.
694    pub fn caller_location_span<T>(
695        &self,
696        mut source_info: SourceInfo,
697        caller_location: Option<T>,
698        tcx: TyCtxt<'tcx>,
699        from_span: impl FnOnce(Span) -> T,
700    ) -> T {
701        loop {
702            let scope_data = &self.source_scopes[source_info.scope];
703
704            if let Some((callee, callsite_span)) = scope_data.inlined {
705                // Stop inside the most nested non-`#[track_caller]` function,
706                // before ever reaching its caller (which is irrelevant).
707                if !callee.def.requires_caller_location(tcx) {
708                    return from_span(source_info.span);
709                }
710                source_info.span = callsite_span;
711            }
712
713            // Skip past all of the parents with `inlined: None`.
714            match scope_data.inlined_parent_scope {
715                Some(parent) => source_info.scope = parent,
716                None => break,
717            }
718        }
719
720        // No inlined `SourceScope`s, or all of them were `#[track_caller]`.
721        caller_location.unwrap_or_else(|| from_span(source_info.span))
722    }
723
724    #[track_caller]
725    pub fn set_required_consts(&mut self, required_consts: Vec<ConstOperand<'tcx>>) {
726        assert!(
727            self.required_consts.is_none(),
728            "required_consts for {:?} have already been set",
729            self.source.def_id()
730        );
731        self.required_consts = Some(required_consts);
732    }
733    #[track_caller]
734    pub fn required_consts(&self) -> &[ConstOperand<'tcx>] {
735        match &self.required_consts {
736            Some(l) => l,
737            None => panic!("required_consts for {:?} have not yet been set", self.source.def_id()),
738        }
739    }
740
741    #[track_caller]
742    pub fn set_mentioned_items(&mut self, mentioned_items: Vec<Spanned<MentionedItem<'tcx>>>) {
743        assert!(
744            self.mentioned_items.is_none(),
745            "mentioned_items for {:?} have already been set",
746            self.source.def_id()
747        );
748        self.mentioned_items = Some(mentioned_items);
749    }
750    #[track_caller]
751    pub fn mentioned_items(&self) -> &[Spanned<MentionedItem<'tcx>>] {
752        match &self.mentioned_items {
753            Some(l) => l,
754            None => panic!("mentioned_items for {:?} have not yet been set", self.source.def_id()),
755        }
756    }
757}
758
759impl<'tcx> Index<BasicBlock> for Body<'tcx> {
760    type Output = BasicBlockData<'tcx>;
761
762    #[inline]
763    fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
764        &self.basic_blocks[index]
765    }
766}
767
768impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
769    #[inline]
770    fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
771        &mut self.basic_blocks.as_mut()[index]
772    }
773}
774
775#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
776pub enum ClearCrossCrate<T> {
777    Clear,
778    Set(T),
779}
780
781impl<T> ClearCrossCrate<T> {
782    pub fn as_ref(&self) -> ClearCrossCrate<&T> {
783        match self {
784            ClearCrossCrate::Clear => ClearCrossCrate::Clear,
785            ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
786        }
787    }
788
789    pub fn as_mut(&mut self) -> ClearCrossCrate<&mut T> {
790        match self {
791            ClearCrossCrate::Clear => ClearCrossCrate::Clear,
792            ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
793        }
794    }
795
796    pub fn assert_crate_local(self) -> T {
797        match self {
798            ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
799            ClearCrossCrate::Set(v) => v,
800        }
801    }
802}
803
804const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
805const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
806
807impl<E: TyEncoder, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> {
808    #[inline]
809    fn encode(&self, e: &mut E) {
810        if E::CLEAR_CROSS_CRATE {
811            return;
812        }
813
814        match *self {
815            ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
816            ClearCrossCrate::Set(ref val) => {
817                TAG_CLEAR_CROSS_CRATE_SET.encode(e);
818                val.encode(e);
819            }
820        }
821    }
822}
823impl<D: TyDecoder, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> {
824    #[inline]
825    fn decode(d: &mut D) -> ClearCrossCrate<T> {
826        if D::CLEAR_CROSS_CRATE {
827            return ClearCrossCrate::Clear;
828        }
829
830        let discr = u8::decode(d);
831
832        match discr {
833            TAG_CLEAR_CROSS_CRATE_CLEAR => ClearCrossCrate::Clear,
834            TAG_CLEAR_CROSS_CRATE_SET => {
835                let val = T::decode(d);
836                ClearCrossCrate::Set(val)
837            }
838            tag => panic!("Invalid tag for ClearCrossCrate: {tag:?}"),
839        }
840    }
841}
842
843/// Grouped information about the source code origin of a MIR entity.
844/// Intended to be inspected by diagnostics and debuginfo.
845/// Most passes can work with it as a whole, within a single function.
846// The unofficial Cranelift backend, at least as of #65828, needs `SourceInfo` to implement `Eq` and
847// `Hash`. Please ping @bjorn3 if removing them.
848#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
849pub struct SourceInfo {
850    /// The source span for the AST pertaining to this MIR entity.
851    pub span: Span,
852
853    /// The source scope, keeping track of which bindings can be
854    /// seen by debuginfo, active lint levels, etc.
855    pub scope: SourceScope,
856}
857
858impl SourceInfo {
859    #[inline]
860    pub fn outermost(span: Span) -> Self {
861        SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }
862    }
863}
864
865///////////////////////////////////////////////////////////////////////////
866// Variables and temps
867
868rustc_index::newtype_index! {
869    #[derive(HashStable)]
870    #[encodable]
871    #[orderable]
872    #[debug_format = "_{}"]
873    pub struct Local {
874        const RETURN_PLACE = 0;
875    }
876}
877
878impl Atom for Local {
879    fn index(self) -> usize {
880        Idx::index(self)
881    }
882}
883
884/// Classifies locals into categories. See `Body::local_kind`.
885#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
886pub enum LocalKind {
887    /// User-declared variable binding or compiler-introduced temporary.
888    Temp,
889    /// Function argument.
890    Arg,
891    /// Location of function's return value.
892    ReturnPointer,
893}
894
895#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
896pub struct VarBindingForm<'tcx> {
897    /// Is variable bound via `x`, `mut x`, `ref x`, `ref mut x`, `mut ref x`, or `mut ref mut x`?
898    pub binding_mode: BindingMode,
899    /// If an explicit type was provided for this variable binding,
900    /// this holds the source Span of that type.
901    ///
902    /// NOTE: if you want to change this to a `HirId`, be wary that
903    /// doing so breaks incremental compilation (as of this writing),
904    /// while a `Span` does not cause our tests to fail.
905    pub opt_ty_info: Option<Span>,
906    /// Place of the RHS of the =, or the subject of the `match` where this
907    /// variable is initialized. None in the case of `let PATTERN;`.
908    /// Some((None, ..)) in the case of and `let [mut] x = ...` because
909    /// (a) the right-hand side isn't evaluated as a place expression.
910    /// (b) it gives a way to separate this case from the remaining cases
911    ///     for diagnostics.
912    pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
913    /// The span of the pattern in which this variable was bound.
914    pub pat_span: Span,
915}
916
917#[derive(Clone, Debug, TyEncodable, TyDecodable)]
918pub enum BindingForm<'tcx> {
919    /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
920    Var(VarBindingForm<'tcx>),
921    /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
922    ImplicitSelf(ImplicitSelfKind),
923    /// Reference used in a guard expression to ensure immutability.
924    RefForGuard,
925}
926
927mod binding_form_impl {
928    use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
929    use rustc_query_system::ich::StableHashingContext;
930
931    impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for super::BindingForm<'tcx> {
932        fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
933            use super::BindingForm::*;
934            std::mem::discriminant(self).hash_stable(hcx, hasher);
935
936            match self {
937                Var(binding) => binding.hash_stable(hcx, hasher),
938                ImplicitSelf(kind) => kind.hash_stable(hcx, hasher),
939                RefForGuard => (),
940            }
941        }
942    }
943}
944
945/// `BlockTailInfo` is attached to the `LocalDecl` for temporaries
946/// created during evaluation of expressions in a block tail
947/// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`.
948///
949/// It is used to improve diagnostics when such temporaries are
950/// involved in borrow_check errors, e.g., explanations of where the
951/// temporaries come from, when their destructors are run, and/or how
952/// one might revise the code to satisfy the borrow checker's rules.
953#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
954pub struct BlockTailInfo {
955    /// If `true`, then the value resulting from evaluating this tail
956    /// expression is ignored by the block's expression context.
957    ///
958    /// Examples include `{ ...; tail };` and `let _ = { ...; tail };`
959    /// but not e.g., `let _x = { ...; tail };`
960    pub tail_result_is_ignored: bool,
961
962    /// `Span` of the tail expression.
963    pub span: Span,
964}
965
966/// A MIR local.
967///
968/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
969/// argument, or the return place.
970#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
971pub struct LocalDecl<'tcx> {
972    /// Whether this is a mutable binding (i.e., `let x` or `let mut x`).
973    ///
974    /// Temporaries and the return place are always mutable.
975    pub mutability: Mutability,
976
977    // FIXME(matthewjasper) Don't store in this in `Body`
978    pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>,
979
980    /// The type of this local.
981    pub ty: Ty<'tcx>,
982
983    /// If the user manually ascribed a type to this variable,
984    /// e.g., via `let x: T`, then we carry that type here. The MIR
985    /// borrow checker needs this information since it can affect
986    /// region inference.
987    // FIXME(matthewjasper) Don't store in this in `Body`
988    pub user_ty: Option<Box<UserTypeProjections>>,
989
990    /// The *syntactic* (i.e., not visibility) source scope the local is defined
991    /// in. If the local was defined in a let-statement, this
992    /// is *within* the let-statement, rather than outside
993    /// of it.
994    ///
995    /// This is needed because the visibility source scope of locals within
996    /// a let-statement is weird.
997    ///
998    /// The reason is that we want the local to be *within* the let-statement
999    /// for lint purposes, but we want the local to be *after* the let-statement
1000    /// for names-in-scope purposes.
1001    ///
1002    /// That's it, if we have a let-statement like the one in this
1003    /// function:
1004    ///
1005    /// ```
1006    /// fn foo(x: &str) {
1007    ///     #[allow(unused_mut)]
1008    ///     let mut x: u32 = { // <- one unused mut
1009    ///         let mut y: u32 = x.parse().unwrap();
1010    ///         y + 2
1011    ///     };
1012    ///     drop(x);
1013    /// }
1014    /// ```
1015    ///
1016    /// Then, from a lint point of view, the declaration of `x: u32`
1017    /// (and `y: u32`) are within the `#[allow(unused_mut)]` scope - the
1018    /// lint scopes are the same as the AST/HIR nesting.
1019    ///
1020    /// However, from a name lookup point of view, the scopes look more like
1021    /// as if the let-statements were `match` expressions:
1022    ///
1023    /// ```
1024    /// fn foo(x: &str) {
1025    ///     match {
1026    ///         match x.parse::<u32>().unwrap() {
1027    ///             y => y + 2
1028    ///         }
1029    ///     } {
1030    ///         x => drop(x)
1031    ///     };
1032    /// }
1033    /// ```
1034    ///
1035    /// We care about the name-lookup scopes for debuginfo - if the
1036    /// debuginfo instruction pointer is at the call to `x.parse()`, we
1037    /// want `x` to refer to `x: &str`, but if it is at the call to
1038    /// `drop(x)`, we want it to refer to `x: u32`.
1039    ///
1040    /// To allow both uses to work, we need to have more than a single scope
1041    /// for a local. We have the `source_info.scope` represent the "syntactic"
1042    /// lint scope (with a variable being under its let block) while the
1043    /// `var_debug_info.source_info.scope` represents the "local variable"
1044    /// scope (where the "rest" of a block is under all prior let-statements).
1045    ///
1046    /// The end result looks like this:
1047    ///
1048    /// ```text
1049    /// ROOT SCOPE
1050    ///  │{ argument x: &str }
1051    ///  │
1052    ///  │ │{ #[allow(unused_mut)] } // This is actually split into 2 scopes
1053    ///  │ │                         // in practice because I'm lazy.
1054    ///  │ │
1055    ///  │ │← x.source_info.scope
1056    ///  │ │← `x.parse().unwrap()`
1057    ///  │ │
1058    ///  │ │ │← y.source_info.scope
1059    ///  │ │
1060    ///  │ │ │{ let y: u32 }
1061    ///  │ │ │
1062    ///  │ │ │← y.var_debug_info.source_info.scope
1063    ///  │ │ │← `y + 2`
1064    ///  │
1065    ///  │ │{ let x: u32 }
1066    ///  │ │← x.var_debug_info.source_info.scope
1067    ///  │ │← `drop(x)` // This accesses `x: u32`.
1068    /// ```
1069    pub source_info: SourceInfo,
1070}
1071
1072/// Extra information about a some locals that's used for diagnostics and for
1073/// classifying variables into local variables, statics, etc, which is needed e.g.
1074/// for borrow checking.
1075///
1076/// Not used for non-StaticRef temporaries, the return place, or anonymous
1077/// function parameters.
1078#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1079pub enum LocalInfo<'tcx> {
1080    /// A user-defined local variable or function parameter
1081    ///
1082    /// The `BindingForm` is solely used for local diagnostics when generating
1083    /// warnings/errors when compiling the current crate, and therefore it need
1084    /// not be visible across crates.
1085    User(BindingForm<'tcx>),
1086    /// A temporary created that references the static with the given `DefId`.
1087    StaticRef { def_id: DefId, is_thread_local: bool },
1088    /// A temporary created that references the const with the given `DefId`
1089    ConstRef { def_id: DefId },
1090    /// A temporary created during the creation of an aggregate
1091    /// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`)
1092    AggregateTemp,
1093    /// A temporary created for evaluation of some subexpression of some block's tail expression
1094    /// (with no intervening statement context).
1095    // FIXME(matthewjasper) Don't store in this in `Body`
1096    BlockTailTemp(BlockTailInfo),
1097    /// A temporary created during evaluating `if` predicate, possibly for pattern matching for `let`s,
1098    /// and subject to Edition 2024 temporary lifetime rules
1099    IfThenRescopeTemp { if_then: HirId },
1100    /// A temporary created during the pass `Derefer` to avoid it's retagging
1101    DerefTemp,
1102    /// A temporary created for borrow checking.
1103    FakeBorrow,
1104    /// A local without anything interesting about it.
1105    Boring,
1106}
1107
1108impl<'tcx> LocalDecl<'tcx> {
1109    pub fn local_info(&self) -> &LocalInfo<'tcx> {
1110        self.local_info.as_ref().assert_crate_local()
1111    }
1112
1113    /// Returns `true` only if local is a binding that can itself be
1114    /// made mutable via the addition of the `mut` keyword, namely
1115    /// something like the occurrences of `x` in:
1116    /// - `fn foo(x: Type) { ... }`,
1117    /// - `let x = ...`,
1118    /// - or `match ... { C(x) => ... }`
1119    pub fn can_be_made_mutable(&self) -> bool {
1120        matches!(
1121            self.local_info(),
1122            LocalInfo::User(
1123                BindingForm::Var(VarBindingForm {
1124                    binding_mode: BindingMode(ByRef::No, _),
1125                    opt_ty_info: _,
1126                    opt_match_place: _,
1127                    pat_span: _,
1128                }) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
1129            )
1130        )
1131    }
1132
1133    /// Returns `true` if local is definitely not a `ref ident` or
1134    /// `ref mut ident` binding. (Such bindings cannot be made into
1135    /// mutable bindings, but the inverse does not necessarily hold).
1136    pub fn is_nonref_binding(&self) -> bool {
1137        matches!(
1138            self.local_info(),
1139            LocalInfo::User(
1140                BindingForm::Var(VarBindingForm {
1141                    binding_mode: BindingMode(ByRef::No, _),
1142                    opt_ty_info: _,
1143                    opt_match_place: _,
1144                    pat_span: _,
1145                }) | BindingForm::ImplicitSelf(_),
1146            )
1147        )
1148    }
1149
1150    /// Returns `true` if this variable is a named variable or function
1151    /// parameter declared by the user.
1152    #[inline]
1153    pub fn is_user_variable(&self) -> bool {
1154        matches!(self.local_info(), LocalInfo::User(_))
1155    }
1156
1157    /// Returns `true` if this is a reference to a variable bound in a `match`
1158    /// expression that is used to access said variable for the guard of the
1159    /// match arm.
1160    pub fn is_ref_for_guard(&self) -> bool {
1161        matches!(self.local_info(), LocalInfo::User(BindingForm::RefForGuard))
1162    }
1163
1164    /// Returns `Some` if this is a reference to a static item that is used to
1165    /// access that static.
1166    pub fn is_ref_to_static(&self) -> bool {
1167        matches!(self.local_info(), LocalInfo::StaticRef { .. })
1168    }
1169
1170    /// Returns `Some` if this is a reference to a thread-local static item that is used to
1171    /// access that static.
1172    pub fn is_ref_to_thread_local(&self) -> bool {
1173        match self.local_info() {
1174            LocalInfo::StaticRef { is_thread_local, .. } => *is_thread_local,
1175            _ => false,
1176        }
1177    }
1178
1179    /// Returns `true` if this is a DerefTemp
1180    pub fn is_deref_temp(&self) -> bool {
1181        match self.local_info() {
1182            LocalInfo::DerefTemp => true,
1183            _ => false,
1184        }
1185    }
1186
1187    /// Returns `true` is the local is from a compiler desugaring, e.g.,
1188    /// `__next` from a `for` loop.
1189    #[inline]
1190    pub fn from_compiler_desugaring(&self) -> bool {
1191        self.source_info.span.desugaring_kind().is_some()
1192    }
1193
1194    /// Creates a new `LocalDecl` for a temporary, mutable.
1195    #[inline]
1196    pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
1197        Self::with_source_info(ty, SourceInfo::outermost(span))
1198    }
1199
1200    /// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
1201    #[inline]
1202    pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
1203        LocalDecl {
1204            mutability: Mutability::Mut,
1205            local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)),
1206            ty,
1207            user_ty: None,
1208            source_info,
1209        }
1210    }
1211
1212    /// Converts `self` into same `LocalDecl` except tagged as immutable.
1213    #[inline]
1214    pub fn immutable(mut self) -> Self {
1215        self.mutability = Mutability::Not;
1216        self
1217    }
1218}
1219
1220#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1221pub enum VarDebugInfoContents<'tcx> {
1222    /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
1223    Place(Place<'tcx>),
1224    Const(ConstOperand<'tcx>),
1225}
1226
1227impl<'tcx> Debug for VarDebugInfoContents<'tcx> {
1228    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1229        match self {
1230            VarDebugInfoContents::Const(c) => write!(fmt, "{c}"),
1231            VarDebugInfoContents::Place(p) => write!(fmt, "{p:?}"),
1232        }
1233    }
1234}
1235
1236#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1237pub struct VarDebugInfoFragment<'tcx> {
1238    /// Type of the original user variable.
1239    /// This cannot contain a union or an enum.
1240    pub ty: Ty<'tcx>,
1241
1242    /// Where in the composite user variable this fragment is,
1243    /// represented as a "projection" into the composite variable.
1244    /// At lower levels, this corresponds to a byte/bit range.
1245    ///
1246    /// This can only contain `PlaceElem::Field`.
1247    // FIXME support this for `enum`s by either using DWARF's
1248    // more advanced control-flow features (unsupported by LLVM?)
1249    // to match on the discriminant, or by using custom type debuginfo
1250    // with non-overlapping variants for the composite variable.
1251    pub projection: Vec<PlaceElem<'tcx>>,
1252}
1253
1254/// Debug information pertaining to a user variable.
1255#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1256pub struct VarDebugInfo<'tcx> {
1257    pub name: Symbol,
1258
1259    /// Source info of the user variable, including the scope
1260    /// within which the variable is visible (to debuginfo)
1261    /// (see `LocalDecl`'s `source_info` field for more details).
1262    pub source_info: SourceInfo,
1263
1264    /// The user variable's data is split across several fragments,
1265    /// each described by a `VarDebugInfoFragment`.
1266    /// See DWARF 5's "2.6.1.2 Composite Location Descriptions"
1267    /// and LLVM's `DW_OP_LLVM_fragment` for more details on
1268    /// the underlying debuginfo feature this relies on.
1269    pub composite: Option<Box<VarDebugInfoFragment<'tcx>>>,
1270
1271    /// Where the data for this user variable is to be found.
1272    pub value: VarDebugInfoContents<'tcx>,
1273
1274    /// When present, indicates what argument number this variable is in the function that it
1275    /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
1276    /// argument number in the original function before it was inlined.
1277    pub argument_index: Option<u16>,
1278}
1279
1280///////////////////////////////////////////////////////////////////////////
1281// BasicBlock
1282
1283rustc_index::newtype_index! {
1284    /// A node in the MIR [control-flow graph][CFG].
1285    ///
1286    /// There are no branches (e.g., `if`s, function calls, etc.) within a basic block, which makes
1287    /// it easier to do [data-flow analyses] and optimizations. Instead, branches are represented
1288    /// as an edge in a graph between basic blocks.
1289    ///
1290    /// Basic blocks consist of a series of [statements][Statement], ending with a
1291    /// [terminator][Terminator]. Basic blocks can have multiple predecessors and successors,
1292    /// however there is a MIR pass ([`CriticalCallEdges`]) that removes *critical edges*, which
1293    /// are edges that go from a multi-successor node to a multi-predecessor node. This pass is
1294    /// needed because some analyses require that there are no critical edges in the CFG.
1295    ///
1296    /// Note that this type is just an index into [`Body.basic_blocks`](Body::basic_blocks);
1297    /// the actual data that a basic block holds is in [`BasicBlockData`].
1298    ///
1299    /// Read more about basic blocks in the [rustc-dev-guide][guide-mir].
1300    ///
1301    /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
1302    /// [data-flow analyses]:
1303    ///     https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
1304    /// [`CriticalCallEdges`]: ../../rustc_mir_transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
1305    /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
1306    #[derive(HashStable)]
1307    #[encodable]
1308    #[orderable]
1309    #[debug_format = "bb{}"]
1310    pub struct BasicBlock {
1311        const START_BLOCK = 0;
1312    }
1313}
1314
1315impl BasicBlock {
1316    pub fn start_location(self) -> Location {
1317        Location { block: self, statement_index: 0 }
1318    }
1319}
1320
1321///////////////////////////////////////////////////////////////////////////
1322// BasicBlockData
1323
1324/// Data for a basic block, including a list of its statements.
1325///
1326/// See [`BasicBlock`] for documentation on what basic blocks are at a high level.
1327#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1328pub struct BasicBlockData<'tcx> {
1329    /// List of statements in this block.
1330    pub statements: Vec<Statement<'tcx>>,
1331
1332    /// Terminator for this block.
1333    ///
1334    /// N.B., this should generally ONLY be `None` during construction.
1335    /// Therefore, you should generally access it via the
1336    /// `terminator()` or `terminator_mut()` methods. The only
1337    /// exception is that certain passes, such as `simplify_cfg`, swap
1338    /// out the terminator temporarily with `None` while they continue
1339    /// to recurse over the set of basic blocks.
1340    pub terminator: Option<Terminator<'tcx>>,
1341
1342    /// If true, this block lies on an unwind path. This is used
1343    /// during codegen where distinct kinds of basic blocks may be
1344    /// generated (particularly for MSVC cleanup). Unwind blocks must
1345    /// only branch to other unwind blocks.
1346    pub is_cleanup: bool,
1347}
1348
1349impl<'tcx> BasicBlockData<'tcx> {
1350    pub fn new(terminator: Option<Terminator<'tcx>>, is_cleanup: bool) -> BasicBlockData<'tcx> {
1351        BasicBlockData { statements: vec![], terminator, is_cleanup }
1352    }
1353
1354    /// Accessor for terminator.
1355    ///
1356    /// Terminator may not be None after construction of the basic block is complete. This accessor
1357    /// provides a convenient way to reach the terminator.
1358    #[inline]
1359    pub fn terminator(&self) -> &Terminator<'tcx> {
1360        self.terminator.as_ref().expect("invalid terminator state")
1361    }
1362
1363    #[inline]
1364    pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
1365        self.terminator.as_mut().expect("invalid terminator state")
1366    }
1367
1368    pub fn retain_statements<F>(&mut self, mut f: F)
1369    where
1370        F: FnMut(&mut Statement<'_>) -> bool,
1371    {
1372        for s in &mut self.statements {
1373            if !f(s) {
1374                s.make_nop();
1375            }
1376        }
1377    }
1378
1379    pub fn expand_statements<F, I>(&mut self, mut f: F)
1380    where
1381        F: FnMut(&mut Statement<'tcx>) -> Option<I>,
1382        I: iter::TrustedLen<Item = Statement<'tcx>>,
1383    {
1384        // Gather all the iterators we'll need to splice in, and their positions.
1385        let mut splices: Vec<(usize, I)> = vec![];
1386        let mut extra_stmts = 0;
1387        for (i, s) in self.statements.iter_mut().enumerate() {
1388            if let Some(mut new_stmts) = f(s) {
1389                if let Some(first) = new_stmts.next() {
1390                    // We can already store the first new statement.
1391                    *s = first;
1392
1393                    // Save the other statements for optimized splicing.
1394                    let remaining = new_stmts.size_hint().0;
1395                    if remaining > 0 {
1396                        splices.push((i + 1 + extra_stmts, new_stmts));
1397                        extra_stmts += remaining;
1398                    }
1399                } else {
1400                    s.make_nop();
1401                }
1402            }
1403        }
1404
1405        // Splice in the new statements, from the end of the block.
1406        // FIXME(eddyb) This could be more efficient with a "gap buffer"
1407        // where a range of elements ("gap") is left uninitialized, with
1408        // splicing adding new elements to the end of that gap and moving
1409        // existing elements from before the gap to the end of the gap.
1410        // For now, this is safe code, emulating a gap but initializing it.
1411        let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
1412        self.statements.resize(
1413            gap.end,
1414            Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
1415        );
1416        for (splice_start, new_stmts) in splices.into_iter().rev() {
1417            let splice_end = splice_start + new_stmts.size_hint().0;
1418            while gap.end > splice_end {
1419                gap.start -= 1;
1420                gap.end -= 1;
1421                self.statements.swap(gap.start, gap.end);
1422            }
1423            self.statements.splice(splice_start..splice_end, new_stmts);
1424            gap.end = splice_start;
1425        }
1426    }
1427
1428    pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
1429        if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
1430    }
1431
1432    /// Does the block have no statements and an unreachable terminator?
1433    #[inline]
1434    pub fn is_empty_unreachable(&self) -> bool {
1435        self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable)
1436    }
1437
1438    /// Like [`Terminator::successors`] but tries to use information available from the [`Instance`]
1439    /// to skip successors like the `false` side of an `if const {`.
1440    ///
1441    /// This is used to implement [`traversal::mono_reachable`] and
1442    /// [`traversal::mono_reachable_reverse_postorder`].
1443    pub fn mono_successors(&self, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Successors<'_> {
1444        if let Some((bits, targets)) = Body::try_const_mono_switchint(tcx, instance, self) {
1445            targets.successors_for_value(bits)
1446        } else {
1447            self.terminator().successors()
1448        }
1449    }
1450}
1451
1452///////////////////////////////////////////////////////////////////////////
1453// Scopes
1454
1455rustc_index::newtype_index! {
1456    #[derive(HashStable)]
1457    #[encodable]
1458    #[debug_format = "scope[{}]"]
1459    pub struct SourceScope {
1460        const OUTERMOST_SOURCE_SCOPE = 0;
1461    }
1462}
1463
1464impl SourceScope {
1465    /// Finds the original HirId this MIR item came from.
1466    /// This is necessary after MIR optimizations, as otherwise we get a HirId
1467    /// from the function that was inlined instead of the function call site.
1468    pub fn lint_root(
1469        self,
1470        source_scopes: &IndexSlice<SourceScope, SourceScopeData<'_>>,
1471    ) -> Option<HirId> {
1472        let mut data = &source_scopes[self];
1473        // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it
1474        // does not work as I thought it would. Needs more investigation and documentation.
1475        while data.inlined.is_some() {
1476            trace!(?data);
1477            data = &source_scopes[data.parent_scope.unwrap()];
1478        }
1479        trace!(?data);
1480        match &data.local_data {
1481            ClearCrossCrate::Set(data) => Some(data.lint_root),
1482            ClearCrossCrate::Clear => None,
1483        }
1484    }
1485
1486    /// The instance this source scope was inlined from, if any.
1487    #[inline]
1488    pub fn inlined_instance<'tcx>(
1489        self,
1490        source_scopes: &IndexSlice<SourceScope, SourceScopeData<'tcx>>,
1491    ) -> Option<ty::Instance<'tcx>> {
1492        let scope_data = &source_scopes[self];
1493        if let Some((inlined_instance, _)) = scope_data.inlined {
1494            Some(inlined_instance)
1495        } else if let Some(inlined_scope) = scope_data.inlined_parent_scope {
1496            Some(source_scopes[inlined_scope].inlined.unwrap().0)
1497        } else {
1498            None
1499        }
1500    }
1501}
1502
1503#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1504pub struct SourceScopeData<'tcx> {
1505    pub span: Span,
1506    pub parent_scope: Option<SourceScope>,
1507
1508    /// Whether this scope is the root of a scope tree of another body,
1509    /// inlined into this body by the MIR inliner.
1510    /// `ty::Instance` is the callee, and the `Span` is the call site.
1511    pub inlined: Option<(ty::Instance<'tcx>, Span)>,
1512
1513    /// Nearest (transitive) parent scope (if any) which is inlined.
1514    /// This is an optimization over walking up `parent_scope`
1515    /// until a scope with `inlined: Some(...)` is found.
1516    pub inlined_parent_scope: Option<SourceScope>,
1517
1518    /// Crate-local information for this source scope, that can't (and
1519    /// needn't) be tracked across crates.
1520    pub local_data: ClearCrossCrate<SourceScopeLocalData>,
1521}
1522
1523#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
1524pub struct SourceScopeLocalData {
1525    /// An `HirId` with lint levels equivalent to this scope's lint levels.
1526    pub lint_root: HirId,
1527}
1528
1529/// A collection of projections into user types.
1530///
1531/// They are projections because a binding can occur a part of a
1532/// parent pattern that has been ascribed a type.
1533///
1534/// It's a collection because there can be multiple type ascriptions on
1535/// the path from the root of the pattern down to the binding itself.
1536///
1537/// An example:
1538///
1539/// ```ignore (illustrative)
1540/// struct S<'a>((i32, &'a str), String);
1541/// let S((_, w): (i32, &'static str), _): S = ...;
1542/// //    ------  ^^^^^^^^^^^^^^^^^^^ (1)
1543/// //  ---------------------------------  ^ (2)
1544/// ```
1545///
1546/// The highlights labelled `(1)` show the subpattern `(_, w)` being
1547/// ascribed the type `(i32, &'static str)`.
1548///
1549/// The highlights labelled `(2)` show the whole pattern being
1550/// ascribed the type `S`.
1551///
1552/// In this example, when we descend to `w`, we will have built up the
1553/// following two projected types:
1554///
1555///   * base: `S`,                   projection: `(base.0).1`
1556///   * base: `(i32, &'static str)`, projection: `base.1`
1557///
1558/// The first will lead to the constraint `w: &'1 str` (for some
1559/// inferred region `'1`). The second will lead to the constraint `w:
1560/// &'static str`.
1561#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1562pub struct UserTypeProjections {
1563    pub contents: Vec<(UserTypeProjection, Span)>,
1564}
1565
1566impl<'tcx> UserTypeProjections {
1567    pub fn none() -> Self {
1568        UserTypeProjections { contents: vec![] }
1569    }
1570
1571    pub fn is_empty(&self) -> bool {
1572        self.contents.is_empty()
1573    }
1574
1575    pub fn projections_and_spans(
1576        &self,
1577    ) -> impl Iterator<Item = &(UserTypeProjection, Span)> + ExactSizeIterator {
1578        self.contents.iter()
1579    }
1580
1581    pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator {
1582        self.contents.iter().map(|&(ref user_type, _span)| user_type)
1583    }
1584
1585    pub fn push_projection(mut self, user_ty: &UserTypeProjection, span: Span) -> Self {
1586        self.contents.push((user_ty.clone(), span));
1587        self
1588    }
1589
1590    fn map_projections(
1591        mut self,
1592        mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
1593    ) -> Self {
1594        self.contents = self.contents.into_iter().map(|(proj, span)| (f(proj), span)).collect();
1595        self
1596    }
1597
1598    pub fn index(self) -> Self {
1599        self.map_projections(|pat_ty_proj| pat_ty_proj.index())
1600    }
1601
1602    pub fn subslice(self, from: u64, to: u64) -> Self {
1603        self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
1604    }
1605
1606    pub fn deref(self) -> Self {
1607        self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
1608    }
1609
1610    pub fn leaf(self, field: FieldIdx) -> Self {
1611        self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
1612    }
1613
1614    pub fn variant(
1615        self,
1616        adt_def: AdtDef<'tcx>,
1617        variant_index: VariantIdx,
1618        field_index: FieldIdx,
1619    ) -> Self {
1620        self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field_index))
1621    }
1622}
1623
1624/// Encodes the effect of a user-supplied type annotation on the
1625/// subcomponents of a pattern. The effect is determined by applying the
1626/// given list of projections to some underlying base type. Often,
1627/// the projection element list `projs` is empty, in which case this
1628/// directly encodes a type in `base`. But in the case of complex patterns with
1629/// subpatterns and bindings, we want to apply only a *part* of the type to a variable,
1630/// in which case the `projs` vector is used.
1631///
1632/// Examples:
1633///
1634/// * `let x: T = ...` -- here, the `projs` vector is empty.
1635///
1636/// * `let (x, _): T = ...` -- here, the `projs` vector would contain
1637///   `field[0]` (aka `.0`), indicating that the type of `s` is
1638///   determined by finding the type of the `.0` field from `T`.
1639#[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
1640#[derive(TypeFoldable, TypeVisitable)]
1641pub struct UserTypeProjection {
1642    pub base: UserTypeAnnotationIndex,
1643    pub projs: Vec<ProjectionKind>,
1644}
1645
1646impl UserTypeProjection {
1647    pub(crate) fn index(mut self) -> Self {
1648        self.projs.push(ProjectionElem::Index(()));
1649        self
1650    }
1651
1652    pub(crate) fn subslice(mut self, from: u64, to: u64) -> Self {
1653        self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
1654        self
1655    }
1656
1657    pub(crate) fn deref(mut self) -> Self {
1658        self.projs.push(ProjectionElem::Deref);
1659        self
1660    }
1661
1662    pub(crate) fn leaf(mut self, field: FieldIdx) -> Self {
1663        self.projs.push(ProjectionElem::Field(field, ()));
1664        self
1665    }
1666
1667    pub(crate) fn variant(
1668        mut self,
1669        adt_def: AdtDef<'_>,
1670        variant_index: VariantIdx,
1671        field_index: FieldIdx,
1672    ) -> Self {
1673        self.projs.push(ProjectionElem::Downcast(
1674            Some(adt_def.variant(variant_index).name),
1675            variant_index,
1676        ));
1677        self.projs.push(ProjectionElem::Field(field_index, ()));
1678        self
1679    }
1680}
1681
1682rustc_index::newtype_index! {
1683    #[derive(HashStable)]
1684    #[encodable]
1685    #[orderable]
1686    #[debug_format = "promoted[{}]"]
1687    pub struct Promoted {}
1688}
1689
1690/// `Location` represents the position of the start of the statement; or, if
1691/// `statement_index` equals the number of statements, then the start of the
1692/// terminator.
1693#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
1694pub struct Location {
1695    /// The block that the location is within.
1696    pub block: BasicBlock,
1697
1698    pub statement_index: usize,
1699}
1700
1701impl fmt::Debug for Location {
1702    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1703        write!(fmt, "{:?}[{}]", self.block, self.statement_index)
1704    }
1705}
1706
1707impl Location {
1708    pub const START: Location = Location { block: START_BLOCK, statement_index: 0 };
1709
1710    /// Returns the location immediately after this one within the enclosing block.
1711    ///
1712    /// Note that if this location represents a terminator, then the
1713    /// resulting location would be out of bounds and invalid.
1714    #[inline]
1715    pub fn successor_within_block(&self) -> Location {
1716        Location { block: self.block, statement_index: self.statement_index + 1 }
1717    }
1718
1719    /// Returns `true` if `other` is earlier in the control flow graph than `self`.
1720    pub fn is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool {
1721        // If we are in the same block as the other location and are an earlier statement
1722        // then we are a predecessor of `other`.
1723        if self.block == other.block && self.statement_index < other.statement_index {
1724            return true;
1725        }
1726
1727        let predecessors = body.basic_blocks.predecessors();
1728
1729        // If we're in another block, then we want to check that block is a predecessor of `other`.
1730        let mut queue: Vec<BasicBlock> = predecessors[other.block].to_vec();
1731        let mut visited = FxHashSet::default();
1732
1733        while let Some(block) = queue.pop() {
1734            // If we haven't visited this block before, then make sure we visit its predecessors.
1735            if visited.insert(block) {
1736                queue.extend(predecessors[block].iter().cloned());
1737            } else {
1738                continue;
1739            }
1740
1741            // If we found the block that `self` is in, then we are a predecessor of `other` (since
1742            // we found that block by looking at the predecessors of `other`).
1743            if self.block == block {
1744                return true;
1745            }
1746        }
1747
1748        false
1749    }
1750
1751    #[inline]
1752    pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
1753        if self.block == other.block {
1754            self.statement_index <= other.statement_index
1755        } else {
1756            dominators.dominates(self.block, other.block)
1757        }
1758    }
1759}
1760
1761/// `DefLocation` represents the location of a definition - either an argument or an assignment
1762/// within MIR body.
1763#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1764pub enum DefLocation {
1765    Argument,
1766    Assignment(Location),
1767    CallReturn { call: BasicBlock, target: Option<BasicBlock> },
1768}
1769
1770impl DefLocation {
1771    #[inline]
1772    pub fn dominates(self, location: Location, dominators: &Dominators<BasicBlock>) -> bool {
1773        match self {
1774            DefLocation::Argument => true,
1775            DefLocation::Assignment(def) => {
1776                def.successor_within_block().dominates(location, dominators)
1777            }
1778            DefLocation::CallReturn { target: None, .. } => false,
1779            DefLocation::CallReturn { call, target: Some(target) } => {
1780                // The definition occurs on the call -> target edge. The definition dominates a use
1781                // if and only if the edge is on all paths from the entry to the use.
1782                //
1783                // Note that a call terminator has only one edge that can reach the target, so when
1784                // the call strongly dominates the target, all paths from the entry to the target
1785                // go through the call -> target edge.
1786                call != target
1787                    && dominators.dominates(call, target)
1788                    && dominators.dominates(target, location.block)
1789            }
1790        }
1791    }
1792}
1793
1794/// Checks if the specified `local` is used as the `self` parameter of a method call
1795/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
1796/// returned.
1797pub fn find_self_call<'tcx>(
1798    tcx: TyCtxt<'tcx>,
1799    body: &Body<'tcx>,
1800    local: Local,
1801    block: BasicBlock,
1802) -> Option<(DefId, GenericArgsRef<'tcx>)> {
1803    debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
1804    if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
1805        &body[block].terminator
1806        && let Operand::Constant(box ConstOperand { const_, .. }) = func
1807        && let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
1808        && let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
1809            tcx.opt_associated_item(def_id)
1810        && let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
1811            **args
1812    {
1813        if self_place.as_local() == Some(local) {
1814            return Some((def_id, fn_args));
1815        }
1816
1817        // Handle the case where `self_place` gets reborrowed.
1818        // This happens when the receiver is `&T`.
1819        for stmt in &body[block].statements {
1820            if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
1821                && let Some(reborrow_local) = place.as_local()
1822                && self_place.as_local() == Some(reborrow_local)
1823                && let Rvalue::Ref(_, _, deref_place) = rvalue
1824                && let PlaceRef { local: deref_local, projection: [ProjectionElem::Deref] } =
1825                    deref_place.as_ref()
1826                && deref_local == local
1827            {
1828                return Some((def_id, fn_args));
1829            }
1830        }
1831    }
1832    None
1833}
1834
1835// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
1836#[cfg(target_pointer_width = "64")]
1837mod size_asserts {
1838    use rustc_data_structures::static_assert_size;
1839
1840    use super::*;
1841    // tidy-alphabetical-start
1842    static_assert_size!(BasicBlockData<'_>, 128);
1843    static_assert_size!(LocalDecl<'_>, 40);
1844    static_assert_size!(SourceScopeData<'_>, 64);
1845    static_assert_size!(Statement<'_>, 32);
1846    static_assert_size!(Terminator<'_>, 96);
1847    static_assert_size!(VarDebugInfo<'_>, 88);
1848    // tidy-alphabetical-end
1849}