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