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