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