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