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, Pinnedness};
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::RuntimeChecks(kind), _) => {
653 Some((kind.value(tcx.sess) as u128, targets))
654 }
655 Rvalue::Use(Operand::Constant(constant)) => {
656 let bits = eval_mono_const(constant)?;
657 Some((bits, targets))
658 }
659 _ => None,
660 }
661 }
662
663 /// For a `Location` in this scope, determine what the "caller location" at that point is. This
664 /// is interesting because of inlining: the `#[track_caller]` attribute of inlined functions
665 /// must be honored. Falls back to the `tracked_caller` value for `#[track_caller]` functions,
666 /// or the function's scope.
667 pub fn caller_location_span<T>(
668 &self,
669 mut source_info: SourceInfo,
670 caller_location: Option<T>,
671 tcx: TyCtxt<'tcx>,
672 from_span: impl FnOnce(Span) -> T,
673 ) -> T {
674 loop {
675 let scope_data = &self.source_scopes[source_info.scope];
676
677 if let Some((callee, callsite_span)) = scope_data.inlined {
678 // Stop inside the most nested non-`#[track_caller]` function,
679 // before ever reaching its caller (which is irrelevant).
680 if !callee.def.requires_caller_location(tcx) {
681 return from_span(source_info.span);
682 }
683 source_info.span = callsite_span;
684 }
685
686 // Skip past all of the parents with `inlined: None`.
687 match scope_data.inlined_parent_scope {
688 Some(parent) => source_info.scope = parent,
689 None => break,
690 }
691 }
692
693 // No inlined `SourceScope`s, or all of them were `#[track_caller]`.
694 caller_location.unwrap_or_else(|| from_span(source_info.span))
695 }
696
697 #[track_caller]
698 pub fn set_required_consts(&mut self, required_consts: Vec<ConstOperand<'tcx>>) {
699 assert!(
700 self.required_consts.is_none(),
701 "required_consts for {:?} have already been set",
702 self.source.def_id()
703 );
704 self.required_consts = Some(required_consts);
705 }
706 #[track_caller]
707 pub fn required_consts(&self) -> &[ConstOperand<'tcx>] {
708 match &self.required_consts {
709 Some(l) => l,
710 None => panic!("required_consts for {:?} have not yet been set", self.source.def_id()),
711 }
712 }
713
714 #[track_caller]
715 pub fn set_mentioned_items(&mut self, mentioned_items: Vec<Spanned<MentionedItem<'tcx>>>) {
716 assert!(
717 self.mentioned_items.is_none(),
718 "mentioned_items for {:?} have already been set",
719 self.source.def_id()
720 );
721 self.mentioned_items = Some(mentioned_items);
722 }
723 #[track_caller]
724 pub fn mentioned_items(&self) -> &[Spanned<MentionedItem<'tcx>>] {
725 match &self.mentioned_items {
726 Some(l) => l,
727 None => panic!("mentioned_items for {:?} have not yet been set", self.source.def_id()),
728 }
729 }
730}
731
732impl<'tcx> Index<BasicBlock> for Body<'tcx> {
733 type Output = BasicBlockData<'tcx>;
734
735 #[inline]
736 fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
737 &self.basic_blocks[index]
738 }
739}
740
741impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
742 #[inline]
743 fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
744 &mut self.basic_blocks.as_mut()[index]
745 }
746}
747
748#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
749pub enum ClearCrossCrate<T> {
750 Clear,
751 Set(T),
752}
753
754impl<T> ClearCrossCrate<T> {
755 pub fn as_ref(&self) -> ClearCrossCrate<&T> {
756 match self {
757 ClearCrossCrate::Clear => ClearCrossCrate::Clear,
758 ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
759 }
760 }
761
762 pub fn as_mut(&mut self) -> ClearCrossCrate<&mut T> {
763 match self {
764 ClearCrossCrate::Clear => ClearCrossCrate::Clear,
765 ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
766 }
767 }
768
769 pub fn unwrap_crate_local(self) -> T {
770 match self {
771 ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
772 ClearCrossCrate::Set(v) => v,
773 }
774 }
775}
776
777const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
778const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
779
780impl<'tcx, E: TyEncoder<'tcx>, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> {
781 #[inline]
782 fn encode(&self, e: &mut E) {
783 if E::CLEAR_CROSS_CRATE {
784 return;
785 }
786
787 match *self {
788 ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
789 ClearCrossCrate::Set(ref val) => {
790 TAG_CLEAR_CROSS_CRATE_SET.encode(e);
791 val.encode(e);
792 }
793 }
794 }
795}
796impl<'tcx, D: TyDecoder<'tcx>, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> {
797 #[inline]
798 fn decode(d: &mut D) -> ClearCrossCrate<T> {
799 if D::CLEAR_CROSS_CRATE {
800 return ClearCrossCrate::Clear;
801 }
802
803 let discr = u8::decode(d);
804
805 match discr {
806 TAG_CLEAR_CROSS_CRATE_CLEAR => ClearCrossCrate::Clear,
807 TAG_CLEAR_CROSS_CRATE_SET => {
808 let val = T::decode(d);
809 ClearCrossCrate::Set(val)
810 }
811 tag => panic!("Invalid tag for ClearCrossCrate: {tag:?}"),
812 }
813 }
814}
815
816/// Grouped information about the source code origin of a MIR entity.
817/// Intended to be inspected by diagnostics and debuginfo.
818/// Most passes can work with it as a whole, within a single function.
819// The unofficial Cranelift backend, at least as of #65828, needs `SourceInfo` to implement `Eq` and
820// `Hash`. Please ping @bjorn3 if removing them.
821#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
822pub struct SourceInfo {
823 /// The source span for the AST pertaining to this MIR entity.
824 pub span: Span,
825
826 /// The source scope, keeping track of which bindings can be
827 /// seen by debuginfo, active lint levels, etc.
828 pub scope: SourceScope,
829}
830
831impl SourceInfo {
832 #[inline]
833 pub fn outermost(span: Span) -> Self {
834 SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }
835 }
836}
837
838///////////////////////////////////////////////////////////////////////////
839// Variables and temps
840
841rustc_index::newtype_index! {
842 #[derive(HashStable)]
843 #[encodable]
844 #[orderable]
845 #[debug_format = "_{}"]
846 pub struct Local {
847 const RETURN_PLACE = 0;
848 }
849}
850
851impl Atom for Local {
852 fn index(self) -> usize {
853 Idx::index(self)
854 }
855}
856
857/// Classifies locals into categories. See `Body::local_kind`.
858#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
859pub enum LocalKind {
860 /// User-declared variable binding or compiler-introduced temporary.
861 Temp,
862 /// Function argument.
863 Arg,
864 /// Location of function's return value.
865 ReturnPointer,
866}
867
868#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
869pub struct VarBindingForm<'tcx> {
870 /// Is variable bound via `x`, `mut x`, `ref x`, `ref mut x`, `mut ref x`, or `mut ref mut x`?
871 pub binding_mode: BindingMode,
872 /// If an explicit type was provided for this variable binding,
873 /// this holds the source Span of that type.
874 ///
875 /// NOTE: if you want to change this to a `HirId`, be wary that
876 /// doing so breaks incremental compilation (as of this writing),
877 /// while a `Span` does not cause our tests to fail.
878 pub opt_ty_info: Option<Span>,
879 /// Place of the RHS of the =, or the subject of the `match` where this
880 /// variable is initialized. None in the case of `let PATTERN;`.
881 /// Some((None, ..)) in the case of and `let [mut] x = ...` because
882 /// (a) the right-hand side isn't evaluated as a place expression.
883 /// (b) it gives a way to separate this case from the remaining cases
884 /// for diagnostics.
885 pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
886 /// The span of the pattern in which this variable was bound.
887 pub pat_span: Span,
888 /// A binding can be introduced multiple times, with or patterns:
889 /// `Foo::A { x } | Foo::B { z: x }`. This stores information for each of those introductions.
890 pub introductions: Vec<VarBindingIntroduction>,
891}
892
893#[derive(Clone, Debug, TyEncodable, TyDecodable)]
894pub enum BindingForm<'tcx> {
895 /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
896 Var(VarBindingForm<'tcx>),
897 /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
898 ImplicitSelf(ImplicitSelfKind),
899 /// Reference used in a guard expression to ensure immutability.
900 RefForGuard(Local),
901}
902
903#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
904pub struct VarBindingIntroduction {
905 /// Where this additional introduction happened.
906 pub span: Span,
907 /// Is that introduction a shorthand struct pattern, i.e. `Foo { x }`.
908 pub is_shorthand: bool,
909}
910
911mod binding_form_impl {
912 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
913 use rustc_query_system::ich::StableHashingContext;
914
915 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for super::BindingForm<'tcx> {
916 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
917 use super::BindingForm::*;
918 std::mem::discriminant(self).hash_stable(hcx, hasher);
919
920 match self {
921 Var(binding) => binding.hash_stable(hcx, hasher),
922 ImplicitSelf(kind) => kind.hash_stable(hcx, hasher),
923 RefForGuard(local) => local.hash_stable(hcx, hasher),
924 }
925 }
926 }
927}
928
929/// `BlockTailInfo` is attached to the `LocalDecl` for temporaries
930/// created during evaluation of expressions in a block tail
931/// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`.
932///
933/// It is used to improve diagnostics when such temporaries are
934/// involved in borrow_check errors, e.g., explanations of where the
935/// temporaries come from, when their destructors are run, and/or how
936/// one might revise the code to satisfy the borrow checker's rules.
937#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
938pub struct BlockTailInfo {
939 /// If `true`, then the value resulting from evaluating this tail
940 /// expression is ignored by the block's expression context.
941 ///
942 /// Examples include `{ ...; tail };` and `let _ = { ...; tail };`
943 /// but not e.g., `let _x = { ...; tail };`
944 pub tail_result_is_ignored: bool,
945
946 /// `Span` of the tail expression.
947 pub span: Span,
948}
949
950/// A MIR local.
951///
952/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
953/// argument, or the return place.
954#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
955pub struct LocalDecl<'tcx> {
956 /// Whether this is a mutable binding (i.e., `let x` or `let mut x`).
957 ///
958 /// Temporaries and the return place are always mutable.
959 pub mutability: Mutability,
960
961 pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>,
962
963 /// The type of this local.
964 pub ty: Ty<'tcx>,
965
966 /// If the user manually ascribed a type to this variable,
967 /// e.g., via `let x: T`, then we carry that type here. The MIR
968 /// borrow checker needs this information since it can affect
969 /// region inference.
970 pub user_ty: Option<Box<UserTypeProjections>>,
971
972 /// The *syntactic* (i.e., not visibility) source scope the local is defined
973 /// in. If the local was defined in a let-statement, this
974 /// is *within* the let-statement, rather than outside
975 /// of it.
976 ///
977 /// This is needed because the visibility source scope of locals within
978 /// a let-statement is weird.
979 ///
980 /// The reason is that we want the local to be *within* the let-statement
981 /// for lint purposes, but we want the local to be *after* the let-statement
982 /// for names-in-scope purposes.
983 ///
984 /// That's it, if we have a let-statement like the one in this
985 /// function:
986 ///
987 /// ```
988 /// fn foo(x: &str) {
989 /// #[allow(unused_mut)]
990 /// let mut x: u32 = {
991 /// //^ one unused mut
992 /// let mut y: u32 = x.parse().unwrap();
993 /// y + 2
994 /// };
995 /// drop(x);
996 /// }
997 /// ```
998 ///
999 /// Then, from a lint point of view, the declaration of `x: u32`
1000 /// (and `y: u32`) are within the `#[allow(unused_mut)]` scope - the
1001 /// lint scopes are the same as the AST/HIR nesting.
1002 ///
1003 /// However, from a name lookup point of view, the scopes look more like
1004 /// as if the let-statements were `match` expressions:
1005 ///
1006 /// ```
1007 /// fn foo(x: &str) {
1008 /// match {
1009 /// match x.parse::<u32>().unwrap() {
1010 /// y => y + 2
1011 /// }
1012 /// } {
1013 /// x => drop(x)
1014 /// };
1015 /// }
1016 /// ```
1017 ///
1018 /// We care about the name-lookup scopes for debuginfo - if the
1019 /// debuginfo instruction pointer is at the call to `x.parse()`, we
1020 /// want `x` to refer to `x: &str`, but if it is at the call to
1021 /// `drop(x)`, we want it to refer to `x: u32`.
1022 ///
1023 /// To allow both uses to work, we need to have more than a single scope
1024 /// for a local. We have the `source_info.scope` represent the "syntactic"
1025 /// lint scope (with a variable being under its let block) while the
1026 /// `var_debug_info.source_info.scope` represents the "local variable"
1027 /// scope (where the "rest" of a block is under all prior let-statements).
1028 ///
1029 /// The end result looks like this:
1030 ///
1031 /// ```text
1032 /// ROOT SCOPE
1033 /// │{ argument x: &str }
1034 /// │
1035 /// │ │{ #[allow(unused_mut)] } // This is actually split into 2 scopes
1036 /// │ │ // in practice because I'm lazy.
1037 /// │ │
1038 /// │ │← x.source_info.scope
1039 /// │ │← `x.parse().unwrap()`
1040 /// │ │
1041 /// │ │ │← y.source_info.scope
1042 /// │ │
1043 /// │ │ │{ let y: u32 }
1044 /// │ │ │
1045 /// │ │ │← y.var_debug_info.source_info.scope
1046 /// │ │ │← `y + 2`
1047 /// │
1048 /// │ │{ let x: u32 }
1049 /// │ │← x.var_debug_info.source_info.scope
1050 /// │ │← `drop(x)` // This accesses `x: u32`.
1051 /// ```
1052 pub source_info: SourceInfo,
1053}
1054
1055/// Extra information about a some locals that's used for diagnostics and for
1056/// classifying variables into local variables, statics, etc, which is needed e.g.
1057/// for borrow checking.
1058///
1059/// Not used for non-StaticRef temporaries, the return place, or anonymous
1060/// function parameters.
1061#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1062pub enum LocalInfo<'tcx> {
1063 /// A user-defined local variable or function parameter
1064 ///
1065 /// The `BindingForm` is solely used for local diagnostics when generating
1066 /// warnings/errors when compiling the current crate, and therefore it need
1067 /// not be visible across crates.
1068 User(BindingForm<'tcx>),
1069 /// A temporary created that references the static with the given `DefId`.
1070 StaticRef { def_id: DefId, is_thread_local: bool },
1071 /// A temporary created that references the const with the given `DefId`
1072 ConstRef { def_id: DefId },
1073 /// A temporary created during the creation of an aggregate
1074 /// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`)
1075 AggregateTemp,
1076 /// A temporary created for evaluation of some subexpression of some block's tail expression
1077 /// (with no intervening statement context).
1078 BlockTailTemp(BlockTailInfo),
1079 /// A temporary created during evaluating `if` predicate, possibly for pattern matching for `let`s,
1080 /// and subject to Edition 2024 temporary lifetime rules
1081 IfThenRescopeTemp { if_then: HirId },
1082 /// A temporary created during the pass `Derefer` treated as a transparent alias
1083 /// for the place its copied from by analysis passes such as `AddRetag` and `ElaborateDrops`.
1084 ///
1085 /// It may only be written to by a `CopyForDeref` and otherwise only accessed through a deref.
1086 /// In runtime MIR, it is replaced with a normal `Boring` local.
1087 DerefTemp,
1088 /// A temporary created for borrow checking.
1089 FakeBorrow,
1090 /// A local without anything interesting about it.
1091 Boring,
1092}
1093
1094impl<'tcx> LocalDecl<'tcx> {
1095 pub fn local_info(&self) -> &LocalInfo<'tcx> {
1096 self.local_info.as_ref().unwrap_crate_local()
1097 }
1098
1099 /// Returns `true` only if local is a binding that can itself be
1100 /// made mutable via the addition of the `mut` keyword, namely
1101 /// something like the occurrences of `x` in:
1102 /// - `fn foo(x: Type) { ... }`,
1103 /// - `let x = ...`,
1104 /// - or `match ... { C(x) => ... }`
1105 pub fn can_be_made_mutable(&self) -> bool {
1106 matches!(
1107 self.local_info(),
1108 LocalInfo::User(
1109 BindingForm::Var(VarBindingForm { binding_mode: BindingMode(ByRef::No, _), .. })
1110 | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
1111 )
1112 )
1113 }
1114
1115 /// Returns `true` if local is definitely not a `ref ident` or
1116 /// `ref mut ident` binding. (Such bindings cannot be made into
1117 /// mutable bindings, but the inverse does not necessarily hold).
1118 pub fn is_nonref_binding(&self) -> bool {
1119 matches!(
1120 self.local_info(),
1121 LocalInfo::User(
1122 BindingForm::Var(VarBindingForm { binding_mode: BindingMode(ByRef::No, _), .. })
1123 | BindingForm::ImplicitSelf(_),
1124 )
1125 )
1126 }
1127
1128 /// Returns `true` if this variable is a named variable or function
1129 /// parameter declared by the user.
1130 #[inline]
1131 pub fn is_user_variable(&self) -> bool {
1132 matches!(self.local_info(), LocalInfo::User(_))
1133 }
1134
1135 /// Returns `true` if this is a reference to a variable bound in a `match`
1136 /// expression that is used to access said variable for the guard of the
1137 /// match arm.
1138 pub fn is_ref_for_guard(&self) -> bool {
1139 matches!(self.local_info(), LocalInfo::User(BindingForm::RefForGuard(_)))
1140 }
1141
1142 /// Returns `Some` if this is a reference to a static item that is used to
1143 /// access that static.
1144 pub fn is_ref_to_static(&self) -> bool {
1145 matches!(self.local_info(), LocalInfo::StaticRef { .. })
1146 }
1147
1148 /// Returns `Some` if this is a reference to a thread-local static item that is used to
1149 /// access that static.
1150 pub fn is_ref_to_thread_local(&self) -> bool {
1151 match self.local_info() {
1152 LocalInfo::StaticRef { is_thread_local, .. } => *is_thread_local,
1153 _ => false,
1154 }
1155 }
1156
1157 /// Returns `true` if this is a DerefTemp
1158 pub fn is_deref_temp(&self) -> bool {
1159 match self.local_info() {
1160 LocalInfo::DerefTemp => true,
1161 _ => false,
1162 }
1163 }
1164
1165 /// Returns `true` is the local is from a compiler desugaring, e.g.,
1166 /// `__next` from a `for` loop.
1167 #[inline]
1168 pub fn from_compiler_desugaring(&self) -> bool {
1169 self.source_info.span.desugaring_kind().is_some()
1170 }
1171
1172 /// Creates a new `LocalDecl` for a temporary, mutable.
1173 #[inline]
1174 pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
1175 Self::with_source_info(ty, SourceInfo::outermost(span))
1176 }
1177
1178 /// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
1179 #[inline]
1180 pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
1181 LocalDecl {
1182 mutability: Mutability::Mut,
1183 local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)),
1184 ty,
1185 user_ty: None,
1186 source_info,
1187 }
1188 }
1189
1190 /// Converts `self` into same `LocalDecl` except tagged as immutable.
1191 #[inline]
1192 pub fn immutable(mut self) -> Self {
1193 self.mutability = Mutability::Not;
1194 self
1195 }
1196}
1197
1198#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1199pub enum VarDebugInfoContents<'tcx> {
1200 /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
1201 Place(Place<'tcx>),
1202 Const(ConstOperand<'tcx>),
1203}
1204
1205impl<'tcx> Debug for VarDebugInfoContents<'tcx> {
1206 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1207 match self {
1208 VarDebugInfoContents::Const(c) => write!(fmt, "{c}"),
1209 VarDebugInfoContents::Place(p) => write!(fmt, "{p:?}"),
1210 }
1211 }
1212}
1213
1214#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1215pub struct VarDebugInfoFragment<'tcx> {
1216 /// Type of the original user variable.
1217 /// This cannot contain a union or an enum.
1218 pub ty: Ty<'tcx>,
1219
1220 /// Where in the composite user variable this fragment is,
1221 /// represented as a "projection" into the composite variable.
1222 /// At lower levels, this corresponds to a byte/bit range.
1223 ///
1224 /// This can only contain `PlaceElem::Field`.
1225 // FIXME support this for `enum`s by either using DWARF's
1226 // more advanced control-flow features (unsupported by LLVM?)
1227 // to match on the discriminant, or by using custom type debuginfo
1228 // with non-overlapping variants for the composite variable.
1229 pub projection: Vec<PlaceElem<'tcx>>,
1230}
1231
1232/// Debug information pertaining to a user variable.
1233#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1234pub struct VarDebugInfo<'tcx> {
1235 pub name: Symbol,
1236
1237 /// Source info of the user variable, including the scope
1238 /// within which the variable is visible (to debuginfo)
1239 /// (see `LocalDecl`'s `source_info` field for more details).
1240 pub source_info: SourceInfo,
1241
1242 /// The user variable's data is split across several fragments,
1243 /// each described by a `VarDebugInfoFragment`.
1244 /// See DWARF 5's "2.6.1.2 Composite Location Descriptions"
1245 /// and LLVM's `DW_OP_LLVM_fragment` for more details on
1246 /// the underlying debuginfo feature this relies on.
1247 pub composite: Option<Box<VarDebugInfoFragment<'tcx>>>,
1248
1249 /// Where the data for this user variable is to be found.
1250 pub value: VarDebugInfoContents<'tcx>,
1251
1252 /// When present, indicates what argument number this variable is in the function that it
1253 /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
1254 /// argument number in the original function before it was inlined.
1255 pub argument_index: Option<u16>,
1256}
1257
1258///////////////////////////////////////////////////////////////////////////
1259// BasicBlock
1260
1261rustc_index::newtype_index! {
1262 /// A node in the MIR [control-flow graph][CFG].
1263 ///
1264 /// There are no branches (e.g., `if`s, function calls, etc.) within a basic block, which makes
1265 /// it easier to do [data-flow analyses] and optimizations. Instead, branches are represented
1266 /// as an edge in a graph between basic blocks.
1267 ///
1268 /// Basic blocks consist of a series of [statements][Statement], ending with a
1269 /// [terminator][Terminator]. Basic blocks can have multiple predecessors and successors,
1270 /// however there is a MIR pass ([`CriticalCallEdges`]) that removes *critical edges*, which
1271 /// are edges that go from a multi-successor node to a multi-predecessor node. This pass is
1272 /// needed because some analyses require that there are no critical edges in the CFG.
1273 ///
1274 /// Note that this type is just an index into [`Body.basic_blocks`](Body::basic_blocks);
1275 /// the actual data that a basic block holds is in [`BasicBlockData`].
1276 ///
1277 /// Read more about basic blocks in the [rustc-dev-guide][guide-mir].
1278 ///
1279 /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
1280 /// [data-flow analyses]:
1281 /// https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
1282 /// [`CriticalCallEdges`]: ../../rustc_mir_transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
1283 /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
1284 #[derive(HashStable)]
1285 #[encodable]
1286 #[orderable]
1287 #[debug_format = "bb{}"]
1288 pub struct BasicBlock {
1289 const START_BLOCK = 0;
1290 }
1291}
1292
1293impl BasicBlock {
1294 pub fn start_location(self) -> Location {
1295 Location { block: self, statement_index: 0 }
1296 }
1297}
1298
1299///////////////////////////////////////////////////////////////////////////
1300// BasicBlockData
1301
1302/// Data for a basic block, including a list of its statements.
1303///
1304/// See [`BasicBlock`] for documentation on what basic blocks are at a high level.
1305#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1306#[non_exhaustive]
1307pub struct BasicBlockData<'tcx> {
1308 /// List of statements in this block.
1309 pub statements: Vec<Statement<'tcx>>,
1310
1311 /// All debuginfos happen before the statement.
1312 /// Put debuginfos here when the last statement is eliminated.
1313 pub after_last_stmt_debuginfos: StmtDebugInfos<'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::new_stmts(Vec::new(), terminator, is_cleanup)
1335 }
1336
1337 pub fn new_stmts(
1338 statements: Vec<Statement<'tcx>>,
1339 terminator: Option<Terminator<'tcx>>,
1340 is_cleanup: bool,
1341 ) -> BasicBlockData<'tcx> {
1342 BasicBlockData {
1343 statements,
1344 after_last_stmt_debuginfos: StmtDebugInfos::default(),
1345 terminator,
1346 is_cleanup,
1347 }
1348 }
1349
1350 /// Accessor for terminator.
1351 ///
1352 /// Terminator may not be None after construction of the basic block is complete. This accessor
1353 /// provides a convenient way to reach the terminator.
1354 #[inline]
1355 pub fn terminator(&self) -> &Terminator<'tcx> {
1356 self.terminator.as_ref().expect("invalid terminator state")
1357 }
1358
1359 #[inline]
1360 pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
1361 self.terminator.as_mut().expect("invalid terminator state")
1362 }
1363
1364 /// Does the block have no statements and an unreachable terminator?
1365 #[inline]
1366 pub fn is_empty_unreachable(&self) -> bool {
1367 self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable)
1368 }
1369
1370 /// Like [`Terminator::successors`] but tries to use information available from the [`Instance`]
1371 /// to skip successors like the `false` side of an `if const {`.
1372 ///
1373 /// This is used to implement [`traversal::mono_reachable`] and
1374 /// [`traversal::mono_reachable_reverse_postorder`].
1375 pub fn mono_successors(&self, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Successors<'_> {
1376 if let Some((bits, targets)) = Body::try_const_mono_switchint(tcx, instance, self) {
1377 targets.successors_for_value(bits)
1378 } else {
1379 self.terminator().successors()
1380 }
1381 }
1382
1383 pub fn retain_statements<F>(&mut self, mut f: F)
1384 where
1385 F: FnMut(&Statement<'tcx>) -> bool,
1386 {
1387 // Place debuginfos into the next retained statement,
1388 // this `debuginfos` variable is used to cache debuginfos between two retained statements.
1389 let mut debuginfos = StmtDebugInfos::default();
1390 self.statements.retain_mut(|stmt| {
1391 let retain = f(stmt);
1392 if retain {
1393 stmt.debuginfos.prepend(&mut debuginfos);
1394 } else {
1395 debuginfos.append(&mut stmt.debuginfos);
1396 }
1397 retain
1398 });
1399 self.after_last_stmt_debuginfos.prepend(&mut debuginfos);
1400 }
1401
1402 pub fn strip_nops(&mut self) {
1403 self.retain_statements(|stmt| !matches!(stmt.kind, StatementKind::Nop))
1404 }
1405
1406 pub fn drop_debuginfo(&mut self) {
1407 self.after_last_stmt_debuginfos.drop_debuginfo();
1408 for stmt in self.statements.iter_mut() {
1409 stmt.debuginfos.drop_debuginfo();
1410 }
1411 }
1412}
1413
1414///////////////////////////////////////////////////////////////////////////
1415// Scopes
1416
1417rustc_index::newtype_index! {
1418 #[derive(HashStable)]
1419 #[encodable]
1420 #[debug_format = "scope[{}]"]
1421 pub struct SourceScope {
1422 const OUTERMOST_SOURCE_SCOPE = 0;
1423 }
1424}
1425
1426impl SourceScope {
1427 /// Finds the original HirId this MIR item came from.
1428 /// This is necessary after MIR optimizations, as otherwise we get a HirId
1429 /// from the function that was inlined instead of the function call site.
1430 pub fn lint_root(
1431 self,
1432 source_scopes: &IndexSlice<SourceScope, SourceScopeData<'_>>,
1433 ) -> Option<HirId> {
1434 let mut data = &source_scopes[self];
1435 // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it
1436 // does not work as I thought it would. Needs more investigation and documentation.
1437 while data.inlined.is_some() {
1438 trace!(?data);
1439 data = &source_scopes[data.parent_scope.unwrap()];
1440 }
1441 trace!(?data);
1442 match &data.local_data {
1443 ClearCrossCrate::Set(data) => Some(data.lint_root),
1444 ClearCrossCrate::Clear => None,
1445 }
1446 }
1447
1448 /// The instance this source scope was inlined from, if any.
1449 #[inline]
1450 pub fn inlined_instance<'tcx>(
1451 self,
1452 source_scopes: &IndexSlice<SourceScope, SourceScopeData<'tcx>>,
1453 ) -> Option<ty::Instance<'tcx>> {
1454 let scope_data = &source_scopes[self];
1455 if let Some((inlined_instance, _)) = scope_data.inlined {
1456 Some(inlined_instance)
1457 } else if let Some(inlined_scope) = scope_data.inlined_parent_scope {
1458 Some(source_scopes[inlined_scope].inlined.unwrap().0)
1459 } else {
1460 None
1461 }
1462 }
1463}
1464
1465#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1466pub struct SourceScopeData<'tcx> {
1467 pub span: Span,
1468 pub parent_scope: Option<SourceScope>,
1469
1470 /// Whether this scope is the root of a scope tree of another body,
1471 /// inlined into this body by the MIR inliner.
1472 /// `ty::Instance` is the callee, and the `Span` is the call site.
1473 pub inlined: Option<(ty::Instance<'tcx>, Span)>,
1474
1475 /// Nearest (transitive) parent scope (if any) which is inlined.
1476 /// This is an optimization over walking up `parent_scope`
1477 /// until a scope with `inlined: Some(...)` is found.
1478 pub inlined_parent_scope: Option<SourceScope>,
1479
1480 /// Crate-local information for this source scope, that can't (and
1481 /// needn't) be tracked across crates.
1482 pub local_data: ClearCrossCrate<SourceScopeLocalData>,
1483}
1484
1485#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
1486pub struct SourceScopeLocalData {
1487 /// An `HirId` with lint levels equivalent to this scope's lint levels.
1488 pub lint_root: HirId,
1489}
1490
1491/// A collection of projections into user types.
1492///
1493/// They are projections because a binding can occur a part of a
1494/// parent pattern that has been ascribed a type.
1495///
1496/// It's a collection because there can be multiple type ascriptions on
1497/// the path from the root of the pattern down to the binding itself.
1498///
1499/// An example:
1500///
1501/// ```ignore (illustrative)
1502/// struct S<'a>((i32, &'a str), String);
1503/// let S((_, w): (i32, &'static str), _): S = ...;
1504/// // ------ ^^^^^^^^^^^^^^^^^^^ (1)
1505/// // --------------------------------- ^ (2)
1506/// ```
1507///
1508/// The highlights labelled `(1)` show the subpattern `(_, w)` being
1509/// ascribed the type `(i32, &'static str)`.
1510///
1511/// The highlights labelled `(2)` show the whole pattern being
1512/// ascribed the type `S`.
1513///
1514/// In this example, when we descend to `w`, we will have built up the
1515/// following two projected types:
1516///
1517/// * base: `S`, projection: `(base.0).1`
1518/// * base: `(i32, &'static str)`, projection: `base.1`
1519///
1520/// The first will lead to the constraint `w: &'1 str` (for some
1521/// inferred region `'1`). The second will lead to the constraint `w:
1522/// &'static str`.
1523#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1524pub struct UserTypeProjections {
1525 pub contents: Vec<UserTypeProjection>,
1526}
1527
1528impl UserTypeProjections {
1529 pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator {
1530 self.contents.iter()
1531 }
1532}
1533
1534/// Encodes the effect of a user-supplied type annotation on the
1535/// subcomponents of a pattern. The effect is determined by applying the
1536/// given list of projections to some underlying base type. Often,
1537/// the projection element list `projs` is empty, in which case this
1538/// directly encodes a type in `base`. But in the case of complex patterns with
1539/// subpatterns and bindings, we want to apply only a *part* of the type to a variable,
1540/// in which case the `projs` vector is used.
1541///
1542/// Examples:
1543///
1544/// * `let x: T = ...` -- here, the `projs` vector is empty.
1545///
1546/// * `let (x, _): T = ...` -- here, the `projs` vector would contain
1547/// `field[0]` (aka `.0`), indicating that the type of `s` is
1548/// determined by finding the type of the `.0` field from `T`.
1549#[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
1550#[derive(TypeFoldable, TypeVisitable)]
1551pub struct UserTypeProjection {
1552 pub base: UserTypeAnnotationIndex,
1553 pub projs: Vec<ProjectionKind>,
1554}
1555
1556rustc_index::newtype_index! {
1557 #[derive(HashStable)]
1558 #[encodable]
1559 #[orderable]
1560 #[debug_format = "promoted[{}]"]
1561 pub struct Promoted {}
1562}
1563
1564/// `Location` represents the position of the start of the statement; or, if
1565/// `statement_index` equals the number of statements, then the start of the
1566/// terminator.
1567#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
1568pub struct Location {
1569 /// The block that the location is within.
1570 pub block: BasicBlock,
1571
1572 pub statement_index: usize,
1573}
1574
1575impl fmt::Debug for Location {
1576 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1577 write!(fmt, "{:?}[{}]", self.block, self.statement_index)
1578 }
1579}
1580
1581impl Location {
1582 pub const START: Location = Location { block: START_BLOCK, statement_index: 0 };
1583
1584 /// Returns the location immediately after this one within the enclosing block.
1585 ///
1586 /// Note that if this location represents a terminator, then the
1587 /// resulting location would be out of bounds and invalid.
1588 #[inline]
1589 pub fn successor_within_block(&self) -> Location {
1590 Location { block: self.block, statement_index: self.statement_index + 1 }
1591 }
1592
1593 /// Returns `true` if `other` is earlier in the control flow graph than `self`.
1594 pub fn is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool {
1595 // If we are in the same block as the other location and are an earlier statement
1596 // then we are a predecessor of `other`.
1597 if self.block == other.block && self.statement_index < other.statement_index {
1598 return true;
1599 }
1600
1601 let predecessors = body.basic_blocks.predecessors();
1602
1603 // If we're in another block, then we want to check that block is a predecessor of `other`.
1604 let mut queue: Vec<BasicBlock> = predecessors[other.block].to_vec();
1605 let mut visited = FxHashSet::default();
1606
1607 while let Some(block) = queue.pop() {
1608 // If we haven't visited this block before, then make sure we visit its predecessors.
1609 if visited.insert(block) {
1610 queue.extend(predecessors[block].iter().cloned());
1611 } else {
1612 continue;
1613 }
1614
1615 // If we found the block that `self` is in, then we are a predecessor of `other` (since
1616 // we found that block by looking at the predecessors of `other`).
1617 if self.block == block {
1618 return true;
1619 }
1620 }
1621
1622 false
1623 }
1624
1625 #[inline]
1626 pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
1627 if self.block == other.block {
1628 self.statement_index <= other.statement_index
1629 } else {
1630 dominators.dominates(self.block, other.block)
1631 }
1632 }
1633}
1634
1635/// `DefLocation` represents the location of a definition - either an argument or an assignment
1636/// within MIR body.
1637#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1638pub enum DefLocation {
1639 Argument,
1640 Assignment(Location),
1641 CallReturn { call: BasicBlock, target: Option<BasicBlock> },
1642}
1643
1644impl DefLocation {
1645 #[inline]
1646 pub fn dominates(self, location: Location, dominators: &Dominators<BasicBlock>) -> bool {
1647 match self {
1648 DefLocation::Argument => true,
1649 DefLocation::Assignment(def) => {
1650 def.successor_within_block().dominates(location, dominators)
1651 }
1652 DefLocation::CallReturn { target: None, .. } => false,
1653 DefLocation::CallReturn { call, target: Some(target) } => {
1654 // The definition occurs on the call -> target edge. The definition dominates a use
1655 // if and only if the edge is on all paths from the entry to the use.
1656 //
1657 // Note that a call terminator has only one edge that can reach the target, so when
1658 // the call strongly dominates the target, all paths from the entry to the target
1659 // go through the call -> target edge.
1660 call != target
1661 && dominators.dominates(call, target)
1662 && dominators.dominates(target, location.block)
1663 }
1664 }
1665 }
1666}
1667
1668/// Checks if the specified `local` is used as the `self` parameter of a method call
1669/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
1670/// returned.
1671pub fn find_self_call<'tcx>(
1672 tcx: TyCtxt<'tcx>,
1673 body: &Body<'tcx>,
1674 local: Local,
1675 block: BasicBlock,
1676) -> Option<(DefId, GenericArgsRef<'tcx>)> {
1677 debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
1678 if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
1679 &body[block].terminator
1680 && let Operand::Constant(box ConstOperand { const_, .. }) = func
1681 && let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
1682 && let Some(item) = tcx.opt_associated_item(def_id)
1683 && item.is_method()
1684 && let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
1685 **args
1686 {
1687 if self_place.as_local() == Some(local) {
1688 return Some((def_id, fn_args));
1689 }
1690
1691 // Handle the case where `self_place` gets reborrowed.
1692 // This happens when the receiver is `&T`.
1693 for stmt in &body[block].statements {
1694 if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
1695 && let Some(reborrow_local) = place.as_local()
1696 && self_place.as_local() == Some(reborrow_local)
1697 && let Rvalue::Ref(_, _, deref_place) = rvalue
1698 && let PlaceRef { local: deref_local, projection: [ProjectionElem::Deref] } =
1699 deref_place.as_ref()
1700 && deref_local == local
1701 {
1702 return Some((def_id, fn_args));
1703 }
1704 }
1705 }
1706 None
1707}
1708
1709// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
1710#[cfg(target_pointer_width = "64")]
1711mod size_asserts {
1712 use rustc_data_structures::static_assert_size;
1713
1714 use super::*;
1715 // tidy-alphabetical-start
1716 static_assert_size!(BasicBlockData<'_>, 152);
1717 static_assert_size!(LocalDecl<'_>, 40);
1718 static_assert_size!(SourceScopeData<'_>, 64);
1719 static_assert_size!(Statement<'_>, 56);
1720 static_assert_size!(Terminator<'_>, 96);
1721 static_assert_size!(VarDebugInfo<'_>, 88);
1722 // tidy-alphabetical-end
1723}