• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 use crate::mir::interpret::{
6     AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
7 };
8 use crate::mir::visit::MirVisitable;
9 use crate::ty::codec::{TyDecoder, TyEncoder};
10 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
11 use crate::ty::print::{FmtPrinter, Printer};
12 use crate::ty::visit::TypeVisitableExt;
13 use crate::ty::{self, List, Ty, TyCtxt};
14 use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
15 use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
16 
17 use rustc_data_structures::captures::Captures;
18 use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
19 use rustc_hir::def::{CtorKind, Namespace};
20 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
21 use rustc_hir::{self, GeneratorKind, ImplicitSelfKind};
22 use rustc_hir::{self as hir, HirId};
23 use rustc_session::Session;
24 use rustc_target::abi::{FieldIdx, Size, VariantIdx};
25 
26 use polonius_engine::Atom;
27 pub use rustc_ast::Mutability;
28 use rustc_data_structures::fx::FxHashSet;
29 use rustc_data_structures::graph::dominators::Dominators;
30 use rustc_index::{Idx, IndexSlice, IndexVec};
31 use rustc_serialize::{Decodable, Encodable};
32 use rustc_span::symbol::Symbol;
33 use rustc_span::{Span, DUMMY_SP};
34 
35 use either::Either;
36 
37 use std::borrow::Cow;
38 use std::fmt::{self, Debug, Display, Formatter, Write};
39 use std::ops::{Index, IndexMut};
40 use std::{iter, mem};
41 
42 pub use self::query::*;
43 pub use basic_blocks::BasicBlocks;
44 
45 mod basic_blocks;
46 pub mod coverage;
47 mod generic_graph;
48 pub mod generic_graphviz;
49 pub mod graphviz;
50 pub mod interpret;
51 pub mod mono;
52 pub mod patch;
53 pub mod pretty;
54 mod query;
55 pub mod spanview;
56 mod syntax;
57 pub use syntax::*;
58 pub mod tcx;
59 pub mod terminator;
60 pub use terminator::*;
61 
62 pub mod traversal;
63 mod type_foldable;
64 pub mod visit;
65 
66 pub use self::generic_graph::graphviz_safe_def_name;
67 pub use self::graphviz::write_mir_graphviz;
68 pub use self::pretty::{
69     create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty, PassWhere,
70 };
71 
72 /// Types for locals
73 pub type LocalDecls<'tcx> = IndexSlice<Local, LocalDecl<'tcx>>;
74 
75 pub trait HasLocalDecls<'tcx> {
local_decls(&self) -> &LocalDecls<'tcx>76     fn local_decls(&self) -> &LocalDecls<'tcx>;
77 }
78 
79 impl<'tcx> HasLocalDecls<'tcx> for IndexVec<Local, LocalDecl<'tcx>> {
80     #[inline]
local_decls(&self) -> &LocalDecls<'tcx>81     fn local_decls(&self) -> &LocalDecls<'tcx> {
82         self
83     }
84 }
85 
86 impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
87     #[inline]
local_decls(&self) -> &LocalDecls<'tcx>88     fn local_decls(&self) -> &LocalDecls<'tcx> {
89         self
90     }
91 }
92 
93 impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
94     #[inline]
local_decls(&self) -> &LocalDecls<'tcx>95     fn local_decls(&self) -> &LocalDecls<'tcx> {
96         &self.local_decls
97     }
98 }
99 
100 /// A streamlined trait that you can implement to create a pass; the
101 /// pass will be named after the type, and it will consist of a main
102 /// loop that goes over each available MIR and applies `run_pass`.
103 pub trait MirPass<'tcx> {
name(&self) -> &'static str104     fn name(&self) -> &'static str {
105         let name = std::any::type_name::<Self>();
106         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
107     }
108 
109     /// Returns `true` if this pass is enabled with the current combination of compiler flags.
is_enabled(&self, _sess: &Session) -> bool110     fn is_enabled(&self, _sess: &Session) -> bool {
111         true
112     }
113 
run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>)114     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
115 
is_mir_dump_enabled(&self) -> bool116     fn is_mir_dump_enabled(&self) -> bool {
117         true
118     }
119 }
120 
121 impl MirPhase {
122     /// Gets the index of the current MirPhase within the set of all `MirPhase`s.
123     ///
124     /// FIXME(JakobDegen): Return a `(usize, usize)` instead.
phase_index(&self) -> usize125     pub fn phase_index(&self) -> usize {
126         const BUILT_PHASE_COUNT: usize = 1;
127         const ANALYSIS_PHASE_COUNT: usize = 2;
128         match self {
129             MirPhase::Built => 1,
130             MirPhase::Analysis(analysis_phase) => {
131                 1 + BUILT_PHASE_COUNT + (*analysis_phase as usize)
132             }
133             MirPhase::Runtime(runtime_phase) => {
134                 1 + BUILT_PHASE_COUNT + ANALYSIS_PHASE_COUNT + (*runtime_phase as usize)
135             }
136         }
137     }
138 
139     /// Parses an `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
parse(dialect: String, phase: Option<String>) -> Self140     pub fn parse(dialect: String, phase: Option<String>) -> Self {
141         match &*dialect.to_ascii_lowercase() {
142             "built" => {
143                 assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR");
144                 MirPhase::Built
145             }
146             "analysis" => Self::Analysis(AnalysisPhase::parse(phase)),
147             "runtime" => Self::Runtime(RuntimePhase::parse(phase)),
148             _ => bug!("Unknown MIR dialect: '{}'", dialect),
149         }
150     }
151 }
152 
153 impl AnalysisPhase {
parse(phase: Option<String>) -> Self154     pub fn parse(phase: Option<String>) -> Self {
155         let Some(phase) = phase else {
156             return Self::Initial;
157         };
158 
159         match &*phase.to_ascii_lowercase() {
160             "initial" => Self::Initial,
161             "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
162             _ => bug!("Unknown analysis phase: '{}'", phase),
163         }
164     }
165 }
166 
167 impl RuntimePhase {
parse(phase: Option<String>) -> Self168     pub fn parse(phase: Option<String>) -> Self {
169         let Some(phase) = phase else {
170             return Self::Initial;
171         };
172 
173         match &*phase.to_ascii_lowercase() {
174             "initial" => Self::Initial,
175             "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
176             "optimized" => Self::Optimized,
177             _ => bug!("Unknown runtime phase: '{}'", phase),
178         }
179     }
180 }
181 
182 /// Where a specific `mir::Body` comes from.
183 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
184 #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
185 pub struct MirSource<'tcx> {
186     pub instance: InstanceDef<'tcx>,
187 
188     /// If `Some`, this is a promoted rvalue within the parent function.
189     pub promoted: Option<Promoted>,
190 }
191 
192 impl<'tcx> MirSource<'tcx> {
item(def_id: DefId) -> Self193     pub fn item(def_id: DefId) -> Self {
194         MirSource { instance: InstanceDef::Item(def_id), promoted: None }
195     }
196 
from_instance(instance: InstanceDef<'tcx>) -> Self197     pub fn from_instance(instance: InstanceDef<'tcx>) -> Self {
198         MirSource { instance, promoted: None }
199     }
200 
201     #[inline]
def_id(&self) -> DefId202     pub fn def_id(&self) -> DefId {
203         self.instance.def_id()
204     }
205 }
206 
207 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
208 pub struct GeneratorInfo<'tcx> {
209     /// The yield type of the function, if it is a generator.
210     pub yield_ty: Option<Ty<'tcx>>,
211 
212     /// Generator drop glue.
213     pub generator_drop: Option<Body<'tcx>>,
214 
215     /// The layout of a generator. Produced by the state transformation.
216     pub generator_layout: Option<GeneratorLayout<'tcx>>,
217 
218     /// If this is a generator then record the type of source expression that caused this generator
219     /// to be created.
220     pub generator_kind: GeneratorKind,
221 }
222 
223 /// The lowered representation of a single function.
224 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
225 pub struct Body<'tcx> {
226     /// A list of basic blocks. References to basic block use a newtyped index type [`BasicBlock`]
227     /// that indexes into this vector.
228     pub basic_blocks: BasicBlocks<'tcx>,
229 
230     /// Records how far through the "desugaring and optimization" process this particular
231     /// MIR has traversed. This is particularly useful when inlining, since in that context
232     /// we instantiate the promoted constants and add them to our promoted vector -- but those
233     /// promoted items have already been optimized, whereas ours have not. This field allows
234     /// us to see the difference and forego optimization on the inlined promoted items.
235     pub phase: MirPhase,
236 
237     /// How many passses we have executed since starting the current phase. Used for debug output.
238     pub pass_count: usize,
239 
240     pub source: MirSource<'tcx>,
241 
242     /// A list of source scopes; these are referenced by statements
243     /// and used for debuginfo. Indexed by a `SourceScope`.
244     pub source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
245 
246     pub generator: Option<Box<GeneratorInfo<'tcx>>>,
247 
248     /// Declarations of locals.
249     ///
250     /// The first local is the return value pointer, followed by `arg_count`
251     /// locals for the function arguments, followed by any user-declared
252     /// variables and temporaries.
253     pub local_decls: IndexVec<Local, LocalDecl<'tcx>>,
254 
255     /// User type annotations.
256     pub user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
257 
258     /// The number of arguments this function takes.
259     ///
260     /// Starting at local 1, `arg_count` locals will be provided by the caller
261     /// and can be assumed to be initialized.
262     ///
263     /// If this MIR was built for a constant, this will be 0.
264     pub arg_count: usize,
265 
266     /// Mark an argument local (which must be a tuple) as getting passed as
267     /// its individual components at the LLVM level.
268     ///
269     /// This is used for the "rust-call" ABI.
270     pub spread_arg: Option<Local>,
271 
272     /// Debug information pertaining to user variables, including captures.
273     pub var_debug_info: Vec<VarDebugInfo<'tcx>>,
274 
275     /// A span representing this MIR, for error reporting.
276     pub span: Span,
277 
278     /// Constants that are required to evaluate successfully for this MIR to be well-formed.
279     /// We hold in this field all the constants we are not able to evaluate yet.
280     pub required_consts: Vec<Constant<'tcx>>,
281 
282     /// Does this body use generic parameters. This is used for the `ConstEvaluatable` check.
283     ///
284     /// Note that this does not actually mean that this body is not computable right now.
285     /// The repeat count in the following example is polymorphic, but can still be evaluated
286     /// without knowing anything about the type parameter `T`.
287     ///
288     /// ```rust
289     /// fn test<T>() {
290     ///     let _ = [0; std::mem::size_of::<*mut T>()];
291     /// }
292     /// ```
293     ///
294     /// **WARNING**: Do not change this flags after the MIR was originally created, even if an optimization
295     /// removed the last mention of all generic params. We do not want to rely on optimizations and
296     /// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this.
297     pub is_polymorphic: bool,
298 
299     /// The phase at which this MIR should be "injected" into the compilation process.
300     ///
301     /// Everything that comes before this `MirPhase` should be skipped.
302     ///
303     /// This is only `Some` if the function that this body comes from was annotated with `rustc_custom_mir`.
304     pub injection_phase: Option<MirPhase>,
305 
306     pub tainted_by_errors: Option<ErrorGuaranteed>,
307 }
308 
309 impl<'tcx> Body<'tcx> {
new( source: MirSource<'tcx>, basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>, local_decls: IndexVec<Local, LocalDecl<'tcx>>, user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, arg_count: usize, var_debug_info: Vec<VarDebugInfo<'tcx>>, span: Span, generator_kind: Option<GeneratorKind>, tainted_by_errors: Option<ErrorGuaranteed>, ) -> Self310     pub fn new(
311         source: MirSource<'tcx>,
312         basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
313         source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
314         local_decls: IndexVec<Local, LocalDecl<'tcx>>,
315         user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
316         arg_count: usize,
317         var_debug_info: Vec<VarDebugInfo<'tcx>>,
318         span: Span,
319         generator_kind: Option<GeneratorKind>,
320         tainted_by_errors: Option<ErrorGuaranteed>,
321     ) -> Self {
322         // We need `arg_count` locals, and one for the return place.
323         assert!(
324             local_decls.len() > arg_count,
325             "expected at least {} locals, got {}",
326             arg_count + 1,
327             local_decls.len()
328         );
329 
330         let mut body = Body {
331             phase: MirPhase::Built,
332             pass_count: 0,
333             source,
334             basic_blocks: BasicBlocks::new(basic_blocks),
335             source_scopes,
336             generator: generator_kind.map(|generator_kind| {
337                 Box::new(GeneratorInfo {
338                     yield_ty: None,
339                     generator_drop: None,
340                     generator_layout: None,
341                     generator_kind,
342                 })
343             }),
344             local_decls,
345             user_type_annotations,
346             arg_count,
347             spread_arg: None,
348             var_debug_info,
349             span,
350             required_consts: Vec::new(),
351             is_polymorphic: false,
352             injection_phase: None,
353             tainted_by_errors,
354         };
355         body.is_polymorphic = body.has_non_region_param();
356         body
357     }
358 
359     /// Returns a partially initialized MIR body containing only a list of basic blocks.
360     ///
361     /// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
362     /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
363     /// crate.
new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self364     pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
365         let mut body = Body {
366             phase: MirPhase::Built,
367             pass_count: 0,
368             source: MirSource::item(CRATE_DEF_ID.to_def_id()),
369             basic_blocks: BasicBlocks::new(basic_blocks),
370             source_scopes: IndexVec::new(),
371             generator: None,
372             local_decls: IndexVec::new(),
373             user_type_annotations: IndexVec::new(),
374             arg_count: 0,
375             spread_arg: None,
376             span: DUMMY_SP,
377             required_consts: Vec::new(),
378             var_debug_info: Vec::new(),
379             is_polymorphic: false,
380             injection_phase: None,
381             tainted_by_errors: None,
382         };
383         body.is_polymorphic = body.has_non_region_param();
384         body
385     }
386 
387     #[inline]
basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>388     pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
389         self.basic_blocks.as_mut()
390     }
391 
392     #[inline]
local_kind(&self, local: Local) -> LocalKind393     pub fn local_kind(&self, local: Local) -> LocalKind {
394         let index = local.as_usize();
395         if index == 0 {
396             debug_assert!(
397                 self.local_decls[local].mutability == Mutability::Mut,
398                 "return place should be mutable"
399             );
400 
401             LocalKind::ReturnPointer
402         } else if index < self.arg_count + 1 {
403             LocalKind::Arg
404         } else {
405             LocalKind::Temp
406         }
407     }
408 
409     /// Returns an iterator over all user-declared mutable locals.
410     #[inline]
mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + Captures<'tcx> + 'a411     pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + Captures<'tcx> + 'a {
412         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
413             let local = Local::new(index);
414             let decl = &self.local_decls[local];
415             (decl.is_user_variable() && decl.mutability.is_mut()).then_some(local)
416         })
417     }
418 
419     /// Returns an iterator over all user-declared mutable arguments and locals.
420     #[inline]
mut_vars_and_args_iter<'a>( &'a self, ) -> impl Iterator<Item = Local> + Captures<'tcx> + 'a421     pub fn mut_vars_and_args_iter<'a>(
422         &'a self,
423     ) -> impl Iterator<Item = Local> + Captures<'tcx> + 'a {
424         (1..self.local_decls.len()).filter_map(move |index| {
425             let local = Local::new(index);
426             let decl = &self.local_decls[local];
427             if (decl.is_user_variable() || index < self.arg_count + 1)
428                 && decl.mutability == Mutability::Mut
429             {
430                 Some(local)
431             } else {
432                 None
433             }
434         })
435     }
436 
437     /// Returns an iterator over all function arguments.
438     #[inline]
args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator439     pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
440         (1..self.arg_count + 1).map(Local::new)
441     }
442 
443     /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
444     /// locals that are neither arguments nor the return place).
445     #[inline]
vars_and_temps_iter( &self, ) -> impl DoubleEndedIterator<Item = Local> + ExactSizeIterator446     pub fn vars_and_temps_iter(
447         &self,
448     ) -> impl DoubleEndedIterator<Item = Local> + ExactSizeIterator {
449         (self.arg_count + 1..self.local_decls.len()).map(Local::new)
450     }
451 
452     #[inline]
drain_vars_and_temps<'a>(&'a mut self) -> impl Iterator<Item = LocalDecl<'tcx>> + 'a453     pub fn drain_vars_and_temps<'a>(&'a mut self) -> impl Iterator<Item = LocalDecl<'tcx>> + 'a {
454         self.local_decls.drain(self.arg_count + 1..)
455     }
456 
457     /// Returns the source info associated with `location`.
source_info(&self, location: Location) -> &SourceInfo458     pub fn source_info(&self, location: Location) -> &SourceInfo {
459         let block = &self[location.block];
460         let stmts = &block.statements;
461         let idx = location.statement_index;
462         if idx < stmts.len() {
463             &stmts[idx].source_info
464         } else {
465             assert_eq!(idx, stmts.len());
466             &block.terminator().source_info
467         }
468     }
469 
470     /// Returns the return type; it always return first element from `local_decls` array.
471     #[inline]
return_ty(&self) -> Ty<'tcx>472     pub fn return_ty(&self) -> Ty<'tcx> {
473         self.local_decls[RETURN_PLACE].ty
474     }
475 
476     /// Returns the return type; it always return first element from `local_decls` array.
477     #[inline]
bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>>478     pub fn bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>> {
479         ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty)
480     }
481 
482     /// Gets the location of the terminator for the given block.
483     #[inline]
terminator_loc(&self, bb: BasicBlock) -> Location484     pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
485         Location { block: bb, statement_index: self[bb].statements.len() }
486     }
487 
stmt_at(&self, location: Location) -> Either<&Statement<'tcx>, &Terminator<'tcx>>488     pub fn stmt_at(&self, location: Location) -> Either<&Statement<'tcx>, &Terminator<'tcx>> {
489         let Location { block, statement_index } = location;
490         let block_data = &self.basic_blocks[block];
491         block_data
492             .statements
493             .get(statement_index)
494             .map(Either::Left)
495             .unwrap_or_else(|| Either::Right(block_data.terminator()))
496     }
497 
498     #[inline]
yield_ty(&self) -> Option<Ty<'tcx>>499     pub fn yield_ty(&self) -> Option<Ty<'tcx>> {
500         self.generator.as_ref().and_then(|generator| generator.yield_ty)
501     }
502 
503     #[inline]
generator_layout(&self) -> Option<&GeneratorLayout<'tcx>>504     pub fn generator_layout(&self) -> Option<&GeneratorLayout<'tcx>> {
505         self.generator.as_ref().and_then(|generator| generator.generator_layout.as_ref())
506     }
507 
508     #[inline]
generator_drop(&self) -> Option<&Body<'tcx>>509     pub fn generator_drop(&self) -> Option<&Body<'tcx>> {
510         self.generator.as_ref().and_then(|generator| generator.generator_drop.as_ref())
511     }
512 
513     #[inline]
generator_kind(&self) -> Option<GeneratorKind>514     pub fn generator_kind(&self) -> Option<GeneratorKind> {
515         self.generator.as_ref().map(|generator| generator.generator_kind)
516     }
517 
518     #[inline]
should_skip(&self) -> bool519     pub fn should_skip(&self) -> bool {
520         let Some(injection_phase) = self.injection_phase else {
521             return false;
522         };
523         injection_phase > self.phase
524     }
525 
526     #[inline]
is_custom_mir(&self) -> bool527     pub fn is_custom_mir(&self) -> bool {
528         self.injection_phase.is_some()
529     }
530 }
531 
532 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
533 pub enum Safety {
534     Safe,
535     /// Unsafe because of compiler-generated unsafe code, like `await` desugaring
536     BuiltinUnsafe,
537     /// Unsafe because of an unsafe fn
538     FnUnsafe,
539     /// Unsafe because of an `unsafe` block
540     ExplicitUnsafe(hir::HirId),
541 }
542 
543 impl<'tcx> Index<BasicBlock> for Body<'tcx> {
544     type Output = BasicBlockData<'tcx>;
545 
546     #[inline]
index(&self, index: BasicBlock) -> &BasicBlockData<'tcx>547     fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
548         &self.basic_blocks[index]
549     }
550 }
551 
552 impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
553     #[inline]
index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx>554     fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
555         &mut self.basic_blocks.as_mut()[index]
556     }
557 }
558 
559 #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
560 pub enum ClearCrossCrate<T> {
561     Clear,
562     Set(T),
563 }
564 
565 impl<T> ClearCrossCrate<T> {
as_ref(&self) -> ClearCrossCrate<&T>566     pub fn as_ref(&self) -> ClearCrossCrate<&T> {
567         match self {
568             ClearCrossCrate::Clear => ClearCrossCrate::Clear,
569             ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
570         }
571     }
572 
as_mut(&mut self) -> ClearCrossCrate<&mut T>573     pub fn as_mut(&mut self) -> ClearCrossCrate<&mut T> {
574         match self {
575             ClearCrossCrate::Clear => ClearCrossCrate::Clear,
576             ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
577         }
578     }
579 
assert_crate_local(self) -> T580     pub fn assert_crate_local(self) -> T {
581         match self {
582             ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
583             ClearCrossCrate::Set(v) => v,
584         }
585     }
586 }
587 
588 const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
589 const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
590 
591 impl<E: TyEncoder, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> {
592     #[inline]
encode(&self, e: &mut E)593     fn encode(&self, e: &mut E) {
594         if E::CLEAR_CROSS_CRATE {
595             return;
596         }
597 
598         match *self {
599             ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
600             ClearCrossCrate::Set(ref val) => {
601                 TAG_CLEAR_CROSS_CRATE_SET.encode(e);
602                 val.encode(e);
603             }
604         }
605     }
606 }
607 impl<D: TyDecoder, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> {
608     #[inline]
decode(d: &mut D) -> ClearCrossCrate<T>609     fn decode(d: &mut D) -> ClearCrossCrate<T> {
610         if D::CLEAR_CROSS_CRATE {
611             return ClearCrossCrate::Clear;
612         }
613 
614         let discr = u8::decode(d);
615 
616         match discr {
617             TAG_CLEAR_CROSS_CRATE_CLEAR => ClearCrossCrate::Clear,
618             TAG_CLEAR_CROSS_CRATE_SET => {
619                 let val = T::decode(d);
620                 ClearCrossCrate::Set(val)
621             }
622             tag => panic!("Invalid tag for ClearCrossCrate: {:?}", tag),
623         }
624     }
625 }
626 
627 /// Grouped information about the source code origin of a MIR entity.
628 /// Intended to be inspected by diagnostics and debuginfo.
629 /// Most passes can work with it as a whole, within a single function.
630 // The unofficial Cranelift backend, at least as of #65828, needs `SourceInfo` to implement `Eq` and
631 // `Hash`. Please ping @bjorn3 if removing them.
632 #[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
633 pub struct SourceInfo {
634     /// The source span for the AST pertaining to this MIR entity.
635     pub span: Span,
636 
637     /// The source scope, keeping track of which bindings can be
638     /// seen by debuginfo, active lint levels, `unsafe {...}`, etc.
639     pub scope: SourceScope,
640 }
641 
642 impl SourceInfo {
643     #[inline]
outermost(span: Span) -> Self644     pub fn outermost(span: Span) -> Self {
645         SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }
646     }
647 }
648 
649 ///////////////////////////////////////////////////////////////////////////
650 // Variables and temps
651 
652 rustc_index::newtype_index! {
653     #[derive(HashStable)]
654     #[debug_format = "_{}"]
655     pub struct Local {
656         const RETURN_PLACE = 0;
657     }
658 }
659 
660 impl Atom for Local {
index(self) -> usize661     fn index(self) -> usize {
662         Idx::index(self)
663     }
664 }
665 
666 /// Classifies locals into categories. See `Body::local_kind`.
667 #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
668 pub enum LocalKind {
669     /// User-declared variable binding or compiler-introduced temporary.
670     Temp,
671     /// Function argument.
672     Arg,
673     /// Location of function's return value.
674     ReturnPointer,
675 }
676 
677 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
678 pub struct VarBindingForm<'tcx> {
679     /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
680     pub binding_mode: ty::BindingMode,
681     /// If an explicit type was provided for this variable binding,
682     /// this holds the source Span of that type.
683     ///
684     /// NOTE: if you want to change this to a `HirId`, be wary that
685     /// doing so breaks incremental compilation (as of this writing),
686     /// while a `Span` does not cause our tests to fail.
687     pub opt_ty_info: Option<Span>,
688     /// Place of the RHS of the =, or the subject of the `match` where this
689     /// variable is initialized. None in the case of `let PATTERN;`.
690     /// Some((None, ..)) in the case of and `let [mut] x = ...` because
691     /// (a) the right-hand side isn't evaluated as a place expression.
692     /// (b) it gives a way to separate this case from the remaining cases
693     ///     for diagnostics.
694     pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
695     /// The span of the pattern in which this variable was bound.
696     pub pat_span: Span,
697 }
698 
699 #[derive(Clone, Debug, TyEncodable, TyDecodable)]
700 pub enum BindingForm<'tcx> {
701     /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
702     Var(VarBindingForm<'tcx>),
703     /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
704     ImplicitSelf(ImplicitSelfKind),
705     /// Reference used in a guard expression to ensure immutability.
706     RefForGuard,
707 }
708 
709 TrivialTypeTraversalAndLiftImpls! {
710     BindingForm<'tcx>,
711 }
712 
713 mod binding_form_impl {
714     use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
715     use rustc_query_system::ich::StableHashingContext;
716 
717     impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for super::BindingForm<'tcx> {
hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher)718         fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
719             use super::BindingForm::*;
720             std::mem::discriminant(self).hash_stable(hcx, hasher);
721 
722             match self {
723                 Var(binding) => binding.hash_stable(hcx, hasher),
724                 ImplicitSelf(kind) => kind.hash_stable(hcx, hasher),
725                 RefForGuard => (),
726             }
727         }
728     }
729 }
730 
731 /// `BlockTailInfo` is attached to the `LocalDecl` for temporaries
732 /// created during evaluation of expressions in a block tail
733 /// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`.
734 ///
735 /// It is used to improve diagnostics when such temporaries are
736 /// involved in borrow_check errors, e.g., explanations of where the
737 /// temporaries come from, when their destructors are run, and/or how
738 /// one might revise the code to satisfy the borrow checker's rules.
739 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
740 pub struct BlockTailInfo {
741     /// If `true`, then the value resulting from evaluating this tail
742     /// expression is ignored by the block's expression context.
743     ///
744     /// Examples include `{ ...; tail };` and `let _ = { ...; tail };`
745     /// but not e.g., `let _x = { ...; tail };`
746     pub tail_result_is_ignored: bool,
747 
748     /// `Span` of the tail expression.
749     pub span: Span,
750 }
751 
752 /// A MIR local.
753 ///
754 /// This can be a binding declared by the user, a temporary inserted by the compiler, a function
755 /// argument, or the return place.
756 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
757 pub struct LocalDecl<'tcx> {
758     /// Whether this is a mutable binding (i.e., `let x` or `let mut x`).
759     ///
760     /// Temporaries and the return place are always mutable.
761     pub mutability: Mutability,
762 
763     // FIXME(matthewjasper) Don't store in this in `Body`
764     pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>,
765 
766     /// `true` if this is an internal local.
767     ///
768     /// These locals are not based on types in the source code and are only used
769     /// for a few desugarings at the moment.
770     ///
771     /// The generator transformation will sanity check the locals which are live
772     /// across a suspension point against the type components of the generator
773     /// which type checking knows are live across a suspension point. We need to
774     /// flag drop flags to avoid triggering this check as they are introduced
775     /// outside of type inference.
776     ///
777     /// This should be sound because the drop flags are fully algebraic, and
778     /// therefore don't affect the auto-trait or outlives properties of the
779     /// generator.
780     pub internal: bool,
781 
782     /// The type of this local.
783     pub ty: Ty<'tcx>,
784 
785     /// If the user manually ascribed a type to this variable,
786     /// e.g., via `let x: T`, then we carry that type here. The MIR
787     /// borrow checker needs this information since it can affect
788     /// region inference.
789     // FIXME(matthewjasper) Don't store in this in `Body`
790     pub user_ty: Option<Box<UserTypeProjections>>,
791 
792     /// The *syntactic* (i.e., not visibility) source scope the local is defined
793     /// in. If the local was defined in a let-statement, this
794     /// is *within* the let-statement, rather than outside
795     /// of it.
796     ///
797     /// This is needed because the visibility source scope of locals within
798     /// a let-statement is weird.
799     ///
800     /// The reason is that we want the local to be *within* the let-statement
801     /// for lint purposes, but we want the local to be *after* the let-statement
802     /// for names-in-scope purposes.
803     ///
804     /// That's it, if we have a let-statement like the one in this
805     /// function:
806     ///
807     /// ```
808     /// fn foo(x: &str) {
809     ///     #[allow(unused_mut)]
810     ///     let mut x: u32 = { // <- one unused mut
811     ///         let mut y: u32 = x.parse().unwrap();
812     ///         y + 2
813     ///     };
814     ///     drop(x);
815     /// }
816     /// ```
817     ///
818     /// Then, from a lint point of view, the declaration of `x: u32`
819     /// (and `y: u32`) are within the `#[allow(unused_mut)]` scope - the
820     /// lint scopes are the same as the AST/HIR nesting.
821     ///
822     /// However, from a name lookup point of view, the scopes look more like
823     /// as if the let-statements were `match` expressions:
824     ///
825     /// ```
826     /// fn foo(x: &str) {
827     ///     match {
828     ///         match x.parse::<u32>().unwrap() {
829     ///             y => y + 2
830     ///         }
831     ///     } {
832     ///         x => drop(x)
833     ///     };
834     /// }
835     /// ```
836     ///
837     /// We care about the name-lookup scopes for debuginfo - if the
838     /// debuginfo instruction pointer is at the call to `x.parse()`, we
839     /// want `x` to refer to `x: &str`, but if it is at the call to
840     /// `drop(x)`, we want it to refer to `x: u32`.
841     ///
842     /// To allow both uses to work, we need to have more than a single scope
843     /// for a local. We have the `source_info.scope` represent the "syntactic"
844     /// lint scope (with a variable being under its let block) while the
845     /// `var_debug_info.source_info.scope` represents the "local variable"
846     /// scope (where the "rest" of a block is under all prior let-statements).
847     ///
848     /// The end result looks like this:
849     ///
850     /// ```text
851     /// ROOT SCOPE
852     ///  │{ argument x: &str }
853     ///  │
854     ///  │ │{ #[allow(unused_mut)] } // This is actually split into 2 scopes
855     ///  │ │                         // in practice because I'm lazy.
856     ///  │ │
857     ///  │ │← x.source_info.scope
858     ///  │ │← `x.parse().unwrap()`
859     ///  │ │
860     ///  │ │ │← y.source_info.scope
861     ///  │ │
862     ///  │ │ │{ let y: u32 }
863     ///  │ │ │
864     ///  │ │ │← y.var_debug_info.source_info.scope
865     ///  │ │ │← `y + 2`
866     ///  │
867     ///  │ │{ let x: u32 }
868     ///  │ │← x.var_debug_info.source_info.scope
869     ///  │ │← `drop(x)` // This accesses `x: u32`.
870     /// ```
871     pub source_info: SourceInfo,
872 }
873 
874 /// Extra information about a some locals that's used for diagnostics and for
875 /// classifying variables into local variables, statics, etc, which is needed e.g.
876 /// for unsafety checking.
877 ///
878 /// Not used for non-StaticRef temporaries, the return place, or anonymous
879 /// function parameters.
880 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
881 pub enum LocalInfo<'tcx> {
882     /// A user-defined local variable or function parameter
883     ///
884     /// The `BindingForm` is solely used for local diagnostics when generating
885     /// warnings/errors when compiling the current crate, and therefore it need
886     /// not be visible across crates.
887     User(BindingForm<'tcx>),
888     /// A temporary created that references the static with the given `DefId`.
889     StaticRef { def_id: DefId, is_thread_local: bool },
890     /// A temporary created that references the const with the given `DefId`
891     ConstRef { def_id: DefId },
892     /// A temporary created during the creation of an aggregate
893     /// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`)
894     AggregateTemp,
895     /// A temporary created for evaluation of some subexpression of some block's tail expression
896     /// (with no intervening statement context).
897     // FIXME(matthewjasper) Don't store in this in `Body`
898     BlockTailTemp(BlockTailInfo),
899     /// A temporary created during the pass `Derefer` to avoid it's retagging
900     DerefTemp,
901     /// A temporary created for borrow checking.
902     FakeBorrow,
903     /// A local without anything interesting about it.
904     Boring,
905 }
906 
907 impl<'tcx> LocalDecl<'tcx> {
local_info(&self) -> &LocalInfo<'tcx>908     pub fn local_info(&self) -> &LocalInfo<'tcx> {
909         &self.local_info.as_ref().assert_crate_local()
910     }
911 
912     /// Returns `true` only if local is a binding that can itself be
913     /// made mutable via the addition of the `mut` keyword, namely
914     /// something like the occurrences of `x` in:
915     /// - `fn foo(x: Type) { ... }`,
916     /// - `let x = ...`,
917     /// - or `match ... { C(x) => ... }`
can_be_made_mutable(&self) -> bool918     pub fn can_be_made_mutable(&self) -> bool {
919         matches!(
920             self.local_info(),
921             LocalInfo::User(
922                 BindingForm::Var(VarBindingForm {
923                     binding_mode: ty::BindingMode::BindByValue(_),
924                     opt_ty_info: _,
925                     opt_match_place: _,
926                     pat_span: _,
927                 }) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
928             )
929         )
930     }
931 
932     /// Returns `true` if local is definitely not a `ref ident` or
933     /// `ref mut ident` binding. (Such bindings cannot be made into
934     /// mutable bindings, but the inverse does not necessarily hold).
is_nonref_binding(&self) -> bool935     pub fn is_nonref_binding(&self) -> bool {
936         matches!(
937             self.local_info(),
938             LocalInfo::User(
939                 BindingForm::Var(VarBindingForm {
940                     binding_mode: ty::BindingMode::BindByValue(_),
941                     opt_ty_info: _,
942                     opt_match_place: _,
943                     pat_span: _,
944                 }) | BindingForm::ImplicitSelf(_),
945             )
946         )
947     }
948 
949     /// Returns `true` if this variable is a named variable or function
950     /// parameter declared by the user.
951     #[inline]
is_user_variable(&self) -> bool952     pub fn is_user_variable(&self) -> bool {
953         matches!(self.local_info(), LocalInfo::User(_))
954     }
955 
956     /// Returns `true` if this is a reference to a variable bound in a `match`
957     /// expression that is used to access said variable for the guard of the
958     /// match arm.
is_ref_for_guard(&self) -> bool959     pub fn is_ref_for_guard(&self) -> bool {
960         matches!(self.local_info(), LocalInfo::User(BindingForm::RefForGuard))
961     }
962 
963     /// Returns `Some` if this is a reference to a static item that is used to
964     /// access that static.
is_ref_to_static(&self) -> bool965     pub fn is_ref_to_static(&self) -> bool {
966         matches!(self.local_info(), LocalInfo::StaticRef { .. })
967     }
968 
969     /// Returns `Some` if this is a reference to a thread-local static item that is used to
970     /// access that static.
is_ref_to_thread_local(&self) -> bool971     pub fn is_ref_to_thread_local(&self) -> bool {
972         match self.local_info() {
973             LocalInfo::StaticRef { is_thread_local, .. } => *is_thread_local,
974             _ => false,
975         }
976     }
977 
978     /// Returns `true` if this is a DerefTemp
is_deref_temp(&self) -> bool979     pub fn is_deref_temp(&self) -> bool {
980         match self.local_info() {
981             LocalInfo::DerefTemp => return true,
982             _ => (),
983         }
984         return false;
985     }
986 
987     /// Returns `true` is the local is from a compiler desugaring, e.g.,
988     /// `__next` from a `for` loop.
989     #[inline]
from_compiler_desugaring(&self) -> bool990     pub fn from_compiler_desugaring(&self) -> bool {
991         self.source_info.span.desugaring_kind().is_some()
992     }
993 
994     /// Creates a new `LocalDecl` for a temporary: mutable, non-internal.
995     #[inline]
new(ty: Ty<'tcx>, span: Span) -> Self996     pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
997         Self::with_source_info(ty, SourceInfo::outermost(span))
998     }
999 
1000     /// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
1001     #[inline]
with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self1002     pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
1003         LocalDecl {
1004             mutability: Mutability::Mut,
1005             local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)),
1006             internal: false,
1007             ty,
1008             user_ty: None,
1009             source_info,
1010         }
1011     }
1012 
1013     /// Converts `self` into same `LocalDecl` except tagged as internal.
1014     #[inline]
internal(mut self) -> Self1015     pub fn internal(mut self) -> Self {
1016         self.internal = true;
1017         self
1018     }
1019 
1020     /// Converts `self` into same `LocalDecl` except tagged as immutable.
1021     #[inline]
immutable(mut self) -> Self1022     pub fn immutable(mut self) -> Self {
1023         self.mutability = Mutability::Not;
1024         self
1025     }
1026 }
1027 
1028 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1029 pub enum VarDebugInfoContents<'tcx> {
1030     /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
1031     Place(Place<'tcx>),
1032     Const(Constant<'tcx>),
1033     /// The user variable's data is split across several fragments,
1034     /// each described by a `VarDebugInfoFragment`.
1035     /// See DWARF 5's "2.6.1.2 Composite Location Descriptions"
1036     /// and LLVM's `DW_OP_LLVM_fragment` for more details on
1037     /// the underlying debuginfo feature this relies on.
1038     Composite {
1039         /// Type of the original user variable.
1040         /// This cannot contain a union or an enum.
1041         ty: Ty<'tcx>,
1042         /// All the parts of the original user variable, which ended
1043         /// up in disjoint places, due to optimizations.
1044         fragments: Vec<VarDebugInfoFragment<'tcx>>,
1045     },
1046 }
1047 
1048 impl<'tcx> Debug for VarDebugInfoContents<'tcx> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result1049     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1050         match self {
1051             VarDebugInfoContents::Const(c) => write!(fmt, "{}", c),
1052             VarDebugInfoContents::Place(p) => write!(fmt, "{:?}", p),
1053             VarDebugInfoContents::Composite { ty, fragments } => {
1054                 write!(fmt, "{:?}{{ ", ty)?;
1055                 for f in fragments.iter() {
1056                     write!(fmt, "{:?}, ", f)?;
1057                 }
1058                 write!(fmt, "}}")
1059             }
1060         }
1061     }
1062 }
1063 
1064 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1065 pub struct VarDebugInfoFragment<'tcx> {
1066     /// Where in the composite user variable this fragment is,
1067     /// represented as a "projection" into the composite variable.
1068     /// At lower levels, this corresponds to a byte/bit range.
1069     ///
1070     /// This can only contain `PlaceElem::Field`.
1071     // FIXME support this for `enum`s by either using DWARF's
1072     // more advanced control-flow features (unsupported by LLVM?)
1073     // to match on the discriminant, or by using custom type debuginfo
1074     // with non-overlapping variants for the composite variable.
1075     pub projection: Vec<PlaceElem<'tcx>>,
1076 
1077     /// Where the data for this fragment can be found.
1078     /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
1079     pub contents: Place<'tcx>,
1080 }
1081 
1082 impl Debug for VarDebugInfoFragment<'_> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result1083     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1084         for elem in self.projection.iter() {
1085             match elem {
1086                 ProjectionElem::Field(field, _) => {
1087                     write!(fmt, ".{:?}", field.index())?;
1088                 }
1089                 _ => bug!("unsupported fragment projection `{:?}`", elem),
1090             }
1091         }
1092 
1093         write!(fmt, " => {:?}", self.contents)
1094     }
1095 }
1096 
1097 /// Debug information pertaining to a user variable.
1098 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1099 pub struct VarDebugInfo<'tcx> {
1100     pub name: Symbol,
1101 
1102     /// Source info of the user variable, including the scope
1103     /// within which the variable is visible (to debuginfo)
1104     /// (see `LocalDecl`'s `source_info` field for more details).
1105     pub source_info: SourceInfo,
1106 
1107     /// Where the data for this user variable is to be found.
1108     pub value: VarDebugInfoContents<'tcx>,
1109 
1110     /// When present, indicates what argument number this variable is in the function that it
1111     /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
1112     /// argument number in the original function before it was inlined.
1113     pub argument_index: Option<u16>,
1114 
1115     /// The data represents `name` dereferenced `references` times,
1116     /// and not the direct value.
1117     pub references: u8,
1118 }
1119 
1120 ///////////////////////////////////////////////////////////////////////////
1121 // BasicBlock
1122 
1123 rustc_index::newtype_index! {
1124     /// A node in the MIR [control-flow graph][CFG].
1125     ///
1126     /// There are no branches (e.g., `if`s, function calls, etc.) within a basic block, which makes
1127     /// it easier to do [data-flow analyses] and optimizations. Instead, branches are represented
1128     /// as an edge in a graph between basic blocks.
1129     ///
1130     /// Basic blocks consist of a series of [statements][Statement], ending with a
1131     /// [terminator][Terminator]. Basic blocks can have multiple predecessors and successors,
1132     /// however there is a MIR pass ([`CriticalCallEdges`]) that removes *critical edges*, which
1133     /// are edges that go from a multi-successor node to a multi-predecessor node. This pass is
1134     /// needed because some analyses require that there are no critical edges in the CFG.
1135     ///
1136     /// Note that this type is just an index into [`Body.basic_blocks`](Body::basic_blocks);
1137     /// the actual data that a basic block holds is in [`BasicBlockData`].
1138     ///
1139     /// Read more about basic blocks in the [rustc-dev-guide][guide-mir].
1140     ///
1141     /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
1142     /// [data-flow analyses]:
1143     ///     https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
1144     /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
1145     /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
1146     #[derive(HashStable)]
1147     #[debug_format = "bb{}"]
1148     pub struct BasicBlock {
1149         const START_BLOCK = 0;
1150     }
1151 }
1152 
1153 impl BasicBlock {
start_location(self) -> Location1154     pub fn start_location(self) -> Location {
1155         Location { block: self, statement_index: 0 }
1156     }
1157 }
1158 
1159 ///////////////////////////////////////////////////////////////////////////
1160 // BasicBlockData
1161 
1162 /// Data for a basic block, including a list of its statements.
1163 ///
1164 /// See [`BasicBlock`] for documentation on what basic blocks are at a high level.
1165 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1166 pub struct BasicBlockData<'tcx> {
1167     /// List of statements in this block.
1168     pub statements: Vec<Statement<'tcx>>,
1169 
1170     /// Terminator for this block.
1171     ///
1172     /// N.B., this should generally ONLY be `None` during construction.
1173     /// Therefore, you should generally access it via the
1174     /// `terminator()` or `terminator_mut()` methods. The only
1175     /// exception is that certain passes, such as `simplify_cfg`, swap
1176     /// out the terminator temporarily with `None` while they continue
1177     /// to recurse over the set of basic blocks.
1178     pub terminator: Option<Terminator<'tcx>>,
1179 
1180     /// If true, this block lies on an unwind path. This is used
1181     /// during codegen where distinct kinds of basic blocks may be
1182     /// generated (particularly for MSVC cleanup). Unwind blocks must
1183     /// only branch to other unwind blocks.
1184     pub is_cleanup: bool,
1185 }
1186 
1187 impl<'tcx> BasicBlockData<'tcx> {
new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx>1188     pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
1189         BasicBlockData { statements: vec![], terminator, is_cleanup: false }
1190     }
1191 
1192     /// Accessor for terminator.
1193     ///
1194     /// Terminator may not be None after construction of the basic block is complete. This accessor
1195     /// provides a convenient way to reach the terminator.
1196     #[inline]
terminator(&self) -> &Terminator<'tcx>1197     pub fn terminator(&self) -> &Terminator<'tcx> {
1198         self.terminator.as_ref().expect("invalid terminator state")
1199     }
1200 
1201     #[inline]
terminator_mut(&mut self) -> &mut Terminator<'tcx>1202     pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
1203         self.terminator.as_mut().expect("invalid terminator state")
1204     }
1205 
retain_statements<F>(&mut self, mut f: F) where F: FnMut(&mut Statement<'_>) -> bool,1206     pub fn retain_statements<F>(&mut self, mut f: F)
1207     where
1208         F: FnMut(&mut Statement<'_>) -> bool,
1209     {
1210         for s in &mut self.statements {
1211             if !f(s) {
1212                 s.make_nop();
1213             }
1214         }
1215     }
1216 
expand_statements<F, I>(&mut self, mut f: F) where F: FnMut(&mut Statement<'tcx>) -> Option<I>, I: iter::TrustedLen<Item = Statement<'tcx>>,1217     pub fn expand_statements<F, I>(&mut self, mut f: F)
1218     where
1219         F: FnMut(&mut Statement<'tcx>) -> Option<I>,
1220         I: iter::TrustedLen<Item = Statement<'tcx>>,
1221     {
1222         // Gather all the iterators we'll need to splice in, and their positions.
1223         let mut splices: Vec<(usize, I)> = vec![];
1224         let mut extra_stmts = 0;
1225         for (i, s) in self.statements.iter_mut().enumerate() {
1226             if let Some(mut new_stmts) = f(s) {
1227                 if let Some(first) = new_stmts.next() {
1228                     // We can already store the first new statement.
1229                     *s = first;
1230 
1231                     // Save the other statements for optimized splicing.
1232                     let remaining = new_stmts.size_hint().0;
1233                     if remaining > 0 {
1234                         splices.push((i + 1 + extra_stmts, new_stmts));
1235                         extra_stmts += remaining;
1236                     }
1237                 } else {
1238                     s.make_nop();
1239                 }
1240             }
1241         }
1242 
1243         // Splice in the new statements, from the end of the block.
1244         // FIXME(eddyb) This could be more efficient with a "gap buffer"
1245         // where a range of elements ("gap") is left uninitialized, with
1246         // splicing adding new elements to the end of that gap and moving
1247         // existing elements from before the gap to the end of the gap.
1248         // For now, this is safe code, emulating a gap but initializing it.
1249         let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
1250         self.statements.resize(
1251             gap.end,
1252             Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
1253         );
1254         for (splice_start, new_stmts) in splices.into_iter().rev() {
1255             let splice_end = splice_start + new_stmts.size_hint().0;
1256             while gap.end > splice_end {
1257                 gap.start -= 1;
1258                 gap.end -= 1;
1259                 self.statements.swap(gap.start, gap.end);
1260             }
1261             self.statements.splice(splice_start..splice_end, new_stmts);
1262             gap.end = splice_start;
1263         }
1264     }
1265 
visitable(&self, index: usize) -> &dyn MirVisitable<'tcx>1266     pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
1267         if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
1268     }
1269 
1270     /// Does the block have no statements and an unreachable terminator?
is_empty_unreachable(&self) -> bool1271     pub fn is_empty_unreachable(&self) -> bool {
1272         self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable)
1273     }
1274 }
1275 
1276 impl<O> AssertKind<O> {
1277     /// Returns true if this an overflow checking assertion controlled by -C overflow-checks.
is_optional_overflow_check(&self) -> bool1278     pub fn is_optional_overflow_check(&self) -> bool {
1279         use AssertKind::*;
1280         use BinOp::*;
1281         matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..))
1282     }
1283 
1284     /// Getting a description does not require `O` to be printable, and does not
1285     /// require allocation.
1286     /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` separately.
description(&self) -> &'static str1287     pub fn description(&self) -> &'static str {
1288         use AssertKind::*;
1289         match self {
1290             Overflow(BinOp::Add, _, _) => "attempt to add with overflow",
1291             Overflow(BinOp::Sub, _, _) => "attempt to subtract with overflow",
1292             Overflow(BinOp::Mul, _, _) => "attempt to multiply with overflow",
1293             Overflow(BinOp::Div, _, _) => "attempt to divide with overflow",
1294             Overflow(BinOp::Rem, _, _) => "attempt to calculate the remainder with overflow",
1295             OverflowNeg(_) => "attempt to negate with overflow",
1296             Overflow(BinOp::Shr, _, _) => "attempt to shift right with overflow",
1297             Overflow(BinOp::Shl, _, _) => "attempt to shift left with overflow",
1298             Overflow(op, _, _) => bug!("{:?} cannot overflow", op),
1299             DivisionByZero(_) => "attempt to divide by zero",
1300             RemainderByZero(_) => "attempt to calculate the remainder with a divisor of zero",
1301             ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion",
1302             ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion",
1303             ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking",
1304             ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking",
1305             BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
1306                 bug!("Unexpected AssertKind")
1307             }
1308         }
1309     }
1310 
1311     /// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing.
fmt_assert_args<W: Write>(&self, f: &mut W) -> fmt::Result where O: Debug,1312     pub fn fmt_assert_args<W: Write>(&self, f: &mut W) -> fmt::Result
1313     where
1314         O: Debug,
1315     {
1316         use AssertKind::*;
1317         match self {
1318             BoundsCheck { ref len, ref index } => write!(
1319                 f,
1320                 "\"index out of bounds: the length is {{}} but the index is {{}}\", {:?}, {:?}",
1321                 len, index
1322             ),
1323 
1324             OverflowNeg(op) => {
1325                 write!(f, "\"attempt to negate `{{}}`, which would overflow\", {:?}", op)
1326             }
1327             DivisionByZero(op) => write!(f, "\"attempt to divide `{{}}` by zero\", {:?}", op),
1328             RemainderByZero(op) => write!(
1329                 f,
1330                 "\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {:?}",
1331                 op
1332             ),
1333             Overflow(BinOp::Add, l, r) => write!(
1334                 f,
1335                 "\"attempt to compute `{{}} + {{}}`, which would overflow\", {:?}, {:?}",
1336                 l, r
1337             ),
1338             Overflow(BinOp::Sub, l, r) => write!(
1339                 f,
1340                 "\"attempt to compute `{{}} - {{}}`, which would overflow\", {:?}, {:?}",
1341                 l, r
1342             ),
1343             Overflow(BinOp::Mul, l, r) => write!(
1344                 f,
1345                 "\"attempt to compute `{{}} * {{}}`, which would overflow\", {:?}, {:?}",
1346                 l, r
1347             ),
1348             Overflow(BinOp::Div, l, r) => write!(
1349                 f,
1350                 "\"attempt to compute `{{}} / {{}}`, which would overflow\", {:?}, {:?}",
1351                 l, r
1352             ),
1353             Overflow(BinOp::Rem, l, r) => write!(
1354                 f,
1355                 "\"attempt to compute the remainder of `{{}} % {{}}`, which would overflow\", {:?}, {:?}",
1356                 l, r
1357             ),
1358             Overflow(BinOp::Shr, _, r) => {
1359                 write!(f, "\"attempt to shift right by `{{}}`, which would overflow\", {:?}", r)
1360             }
1361             Overflow(BinOp::Shl, _, r) => {
1362                 write!(f, "\"attempt to shift left by `{{}}`, which would overflow\", {:?}", r)
1363             }
1364             MisalignedPointerDereference { required, found } => {
1365                 write!(
1366                     f,
1367                     "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {:?}, {:?}",
1368                     required, found
1369                 )
1370             }
1371             _ => write!(f, "\"{}\"", self.description()),
1372         }
1373     }
1374 
diagnostic_message(&self) -> DiagnosticMessage1375     pub fn diagnostic_message(&self) -> DiagnosticMessage {
1376         use crate::fluent_generated::*;
1377         use AssertKind::*;
1378 
1379         match self {
1380             BoundsCheck { .. } => middle_bounds_check,
1381             Overflow(BinOp::Shl, _, _) => middle_assert_shl_overflow,
1382             Overflow(BinOp::Shr, _, _) => middle_assert_shr_overflow,
1383             Overflow(_, _, _) => middle_assert_op_overflow,
1384             OverflowNeg(_) => middle_assert_overflow_neg,
1385             DivisionByZero(_) => middle_assert_divide_by_zero,
1386             RemainderByZero(_) => middle_assert_remainder_by_zero,
1387             ResumedAfterReturn(GeneratorKind::Async(_)) => middle_assert_async_resume_after_return,
1388             ResumedAfterReturn(GeneratorKind::Gen) => middle_assert_generator_resume_after_return,
1389             ResumedAfterPanic(GeneratorKind::Async(_)) => middle_assert_async_resume_after_panic,
1390             ResumedAfterPanic(GeneratorKind::Gen) => middle_assert_generator_resume_after_panic,
1391 
1392             MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
1393         }
1394     }
1395 
add_args(self, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>)) where O: fmt::Debug,1396     pub fn add_args(self, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>))
1397     where
1398         O: fmt::Debug,
1399     {
1400         use AssertKind::*;
1401 
1402         macro_rules! add {
1403             ($name: expr, $value: expr) => {
1404                 adder($name.into(), $value.into_diagnostic_arg());
1405             };
1406         }
1407 
1408         match self {
1409             BoundsCheck { len, index } => {
1410                 add!("len", format!("{len:?}"));
1411                 add!("index", format!("{index:?}"));
1412             }
1413             Overflow(BinOp::Shl | BinOp::Shr, _, val)
1414             | DivisionByZero(val)
1415             | RemainderByZero(val)
1416             | OverflowNeg(val) => {
1417                 add!("val", format!("{val:#?}"));
1418             }
1419             Overflow(binop, left, right) => {
1420                 add!("op", binop.to_hir_binop().as_str());
1421                 add!("left", format!("{left:#?}"));
1422                 add!("right", format!("{right:#?}"));
1423             }
1424             ResumedAfterReturn(_) | ResumedAfterPanic(_) => {}
1425             MisalignedPointerDereference { required, found } => {
1426                 add!("required", format!("{required:#?}"));
1427                 add!("found", format!("{found:#?}"));
1428             }
1429         }
1430     }
1431 }
1432 
1433 ///////////////////////////////////////////////////////////////////////////
1434 // Statements
1435 
1436 /// A statement in a basic block, including information about its source code.
1437 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1438 pub struct Statement<'tcx> {
1439     pub source_info: SourceInfo,
1440     pub kind: StatementKind<'tcx>,
1441 }
1442 
1443 impl Statement<'_> {
1444     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
1445     /// invalidating statement indices in `Location`s.
make_nop(&mut self)1446     pub fn make_nop(&mut self) {
1447         self.kind = StatementKind::Nop
1448     }
1449 
1450     /// Changes a statement to a nop and returns the original statement.
1451     #[must_use = "If you don't need the statement, use `make_nop` instead"]
replace_nop(&mut self) -> Self1452     pub fn replace_nop(&mut self) -> Self {
1453         Statement {
1454             source_info: self.source_info,
1455             kind: mem::replace(&mut self.kind, StatementKind::Nop),
1456         }
1457     }
1458 }
1459 
1460 impl Debug for Statement<'_> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result1461     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1462         use self::StatementKind::*;
1463         match self.kind {
1464             Assign(box (ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv),
1465             FakeRead(box (ref cause, ref place)) => {
1466                 write!(fmt, "FakeRead({:?}, {:?})", cause, place)
1467             }
1468             Retag(ref kind, ref place) => write!(
1469                 fmt,
1470                 "Retag({}{:?})",
1471                 match kind {
1472                     RetagKind::FnEntry => "[fn entry] ",
1473                     RetagKind::TwoPhase => "[2phase] ",
1474                     RetagKind::Raw => "[raw] ",
1475                     RetagKind::Default => "",
1476                 },
1477                 place,
1478             ),
1479             StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
1480             StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
1481             SetDiscriminant { ref place, variant_index } => {
1482                 write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
1483             }
1484             Deinit(ref place) => write!(fmt, "Deinit({:?})", place),
1485             PlaceMention(ref place) => {
1486                 write!(fmt, "PlaceMention({:?})", place)
1487             }
1488             AscribeUserType(box (ref place, ref c_ty), ref variance) => {
1489                 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
1490             }
1491             Coverage(box self::Coverage { ref kind, code_region: Some(ref rgn) }) => {
1492                 write!(fmt, "Coverage::{:?} for {:?}", kind, rgn)
1493             }
1494             Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind),
1495             Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"),
1496             ConstEvalCounter => write!(fmt, "ConstEvalCounter"),
1497             Nop => write!(fmt, "nop"),
1498         }
1499     }
1500 }
1501 
1502 impl<'tcx> StatementKind<'tcx> {
as_assign_mut(&mut self) -> Option<&mut (Place<'tcx>, Rvalue<'tcx>)>1503     pub fn as_assign_mut(&mut self) -> Option<&mut (Place<'tcx>, Rvalue<'tcx>)> {
1504         match self {
1505             StatementKind::Assign(x) => Some(x),
1506             _ => None,
1507         }
1508     }
1509 
as_assign(&self) -> Option<&(Place<'tcx>, Rvalue<'tcx>)>1510     pub fn as_assign(&self) -> Option<&(Place<'tcx>, Rvalue<'tcx>)> {
1511         match self {
1512             StatementKind::Assign(x) => Some(x),
1513             _ => None,
1514         }
1515     }
1516 }
1517 
1518 ///////////////////////////////////////////////////////////////////////////
1519 // Places
1520 
1521 impl<V, T> ProjectionElem<V, T> {
1522     /// Returns `true` if the target of this projection may refer to a different region of memory
1523     /// than the base.
is_indirect(&self) -> bool1524     fn is_indirect(&self) -> bool {
1525         match self {
1526             Self::Deref => true,
1527 
1528             Self::Field(_, _)
1529             | Self::Index(_)
1530             | Self::OpaqueCast(_)
1531             | Self::ConstantIndex { .. }
1532             | Self::Subslice { .. }
1533             | Self::Downcast(_, _) => false,
1534         }
1535     }
1536 
1537     /// Returns `true` if the target of this projection always refers to the same memory region
1538     /// whatever the state of the program.
is_stable_offset(&self) -> bool1539     pub fn is_stable_offset(&self) -> bool {
1540         match self {
1541             Self::Deref | Self::Index(_) => false,
1542             Self::Field(_, _)
1543             | Self::OpaqueCast(_)
1544             | Self::ConstantIndex { .. }
1545             | Self::Subslice { .. }
1546             | Self::Downcast(_, _) => true,
1547         }
1548     }
1549 
1550     /// Returns `true` if this is a `Downcast` projection with the given `VariantIdx`.
is_downcast_to(&self, v: VariantIdx) -> bool1551     pub fn is_downcast_to(&self, v: VariantIdx) -> bool {
1552         matches!(*self, Self::Downcast(_, x) if x == v)
1553     }
1554 
1555     /// Returns `true` if this is a `Field` projection with the given index.
is_field_to(&self, f: FieldIdx) -> bool1556     pub fn is_field_to(&self, f: FieldIdx) -> bool {
1557         matches!(*self, Self::Field(x, _) if x == f)
1558     }
1559 
1560     /// Returns `true` if this is accepted inside `VarDebugInfoContents::Place`.
can_use_in_debuginfo(&self) -> bool1561     pub fn can_use_in_debuginfo(&self) -> bool {
1562         match self {
1563             Self::ConstantIndex { from_end: false, .. }
1564             | Self::Deref
1565             | Self::Downcast(_, _)
1566             | Self::Field(_, _) => true,
1567             Self::ConstantIndex { from_end: true, .. }
1568             | Self::Index(_)
1569             | Self::OpaqueCast(_)
1570             | Self::Subslice { .. } => false,
1571         }
1572     }
1573 }
1574 
1575 /// Alias for projections as they appear in `UserTypeProjection`, where we
1576 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
1577 pub type ProjectionKind = ProjectionElem<(), ()>;
1578 
1579 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1580 pub struct PlaceRef<'tcx> {
1581     pub local: Local,
1582     pub projection: &'tcx [PlaceElem<'tcx>],
1583 }
1584 
1585 // Once we stop implementing `Ord` for `DefId`,
1586 // this impl will be unnecessary. Until then, we'll
1587 // leave this impl in place to prevent re-adding a
1588 // dependency on the `Ord` impl for `DefId`
1589 impl<'tcx> !PartialOrd for PlaceRef<'tcx> {}
1590 
1591 impl<'tcx> Place<'tcx> {
1592     // FIXME change this to a const fn by also making List::empty a const fn.
return_place() -> Place<'tcx>1593     pub fn return_place() -> Place<'tcx> {
1594         Place { local: RETURN_PLACE, projection: List::empty() }
1595     }
1596 
1597     /// Returns `true` if this `Place` contains a `Deref` projection.
1598     ///
1599     /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the
1600     /// same region of memory as its base.
is_indirect(&self) -> bool1601     pub fn is_indirect(&self) -> bool {
1602         self.projection.iter().any(|elem| elem.is_indirect())
1603     }
1604 
1605     /// If MirPhase >= Derefered and if projection contains Deref,
1606     /// It's guaranteed to be in the first place
has_deref(&self) -> bool1607     pub fn has_deref(&self) -> bool {
1608         // To make sure this is not accidentally used in wrong mir phase
1609         debug_assert!(
1610             self.projection.is_empty() || !self.projection[1..].contains(&PlaceElem::Deref)
1611         );
1612         self.projection.first() == Some(&PlaceElem::Deref)
1613     }
1614 
1615     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
1616     /// a single deref of a local.
1617     #[inline(always)]
local_or_deref_local(&self) -> Option<Local>1618     pub fn local_or_deref_local(&self) -> Option<Local> {
1619         self.as_ref().local_or_deref_local()
1620     }
1621 
1622     /// If this place represents a local variable like `_X` with no
1623     /// projections, return `Some(_X)`.
1624     #[inline(always)]
as_local(&self) -> Option<Local>1625     pub fn as_local(&self) -> Option<Local> {
1626         self.as_ref().as_local()
1627     }
1628 
1629     #[inline]
as_ref(&self) -> PlaceRef<'tcx>1630     pub fn as_ref(&self) -> PlaceRef<'tcx> {
1631         PlaceRef { local: self.local, projection: &self.projection }
1632     }
1633 
1634     /// Iterate over the projections in evaluation order, i.e., the first element is the base with
1635     /// its projection and then subsequently more projections are added.
1636     /// As a concrete example, given the place a.b.c, this would yield:
1637     /// - (a, .b)
1638     /// - (a.b, .c)
1639     ///
1640     /// Given a place without projections, the iterator is empty.
1641     #[inline]
iter_projections( self, ) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + DoubleEndedIterator1642     pub fn iter_projections(
1643         self,
1644     ) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + DoubleEndedIterator {
1645         self.as_ref().iter_projections()
1646     }
1647 
1648     /// Generates a new place by appending `more_projections` to the existing ones
1649     /// and interning the result.
project_deeper(self, more_projections: &[PlaceElem<'tcx>], tcx: TyCtxt<'tcx>) -> Self1650     pub fn project_deeper(self, more_projections: &[PlaceElem<'tcx>], tcx: TyCtxt<'tcx>) -> Self {
1651         if more_projections.is_empty() {
1652             return self;
1653         }
1654 
1655         self.as_ref().project_deeper(more_projections, tcx)
1656     }
1657 }
1658 
1659 impl From<Local> for Place<'_> {
1660     #[inline]
from(local: Local) -> Self1661     fn from(local: Local) -> Self {
1662         Place { local, projection: List::empty() }
1663     }
1664 }
1665 
1666 impl<'tcx> PlaceRef<'tcx> {
1667     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
1668     /// a single deref of a local.
local_or_deref_local(&self) -> Option<Local>1669     pub fn local_or_deref_local(&self) -> Option<Local> {
1670         match *self {
1671             PlaceRef { local, projection: [] }
1672             | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local),
1673             _ => None,
1674         }
1675     }
1676 
1677     /// Returns `true` if this `Place` contains a `Deref` projection.
1678     ///
1679     /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the
1680     /// same region of memory as its base.
is_indirect(&self) -> bool1681     pub fn is_indirect(&self) -> bool {
1682         self.projection.iter().any(|elem| elem.is_indirect())
1683     }
1684 
1685     /// If MirPhase >= Derefered and if projection contains Deref,
1686     /// It's guaranteed to be in the first place
has_deref(&self) -> bool1687     pub fn has_deref(&self) -> bool {
1688         self.projection.first() == Some(&PlaceElem::Deref)
1689     }
1690 
1691     /// If this place represents a local variable like `_X` with no
1692     /// projections, return `Some(_X)`.
1693     #[inline]
as_local(&self) -> Option<Local>1694     pub fn as_local(&self) -> Option<Local> {
1695         match *self {
1696             PlaceRef { local, projection: [] } => Some(local),
1697             _ => None,
1698         }
1699     }
1700 
1701     #[inline]
last_projection(&self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)>1702     pub fn last_projection(&self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)> {
1703         if let &[ref proj_base @ .., elem] = self.projection {
1704             Some((PlaceRef { local: self.local, projection: proj_base }, elem))
1705         } else {
1706             None
1707         }
1708     }
1709 
1710     /// Iterate over the projections in evaluation order, i.e., the first element is the base with
1711     /// its projection and then subsequently more projections are added.
1712     /// As a concrete example, given the place a.b.c, this would yield:
1713     /// - (a, .b)
1714     /// - (a.b, .c)
1715     ///
1716     /// Given a place without projections, the iterator is empty.
1717     #[inline]
iter_projections( self, ) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + DoubleEndedIterator1718     pub fn iter_projections(
1719         self,
1720     ) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + DoubleEndedIterator {
1721         self.projection.iter().enumerate().map(move |(i, proj)| {
1722             let base = PlaceRef { local: self.local, projection: &self.projection[..i] };
1723             (base, *proj)
1724         })
1725     }
1726 
1727     /// Generates a new place by appending `more_projections` to the existing ones
1728     /// and interning the result.
project_deeper( self, more_projections: &[PlaceElem<'tcx>], tcx: TyCtxt<'tcx>, ) -> Place<'tcx>1729     pub fn project_deeper(
1730         self,
1731         more_projections: &[PlaceElem<'tcx>],
1732         tcx: TyCtxt<'tcx>,
1733     ) -> Place<'tcx> {
1734         let mut v: Vec<PlaceElem<'tcx>>;
1735 
1736         let new_projections = if self.projection.is_empty() {
1737             more_projections
1738         } else {
1739             v = Vec::with_capacity(self.projection.len() + more_projections.len());
1740             v.extend(self.projection);
1741             v.extend(more_projections);
1742             &v
1743         };
1744 
1745         Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
1746     }
1747 }
1748 
1749 impl Debug for Place<'_> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result1750     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1751         for elem in self.projection.iter().rev() {
1752             match elem {
1753                 ProjectionElem::OpaqueCast(_)
1754                 | ProjectionElem::Downcast(_, _)
1755                 | ProjectionElem::Field(_, _) => {
1756                     write!(fmt, "(").unwrap();
1757                 }
1758                 ProjectionElem::Deref => {
1759                     write!(fmt, "(*").unwrap();
1760                 }
1761                 ProjectionElem::Index(_)
1762                 | ProjectionElem::ConstantIndex { .. }
1763                 | ProjectionElem::Subslice { .. } => {}
1764             }
1765         }
1766 
1767         write!(fmt, "{:?}", self.local)?;
1768 
1769         for elem in self.projection.iter() {
1770             match elem {
1771                 ProjectionElem::OpaqueCast(ty) => {
1772                     write!(fmt, " as {})", ty)?;
1773                 }
1774                 ProjectionElem::Downcast(Some(name), _index) => {
1775                     write!(fmt, " as {})", name)?;
1776                 }
1777                 ProjectionElem::Downcast(None, index) => {
1778                     write!(fmt, " as variant#{:?})", index)?;
1779                 }
1780                 ProjectionElem::Deref => {
1781                     write!(fmt, ")")?;
1782                 }
1783                 ProjectionElem::Field(field, ty) => {
1784                     write!(fmt, ".{:?}: {:?})", field.index(), ty)?;
1785                 }
1786                 ProjectionElem::Index(ref index) => {
1787                     write!(fmt, "[{:?}]", index)?;
1788                 }
1789                 ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => {
1790                     write!(fmt, "[{:?} of {:?}]", offset, min_length)?;
1791                 }
1792                 ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
1793                     write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
1794                 }
1795                 ProjectionElem::Subslice { from, to, from_end: true } if to == 0 => {
1796                     write!(fmt, "[{:?}:]", from)?;
1797                 }
1798                 ProjectionElem::Subslice { from, to, from_end: true } if from == 0 => {
1799                     write!(fmt, "[:-{:?}]", to)?;
1800                 }
1801                 ProjectionElem::Subslice { from, to, from_end: true } => {
1802                     write!(fmt, "[{:?}:-{:?}]", from, to)?;
1803                 }
1804                 ProjectionElem::Subslice { from, to, from_end: false } => {
1805                     write!(fmt, "[{:?}..{:?}]", from, to)?;
1806                 }
1807             }
1808         }
1809 
1810         Ok(())
1811     }
1812 }
1813 
1814 ///////////////////////////////////////////////////////////////////////////
1815 // Scopes
1816 
1817 rustc_index::newtype_index! {
1818     #[derive(HashStable)]
1819     #[debug_format = "scope[{}]"]
1820     pub struct SourceScope {
1821         const OUTERMOST_SOURCE_SCOPE = 0;
1822     }
1823 }
1824 
1825 impl SourceScope {
1826     /// Finds the original HirId this MIR item came from.
1827     /// This is necessary after MIR optimizations, as otherwise we get a HirId
1828     /// from the function that was inlined instead of the function call site.
lint_root( self, source_scopes: &IndexSlice<SourceScope, SourceScopeData<'_>>, ) -> Option<HirId>1829     pub fn lint_root(
1830         self,
1831         source_scopes: &IndexSlice<SourceScope, SourceScopeData<'_>>,
1832     ) -> Option<HirId> {
1833         let mut data = &source_scopes[self];
1834         // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it
1835         // does not work as I thought it would. Needs more investigation and documentation.
1836         while data.inlined.is_some() {
1837             trace!(?data);
1838             data = &source_scopes[data.parent_scope.unwrap()];
1839         }
1840         trace!(?data);
1841         match &data.local_data {
1842             ClearCrossCrate::Set(data) => Some(data.lint_root),
1843             ClearCrossCrate::Clear => None,
1844         }
1845     }
1846 
1847     /// The instance this source scope was inlined from, if any.
1848     #[inline]
inlined_instance<'tcx>( self, source_scopes: &IndexSlice<SourceScope, SourceScopeData<'tcx>>, ) -> Option<ty::Instance<'tcx>>1849     pub fn inlined_instance<'tcx>(
1850         self,
1851         source_scopes: &IndexSlice<SourceScope, SourceScopeData<'tcx>>,
1852     ) -> Option<ty::Instance<'tcx>> {
1853         let scope_data = &source_scopes[self];
1854         if let Some((inlined_instance, _)) = scope_data.inlined {
1855             Some(inlined_instance)
1856         } else if let Some(inlined_scope) = scope_data.inlined_parent_scope {
1857             Some(source_scopes[inlined_scope].inlined.unwrap().0)
1858         } else {
1859             None
1860         }
1861     }
1862 }
1863 
1864 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1865 pub struct SourceScopeData<'tcx> {
1866     pub span: Span,
1867     pub parent_scope: Option<SourceScope>,
1868 
1869     /// Whether this scope is the root of a scope tree of another body,
1870     /// inlined into this body by the MIR inliner.
1871     /// `ty::Instance` is the callee, and the `Span` is the call site.
1872     pub inlined: Option<(ty::Instance<'tcx>, Span)>,
1873 
1874     /// Nearest (transitive) parent scope (if any) which is inlined.
1875     /// This is an optimization over walking up `parent_scope`
1876     /// until a scope with `inlined: Some(...)` is found.
1877     pub inlined_parent_scope: Option<SourceScope>,
1878 
1879     /// Crate-local information for this source scope, that can't (and
1880     /// needn't) be tracked across crates.
1881     pub local_data: ClearCrossCrate<SourceScopeLocalData>,
1882 }
1883 
1884 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
1885 pub struct SourceScopeLocalData {
1886     /// An `HirId` with lint levels equivalent to this scope's lint levels.
1887     pub lint_root: hir::HirId,
1888     /// The unsafe block that contains this node.
1889     pub safety: Safety,
1890 }
1891 
1892 ///////////////////////////////////////////////////////////////////////////
1893 // Operands
1894 
1895 impl<'tcx> Debug for Operand<'tcx> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result1896     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1897         use self::Operand::*;
1898         match *self {
1899             Constant(ref a) => write!(fmt, "{:?}", a),
1900             Copy(ref place) => write!(fmt, "{:?}", place),
1901             Move(ref place) => write!(fmt, "move {:?}", place),
1902         }
1903     }
1904 }
1905 
1906 impl<'tcx> Operand<'tcx> {
1907     /// Convenience helper to make a constant that refers to the fn
1908     /// with given `DefId` and substs. Since this is used to synthesize
1909     /// MIR, assumes `user_ty` is None.
function_handle( tcx: TyCtxt<'tcx>, def_id: DefId, substs: impl IntoIterator<Item = GenericArg<'tcx>>, span: Span, ) -> Self1910     pub fn function_handle(
1911         tcx: TyCtxt<'tcx>,
1912         def_id: DefId,
1913         substs: impl IntoIterator<Item = GenericArg<'tcx>>,
1914         span: Span,
1915     ) -> Self {
1916         let ty = Ty::new_fn_def(tcx, def_id, substs);
1917         Operand::Constant(Box::new(Constant {
1918             span,
1919             user_ty: None,
1920             literal: ConstantKind::Val(ConstValue::ZeroSized, ty),
1921         }))
1922     }
1923 
is_move(&self) -> bool1924     pub fn is_move(&self) -> bool {
1925         matches!(self, Operand::Move(..))
1926     }
1927 
1928     /// Convenience helper to make a literal-like constant from a given scalar value.
1929     /// Since this is used to synthesize MIR, assumes `user_ty` is None.
const_from_scalar( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, val: Scalar, span: Span, ) -> Operand<'tcx>1930     pub fn const_from_scalar(
1931         tcx: TyCtxt<'tcx>,
1932         ty: Ty<'tcx>,
1933         val: Scalar,
1934         span: Span,
1935     ) -> Operand<'tcx> {
1936         debug_assert!({
1937             let param_env_and_ty = ty::ParamEnv::empty().and(ty);
1938             let type_size = tcx
1939                 .layout_of(param_env_and_ty)
1940                 .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
1941                 .size;
1942             let scalar_size = match val {
1943                 Scalar::Int(int) => int.size(),
1944                 _ => panic!("Invalid scalar type {:?}", val),
1945             };
1946             scalar_size == type_size
1947         });
1948         Operand::Constant(Box::new(Constant {
1949             span,
1950             user_ty: None,
1951             literal: ConstantKind::Val(ConstValue::Scalar(val), ty),
1952         }))
1953     }
1954 
to_copy(&self) -> Self1955     pub fn to_copy(&self) -> Self {
1956         match *self {
1957             Operand::Copy(_) | Operand::Constant(_) => self.clone(),
1958             Operand::Move(place) => Operand::Copy(place),
1959         }
1960     }
1961 
1962     /// Returns the `Place` that is the target of this `Operand`, or `None` if this `Operand` is a
1963     /// constant.
place(&self) -> Option<Place<'tcx>>1964     pub fn place(&self) -> Option<Place<'tcx>> {
1965         match self {
1966             Operand::Copy(place) | Operand::Move(place) => Some(*place),
1967             Operand::Constant(_) => None,
1968         }
1969     }
1970 
1971     /// Returns the `Constant` that is the target of this `Operand`, or `None` if this `Operand` is a
1972     /// place.
constant(&self) -> Option<&Constant<'tcx>>1973     pub fn constant(&self) -> Option<&Constant<'tcx>> {
1974         match self {
1975             Operand::Constant(x) => Some(&**x),
1976             Operand::Copy(_) | Operand::Move(_) => None,
1977         }
1978     }
1979 
1980     /// Gets the `ty::FnDef` from an operand if it's a constant function item.
1981     ///
1982     /// While this is unlikely in general, it's the normal case of what you'll
1983     /// find as the `func` in a [`TerminatorKind::Call`].
const_fn_def(&self) -> Option<(DefId, SubstsRef<'tcx>)>1984     pub fn const_fn_def(&self) -> Option<(DefId, SubstsRef<'tcx>)> {
1985         let const_ty = self.constant()?.literal.ty();
1986         if let ty::FnDef(def_id, substs) = *const_ty.kind() { Some((def_id, substs)) } else { None }
1987     }
1988 }
1989 
1990 ///////////////////////////////////////////////////////////////////////////
1991 /// Rvalues
1992 
1993 impl<'tcx> Rvalue<'tcx> {
1994     /// Returns true if rvalue can be safely removed when the result is unused.
1995     #[inline]
is_safe_to_remove(&self) -> bool1996     pub fn is_safe_to_remove(&self) -> bool {
1997         match self {
1998             // Pointer to int casts may be side-effects due to exposing the provenance.
1999             // While the model is undecided, we should be conservative. See
2000             // <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
2001             Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false,
2002 
2003             Rvalue::Use(_)
2004             | Rvalue::CopyForDeref(_)
2005             | Rvalue::Repeat(_, _)
2006             | Rvalue::Ref(_, _, _)
2007             | Rvalue::ThreadLocalRef(_)
2008             | Rvalue::AddressOf(_, _)
2009             | Rvalue::Len(_)
2010             | Rvalue::Cast(
2011                 CastKind::IntToInt
2012                 | CastKind::FloatToInt
2013                 | CastKind::FloatToFloat
2014                 | CastKind::IntToFloat
2015                 | CastKind::FnPtrToPtr
2016                 | CastKind::PtrToPtr
2017                 | CastKind::PointerCoercion(_)
2018                 | CastKind::PointerFromExposedAddress
2019                 | CastKind::DynStar
2020                 | CastKind::Transmute,
2021                 _,
2022                 _,
2023             )
2024             | Rvalue::BinaryOp(_, _)
2025             | Rvalue::CheckedBinaryOp(_, _)
2026             | Rvalue::NullaryOp(_, _)
2027             | Rvalue::UnaryOp(_, _)
2028             | Rvalue::Discriminant(_)
2029             | Rvalue::Aggregate(_, _)
2030             | Rvalue::ShallowInitBox(_, _) => true,
2031         }
2032     }
2033 }
2034 
2035 impl BorrowKind {
mutability(&self) -> Mutability2036     pub fn mutability(&self) -> Mutability {
2037         match *self {
2038             BorrowKind::Shared | BorrowKind::Shallow => Mutability::Not,
2039             BorrowKind::Mut { .. } => Mutability::Mut,
2040         }
2041     }
2042 
allows_two_phase_borrow(&self) -> bool2043     pub fn allows_two_phase_borrow(&self) -> bool {
2044         match *self {
2045             BorrowKind::Shared
2046             | BorrowKind::Shallow
2047             | BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::ClosureCapture } => {
2048                 false
2049             }
2050             BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow } => true,
2051         }
2052     }
2053 }
2054 
2055 impl<'tcx> Debug for Rvalue<'tcx> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result2056     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
2057         use self::Rvalue::*;
2058 
2059         match *self {
2060             Use(ref place) => write!(fmt, "{:?}", place),
2061             Repeat(ref a, b) => {
2062                 write!(fmt, "[{:?}; ", a)?;
2063                 pretty_print_const(b, fmt, false)?;
2064                 write!(fmt, "]")
2065             }
2066             Len(ref a) => write!(fmt, "Len({:?})", a),
2067             Cast(ref kind, ref place, ref ty) => {
2068                 write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind)
2069             }
2070             BinaryOp(ref op, box (ref a, ref b)) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
2071             CheckedBinaryOp(ref op, box (ref a, ref b)) => {
2072                 write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
2073             }
2074             UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
2075             Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
2076             NullaryOp(ref op, ref t) => match op {
2077                 NullOp::SizeOf => write!(fmt, "SizeOf({:?})", t),
2078                 NullOp::AlignOf => write!(fmt, "AlignOf({:?})", t),
2079                 NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({:?}, {:?})", t, fields),
2080             },
2081             ThreadLocalRef(did) => ty::tls::with(|tcx| {
2082                 let muta = tcx.static_mutability(did).unwrap().prefix_str();
2083                 write!(fmt, "&/*tls*/ {}{}", muta, tcx.def_path_str(did))
2084             }),
2085             Ref(region, borrow_kind, ref place) => {
2086                 let kind_str = match borrow_kind {
2087                     BorrowKind::Shared => "",
2088                     BorrowKind::Shallow => "shallow ",
2089                     BorrowKind::Mut { .. } => "mut ",
2090                 };
2091 
2092                 // When printing regions, add trailing space if necessary.
2093                 let print_region = ty::tls::with(|tcx| {
2094                     tcx.sess.verbose() || tcx.sess.opts.unstable_opts.identify_regions
2095                 });
2096                 let region = if print_region {
2097                     let mut region = region.to_string();
2098                     if !region.is_empty() {
2099                         region.push(' ');
2100                     }
2101                     region
2102                 } else {
2103                     // Do not even print 'static
2104                     String::new()
2105                 };
2106                 write!(fmt, "&{}{}{:?}", region, kind_str, place)
2107             }
2108 
2109             CopyForDeref(ref place) => write!(fmt, "deref_copy {:#?}", place),
2110 
2111             AddressOf(mutability, ref place) => {
2112                 let kind_str = match mutability {
2113                     Mutability::Mut => "mut",
2114                     Mutability::Not => "const",
2115                 };
2116 
2117                 write!(fmt, "&raw {} {:?}", kind_str, place)
2118             }
2119 
2120             Aggregate(ref kind, ref places) => {
2121                 let fmt_tuple = |fmt: &mut Formatter<'_>, name: &str| {
2122                     let mut tuple_fmt = fmt.debug_tuple(name);
2123                     for place in places {
2124                         tuple_fmt.field(place);
2125                     }
2126                     tuple_fmt.finish()
2127                 };
2128 
2129                 match **kind {
2130                     AggregateKind::Array(_) => write!(fmt, "{:?}", places),
2131 
2132                     AggregateKind::Tuple => {
2133                         if places.is_empty() {
2134                             write!(fmt, "()")
2135                         } else {
2136                             fmt_tuple(fmt, "")
2137                         }
2138                     }
2139 
2140                     AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => {
2141                         ty::tls::with(|tcx| {
2142                             let variant_def = &tcx.adt_def(adt_did).variant(variant);
2143                             let substs = tcx.lift(substs).expect("could not lift for printing");
2144                             let name = FmtPrinter::new(tcx, Namespace::ValueNS)
2145                                 .print_def_path(variant_def.def_id, substs)?
2146                                 .into_buffer();
2147 
2148                             match variant_def.ctor_kind() {
2149                                 Some(CtorKind::Const) => fmt.write_str(&name),
2150                                 Some(CtorKind::Fn) => fmt_tuple(fmt, &name),
2151                                 None => {
2152                                     let mut struct_fmt = fmt.debug_struct(&name);
2153                                     for (field, place) in iter::zip(&variant_def.fields, places) {
2154                                         struct_fmt.field(field.name.as_str(), place);
2155                                     }
2156                                     struct_fmt.finish()
2157                                 }
2158                             }
2159                         })
2160                     }
2161 
2162                     AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
2163                         let name = if tcx.sess.opts.unstable_opts.span_free_formats {
2164                             let substs = tcx.lift(substs).unwrap();
2165                             format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),)
2166                         } else {
2167                             let span = tcx.def_span(def_id);
2168                             format!(
2169                                 "[closure@{}]",
2170                                 tcx.sess.source_map().span_to_diagnostic_string(span)
2171                             )
2172                         };
2173                         let mut struct_fmt = fmt.debug_struct(&name);
2174 
2175                         // FIXME(project-rfc-2229#48): This should be a list of capture names/places
2176                         if let Some(def_id) = def_id.as_local()
2177                             && let Some(upvars) = tcx.upvars_mentioned(def_id)
2178                         {
2179                             for (&var_id, place) in iter::zip(upvars.keys(), places) {
2180                                 let var_name = tcx.hir().name(var_id);
2181                                 struct_fmt.field(var_name.as_str(), place);
2182                             }
2183                         } else {
2184                             for (index, place) in places.iter().enumerate() {
2185                                 struct_fmt.field(&format!("{index}"), place);
2186                             }
2187                         }
2188 
2189                         struct_fmt.finish()
2190                     }),
2191 
2192                     AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
2193                         let name = format!("[generator@{:?}]", tcx.def_span(def_id));
2194                         let mut struct_fmt = fmt.debug_struct(&name);
2195 
2196                         // FIXME(project-rfc-2229#48): This should be a list of capture names/places
2197                         if let Some(def_id) = def_id.as_local()
2198                             && let Some(upvars) = tcx.upvars_mentioned(def_id)
2199                         {
2200                             for (&var_id, place) in iter::zip(upvars.keys(), places) {
2201                                 let var_name = tcx.hir().name(var_id);
2202                                 struct_fmt.field(var_name.as_str(), place);
2203                             }
2204                         } else {
2205                             for (index, place) in places.iter().enumerate() {
2206                                 struct_fmt.field(&format!("{index}"), place);
2207                             }
2208                         }
2209 
2210                         struct_fmt.finish()
2211                     }),
2212                 }
2213             }
2214 
2215             ShallowInitBox(ref place, ref ty) => {
2216                 write!(fmt, "ShallowInitBox({:?}, {:?})", place, ty)
2217             }
2218         }
2219     }
2220 }
2221 
2222 ///////////////////////////////////////////////////////////////////////////
2223 /// Constants
2224 ///
2225 /// Two constants are equal if they are the same constant. Note that
2226 /// this does not necessarily mean that they are `==` in Rust. In
2227 /// particular, one must be wary of `NaN`!
2228 
2229 #[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
2230 #[derive(TypeFoldable, TypeVisitable)]
2231 pub struct Constant<'tcx> {
2232     pub span: Span,
2233 
2234     /// Optional user-given type: for something like
2235     /// `collect::<Vec<_>>`, this would be present and would
2236     /// indicate that `Vec<_>` was explicitly specified.
2237     ///
2238     /// Needed for NLL to impose user-given type constraints.
2239     pub user_ty: Option<UserTypeAnnotationIndex>,
2240 
2241     pub literal: ConstantKind<'tcx>,
2242 }
2243 
2244 #[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
2245 #[derive(Lift, TypeFoldable, TypeVisitable)]
2246 pub enum ConstantKind<'tcx> {
2247     /// This constant came from the type system
2248     Ty(ty::Const<'tcx>),
2249 
2250     /// An unevaluated mir constant which is not part of the type system.
2251     Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>),
2252 
2253     /// This constant cannot go back into the type system, as it represents
2254     /// something the type system cannot handle (e.g. pointers).
2255     Val(interpret::ConstValue<'tcx>, Ty<'tcx>),
2256 }
2257 
2258 impl<'tcx> Constant<'tcx> {
check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId>2259     pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
2260         match self.literal.try_to_scalar() {
2261             Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) {
2262                 GlobalAlloc::Static(def_id) => {
2263                     assert!(!tcx.is_thread_local_static(def_id));
2264                     Some(def_id)
2265                 }
2266                 _ => None,
2267             },
2268             _ => None,
2269         }
2270     }
2271     #[inline]
ty(&self) -> Ty<'tcx>2272     pub fn ty(&self) -> Ty<'tcx> {
2273         self.literal.ty()
2274     }
2275 }
2276 
2277 impl<'tcx> ConstantKind<'tcx> {
2278     #[inline(always)]
ty(&self) -> Ty<'tcx>2279     pub fn ty(&self) -> Ty<'tcx> {
2280         match self {
2281             ConstantKind::Ty(c) => c.ty(),
2282             ConstantKind::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => *ty,
2283         }
2284     }
2285 
2286     #[inline]
try_to_value(self, tcx: TyCtxt<'tcx>) -> Option<interpret::ConstValue<'tcx>>2287     pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option<interpret::ConstValue<'tcx>> {
2288         match self {
2289             ConstantKind::Ty(c) => match c.kind() {
2290                 ty::ConstKind::Value(valtree) => Some(tcx.valtree_to_const_val((c.ty(), valtree))),
2291                 _ => None,
2292             },
2293             ConstantKind::Val(val, _) => Some(val),
2294             ConstantKind::Unevaluated(..) => None,
2295         }
2296     }
2297 
2298     #[inline]
try_to_scalar(self) -> Option<Scalar>2299     pub fn try_to_scalar(self) -> Option<Scalar> {
2300         match self {
2301             ConstantKind::Ty(c) => match c.kind() {
2302                 ty::ConstKind::Value(valtree) => match valtree {
2303                     ty::ValTree::Leaf(scalar_int) => Some(Scalar::Int(scalar_int)),
2304                     ty::ValTree::Branch(_) => None,
2305                 },
2306                 _ => None,
2307             },
2308             ConstantKind::Val(val, _) => val.try_to_scalar(),
2309             ConstantKind::Unevaluated(..) => None,
2310         }
2311     }
2312 
2313     #[inline]
try_to_scalar_int(self) -> Option<ScalarInt>2314     pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
2315         Some(self.try_to_scalar()?.assert_int())
2316     }
2317 
2318     #[inline]
try_to_bits(self, size: Size) -> Option<u128>2319     pub fn try_to_bits(self, size: Size) -> Option<u128> {
2320         self.try_to_scalar_int()?.to_bits(size).ok()
2321     }
2322 
2323     #[inline]
try_to_bool(self) -> Option<bool>2324     pub fn try_to_bool(self) -> Option<bool> {
2325         self.try_to_scalar_int()?.try_into().ok()
2326     }
2327 
2328     #[inline]
eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self2329     pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
2330         match self {
2331             Self::Ty(c) => {
2332                 if let Some(val) = c.try_eval_for_mir(tcx, param_env) {
2333                     match val {
2334                         Ok(val) => Self::Val(val, c.ty()),
2335                         Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())),
2336                     }
2337                 } else {
2338                     self
2339                 }
2340             }
2341             Self::Val(_, _) => self,
2342             Self::Unevaluated(uneval, ty) => {
2343                 // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
2344                 match tcx.const_eval_resolve(param_env, uneval, None) {
2345                     Ok(val) => Self::Val(val, ty),
2346                     Err(ErrorHandled::TooGeneric) => self,
2347                     Err(ErrorHandled::Reported(guar)) => {
2348                         Self::Ty(ty::Const::new_error(tcx, guar.into(), ty))
2349                     }
2350                 }
2351             }
2352         }
2353     }
2354 
2355     /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
2356     #[inline]
eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u1282357     pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
2358         self.try_eval_bits(tcx, param_env, ty)
2359             .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
2360     }
2361 
2362     #[inline]
try_eval_bits( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Option<u128>2363     pub fn try_eval_bits(
2364         &self,
2365         tcx: TyCtxt<'tcx>,
2366         param_env: ty::ParamEnv<'tcx>,
2367         ty: Ty<'tcx>,
2368     ) -> Option<u128> {
2369         match self {
2370             Self::Ty(ct) => ct.try_eval_bits(tcx, param_env, ty),
2371             Self::Val(val, t) => {
2372                 assert_eq!(*t, ty);
2373                 let size =
2374                     tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
2375                 val.try_to_bits(size)
2376             }
2377             Self::Unevaluated(uneval, ty) => {
2378                 match tcx.const_eval_resolve(param_env, *uneval, None) {
2379                     Ok(val) => {
2380                         let size = tcx
2381                             .layout_of(param_env.with_reveal_all_normalized(tcx).and(*ty))
2382                             .ok()?
2383                             .size;
2384                         val.try_to_bits(size)
2385                     }
2386                     Err(_) => None,
2387                 }
2388             }
2389         }
2390     }
2391 
2392     #[inline]
try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool>2393     pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
2394         match self {
2395             Self::Ty(ct) => ct.try_eval_bool(tcx, param_env),
2396             Self::Val(val, _) => val.try_to_bool(),
2397             Self::Unevaluated(uneval, _) => {
2398                 match tcx.const_eval_resolve(param_env, *uneval, None) {
2399                     Ok(val) => val.try_to_bool(),
2400                     Err(_) => None,
2401                 }
2402             }
2403         }
2404     }
2405 
2406     #[inline]
try_eval_target_usize( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option<u64>2407     pub fn try_eval_target_usize(
2408         &self,
2409         tcx: TyCtxt<'tcx>,
2410         param_env: ty::ParamEnv<'tcx>,
2411     ) -> Option<u64> {
2412         match self {
2413             Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env),
2414             Self::Val(val, _) => val.try_to_target_usize(tcx),
2415             Self::Unevaluated(uneval, _) => {
2416                 match tcx.const_eval_resolve(param_env, *uneval, None) {
2417                     Ok(val) => val.try_to_target_usize(tcx),
2418                     Err(_) => None,
2419                 }
2420             }
2421         }
2422     }
2423 
2424     #[inline]
from_value(val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self2425     pub fn from_value(val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self {
2426         Self::Val(val, ty)
2427     }
2428 
from_bits( tcx: TyCtxt<'tcx>, bits: u128, param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Self2429     pub fn from_bits(
2430         tcx: TyCtxt<'tcx>,
2431         bits: u128,
2432         param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
2433     ) -> Self {
2434         let size = tcx
2435             .layout_of(param_env_ty)
2436             .unwrap_or_else(|e| {
2437                 bug!("could not compute layout for {:?}: {:?}", param_env_ty.value, e)
2438             })
2439             .size;
2440         let cv = ConstValue::Scalar(Scalar::from_uint(bits, size));
2441 
2442         Self::Val(cv, param_env_ty.value)
2443     }
2444 
2445     #[inline]
from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self2446     pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
2447         let cv = ConstValue::from_bool(v);
2448         Self::Val(cv, tcx.types.bool)
2449     }
2450 
2451     #[inline]
zero_sized(ty: Ty<'tcx>) -> Self2452     pub fn zero_sized(ty: Ty<'tcx>) -> Self {
2453         let cv = ConstValue::ZeroSized;
2454         Self::Val(cv, ty)
2455     }
2456 
from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self2457     pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
2458         let ty = tcx.types.usize;
2459         Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty))
2460     }
2461 
2462     #[inline]
from_scalar(_tcx: TyCtxt<'tcx>, s: Scalar, ty: Ty<'tcx>) -> Self2463     pub fn from_scalar(_tcx: TyCtxt<'tcx>, s: Scalar, ty: Ty<'tcx>) -> Self {
2464         let val = ConstValue::Scalar(s);
2465         Self::Val(val, ty)
2466     }
2467 
2468     /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
2469     /// converted to a constant, everything else becomes `Unevaluated`.
2470     #[instrument(skip(tcx), level = "debug", ret)]
from_anon_const( tcx: TyCtxt<'tcx>, def: LocalDefId, param_env: ty::ParamEnv<'tcx>, ) -> Self2471     pub fn from_anon_const(
2472         tcx: TyCtxt<'tcx>,
2473         def: LocalDefId,
2474         param_env: ty::ParamEnv<'tcx>,
2475     ) -> Self {
2476         let body_id = match tcx.hir().get_by_def_id(def) {
2477             hir::Node::AnonConst(ac) => ac.body,
2478             _ => {
2479                 span_bug!(tcx.def_span(def), "from_anon_const can only process anonymous constants")
2480             }
2481         };
2482 
2483         let expr = &tcx.hir().body(body_id).value;
2484         debug!(?expr);
2485 
2486         // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
2487         // currently have to be wrapped in curly brackets, so it's necessary to special-case.
2488         let expr = match &expr.kind {
2489             hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
2490                 block.expr.as_ref().unwrap()
2491             }
2492             _ => expr,
2493         };
2494         debug!("expr.kind: {:?}", expr.kind);
2495 
2496         let ty = tcx.type_of(def).subst_identity();
2497         debug!(?ty);
2498 
2499         // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
2500         // does not provide the parents generics to anonymous constants. We still allow generic const
2501         // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
2502         // ever try to substitute the generic parameters in their bodies.
2503         //
2504         // While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does
2505         // cause issues if we were to remove that special-case and try to evaluate the constant instead.
2506         use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
2507         match expr.kind {
2508             ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
2509                 // Find the name and index of the const parameter by indexing the generics of
2510                 // the parent item and construct a `ParamConst`.
2511                 let item_def_id = tcx.parent(def_id);
2512                 let generics = tcx.generics_of(item_def_id);
2513                 let index = generics.param_def_id_to_index[&def_id];
2514                 let name = tcx.item_name(def_id);
2515                 let ty_const = ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty);
2516                 debug!(?ty_const);
2517 
2518                 return Self::Ty(ty_const);
2519             }
2520             _ => {}
2521         }
2522 
2523         let hir_id = tcx.hir().local_def_id_to_hir_id(def);
2524         let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
2525             && let Some(parent_did) = parent_hir_id.as_owner()
2526         {
2527             InternalSubsts::identity_for_item(tcx, parent_did)
2528         } else {
2529             List::empty()
2530         };
2531         debug!(?parent_substs);
2532 
2533         let did = def.to_def_id();
2534         let child_substs = InternalSubsts::identity_for_item(tcx, did);
2535         let substs =
2536             tcx.mk_substs_from_iter(parent_substs.into_iter().chain(child_substs.into_iter()));
2537         debug!(?substs);
2538 
2539         let span = tcx.def_span(def);
2540         let uneval = UnevaluatedConst::new(did, substs);
2541         debug!(?span, ?param_env);
2542 
2543         match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
2544             Ok(val) => {
2545                 debug!("evaluated const value");
2546                 Self::Val(val, ty)
2547             }
2548             Err(_) => {
2549                 debug!("error encountered during evaluation");
2550                 // Error was handled in `const_eval_resolve`. Here we just create a
2551                 // new unevaluated const and error hard later in codegen
2552                 Self::Unevaluated(
2553                     UnevaluatedConst {
2554                         def: did,
2555                         substs: InternalSubsts::identity_for_item(tcx, did),
2556                         promoted: None,
2557                     },
2558                     ty,
2559                 )
2560             }
2561         }
2562     }
2563 
from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self2564     pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
2565         match c.kind() {
2566             ty::ConstKind::Value(valtree) => {
2567                 let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
2568                 Self::Val(const_val, c.ty())
2569             }
2570             ty::ConstKind::Unevaluated(uv) => Self::Unevaluated(uv.expand(), c.ty()),
2571             _ => Self::Ty(c),
2572         }
2573     }
2574 }
2575 
2576 /// An unevaluated (potentially generic) constant used in MIR.
2577 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
2578 #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
2579 pub struct UnevaluatedConst<'tcx> {
2580     pub def: DefId,
2581     pub substs: SubstsRef<'tcx>,
2582     pub promoted: Option<Promoted>,
2583 }
2584 
2585 impl<'tcx> UnevaluatedConst<'tcx> {
2586     #[inline]
shrink(self) -> ty::UnevaluatedConst<'tcx>2587     pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
2588         assert_eq!(self.promoted, None);
2589         ty::UnevaluatedConst { def: self.def, substs: self.substs }
2590     }
2591 }
2592 
2593 impl<'tcx> UnevaluatedConst<'tcx> {
2594     #[inline]
new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx>2595     pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
2596         UnevaluatedConst { def, substs, promoted: Default::default() }
2597     }
2598 }
2599 
2600 /// A collection of projections into user types.
2601 ///
2602 /// They are projections because a binding can occur a part of a
2603 /// parent pattern that has been ascribed a type.
2604 ///
2605 /// Its a collection because there can be multiple type ascriptions on
2606 /// the path from the root of the pattern down to the binding itself.
2607 ///
2608 /// An example:
2609 ///
2610 /// ```ignore (illustrative)
2611 /// struct S<'a>((i32, &'a str), String);
2612 /// let S((_, w): (i32, &'static str), _): S = ...;
2613 /// //    ------  ^^^^^^^^^^^^^^^^^^^ (1)
2614 /// //  ---------------------------------  ^ (2)
2615 /// ```
2616 ///
2617 /// The highlights labelled `(1)` show the subpattern `(_, w)` being
2618 /// ascribed the type `(i32, &'static str)`.
2619 ///
2620 /// The highlights labelled `(2)` show the whole pattern being
2621 /// ascribed the type `S`.
2622 ///
2623 /// In this example, when we descend to `w`, we will have built up the
2624 /// following two projected types:
2625 ///
2626 ///   * base: `S`,                   projection: `(base.0).1`
2627 ///   * base: `(i32, &'static str)`, projection: `base.1`
2628 ///
2629 /// The first will lead to the constraint `w: &'1 str` (for some
2630 /// inferred region `'1`). The second will lead to the constraint `w:
2631 /// &'static str`.
2632 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
2633 pub struct UserTypeProjections {
2634     pub contents: Vec<(UserTypeProjection, Span)>,
2635 }
2636 
2637 impl<'tcx> UserTypeProjections {
none() -> Self2638     pub fn none() -> Self {
2639         UserTypeProjections { contents: vec![] }
2640     }
2641 
is_empty(&self) -> bool2642     pub fn is_empty(&self) -> bool {
2643         self.contents.is_empty()
2644     }
2645 
projections_and_spans( &self, ) -> impl Iterator<Item = &(UserTypeProjection, Span)> + ExactSizeIterator2646     pub fn projections_and_spans(
2647         &self,
2648     ) -> impl Iterator<Item = &(UserTypeProjection, Span)> + ExactSizeIterator {
2649         self.contents.iter()
2650     }
2651 
projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator2652     pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator {
2653         self.contents.iter().map(|&(ref user_type, _span)| user_type)
2654     }
2655 
push_projection(mut self, user_ty: &UserTypeProjection, span: Span) -> Self2656     pub fn push_projection(mut self, user_ty: &UserTypeProjection, span: Span) -> Self {
2657         self.contents.push((user_ty.clone(), span));
2658         self
2659     }
2660 
map_projections( mut self, mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection, ) -> Self2661     fn map_projections(
2662         mut self,
2663         mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
2664     ) -> Self {
2665         self.contents = self.contents.into_iter().map(|(proj, span)| (f(proj), span)).collect();
2666         self
2667     }
2668 
index(self) -> Self2669     pub fn index(self) -> Self {
2670         self.map_projections(|pat_ty_proj| pat_ty_proj.index())
2671     }
2672 
subslice(self, from: u64, to: u64) -> Self2673     pub fn subslice(self, from: u64, to: u64) -> Self {
2674         self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
2675     }
2676 
deref(self) -> Self2677     pub fn deref(self) -> Self {
2678         self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
2679     }
2680 
leaf(self, field: FieldIdx) -> Self2681     pub fn leaf(self, field: FieldIdx) -> Self {
2682         self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
2683     }
2684 
variant( self, adt_def: AdtDef<'tcx>, variant_index: VariantIdx, field_index: FieldIdx, ) -> Self2685     pub fn variant(
2686         self,
2687         adt_def: AdtDef<'tcx>,
2688         variant_index: VariantIdx,
2689         field_index: FieldIdx,
2690     ) -> Self {
2691         self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field_index))
2692     }
2693 }
2694 
2695 /// Encodes the effect of a user-supplied type annotation on the
2696 /// subcomponents of a pattern. The effect is determined by applying the
2697 /// given list of projections to some underlying base type. Often,
2698 /// the projection element list `projs` is empty, in which case this
2699 /// directly encodes a type in `base`. But in the case of complex patterns with
2700 /// subpatterns and bindings, we want to apply only a *part* of the type to a variable,
2701 /// in which case the `projs` vector is used.
2702 ///
2703 /// Examples:
2704 ///
2705 /// * `let x: T = ...` -- here, the `projs` vector is empty.
2706 ///
2707 /// * `let (x, _): T = ...` -- here, the `projs` vector would contain
2708 ///   `field[0]` (aka `.0`), indicating that the type of `s` is
2709 ///   determined by finding the type of the `.0` field from `T`.
2710 #[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
2711 #[derive(TypeFoldable, TypeVisitable)]
2712 pub struct UserTypeProjection {
2713     pub base: UserTypeAnnotationIndex,
2714     pub projs: Vec<ProjectionKind>,
2715 }
2716 
2717 impl UserTypeProjection {
index(mut self) -> Self2718     pub(crate) fn index(mut self) -> Self {
2719         self.projs.push(ProjectionElem::Index(()));
2720         self
2721     }
2722 
subslice(mut self, from: u64, to: u64) -> Self2723     pub(crate) fn subslice(mut self, from: u64, to: u64) -> Self {
2724         self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
2725         self
2726     }
2727 
deref(mut self) -> Self2728     pub(crate) fn deref(mut self) -> Self {
2729         self.projs.push(ProjectionElem::Deref);
2730         self
2731     }
2732 
leaf(mut self, field: FieldIdx) -> Self2733     pub(crate) fn leaf(mut self, field: FieldIdx) -> Self {
2734         self.projs.push(ProjectionElem::Field(field, ()));
2735         self
2736     }
2737 
variant( mut self, adt_def: AdtDef<'_>, variant_index: VariantIdx, field_index: FieldIdx, ) -> Self2738     pub(crate) fn variant(
2739         mut self,
2740         adt_def: AdtDef<'_>,
2741         variant_index: VariantIdx,
2742         field_index: FieldIdx,
2743     ) -> Self {
2744         self.projs.push(ProjectionElem::Downcast(
2745             Some(adt_def.variant(variant_index).name),
2746             variant_index,
2747         ));
2748         self.projs.push(ProjectionElem::Field(field_index, ()));
2749         self
2750     }
2751 }
2752 
2753 rustc_index::newtype_index! {
2754     #[derive(HashStable)]
2755     #[debug_format = "promoted[{}]"]
2756     pub struct Promoted {}
2757 }
2758 
2759 impl<'tcx> Debug for Constant<'tcx> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result2760     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
2761         write!(fmt, "{}", self)
2762     }
2763 }
2764 
2765 impl<'tcx> Display for Constant<'tcx> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result2766     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
2767         match self.ty().kind() {
2768             ty::FnDef(..) => {}
2769             _ => write!(fmt, "const ")?,
2770         }
2771         Display::fmt(&self.literal, fmt)
2772     }
2773 }
2774 
2775 impl<'tcx> Display for ConstantKind<'tcx> {
fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result2776     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
2777         match *self {
2778             ConstantKind::Ty(c) => pretty_print_const(c, fmt, true),
2779             ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
2780             // FIXME(valtrees): Correctly print mir constants.
2781             ConstantKind::Unevaluated(..) => {
2782                 fmt.write_str("_")?;
2783                 Ok(())
2784             }
2785         }
2786     }
2787 }
2788 
pretty_print_const<'tcx>( c: ty::Const<'tcx>, fmt: &mut Formatter<'_>, print_types: bool, ) -> fmt::Result2789 fn pretty_print_const<'tcx>(
2790     c: ty::Const<'tcx>,
2791     fmt: &mut Formatter<'_>,
2792     print_types: bool,
2793 ) -> fmt::Result {
2794     use crate::ty::print::PrettyPrinter;
2795     ty::tls::with(|tcx| {
2796         let literal = tcx.lift(c).unwrap();
2797         let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
2798         cx.print_alloc_ids = true;
2799         let cx = cx.pretty_print_const(literal, print_types)?;
2800         fmt.write_str(&cx.into_buffer())?;
2801         Ok(())
2802     })
2803 }
2804 
pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Result2805 fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Result {
2806     write!(fmt, "b\"{}\"", byte_str.escape_ascii())
2807 }
2808 
comma_sep<'tcx>( fmt: &mut Formatter<'_>, elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>, ) -> fmt::Result2809 fn comma_sep<'tcx>(
2810     fmt: &mut Formatter<'_>,
2811     elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>,
2812 ) -> fmt::Result {
2813     let mut first = true;
2814     for (ct, ty) in elems {
2815         if !first {
2816             fmt.write_str(", ")?;
2817         }
2818         pretty_print_const_value(ct, ty, fmt)?;
2819         first = false;
2820     }
2821     Ok(())
2822 }
2823 
2824 // FIXME: Move that into `mir/pretty.rs`.
pretty_print_const_value<'tcx>( ct: ConstValue<'tcx>, ty: Ty<'tcx>, fmt: &mut Formatter<'_>, ) -> fmt::Result2825 fn pretty_print_const_value<'tcx>(
2826     ct: ConstValue<'tcx>,
2827     ty: Ty<'tcx>,
2828     fmt: &mut Formatter<'_>,
2829 ) -> fmt::Result {
2830     use crate::ty::print::PrettyPrinter;
2831 
2832     ty::tls::with(|tcx| {
2833         let ct = tcx.lift(ct).unwrap();
2834         let ty = tcx.lift(ty).unwrap();
2835 
2836         if tcx.sess.verbose() {
2837             fmt.write_str(&format!("ConstValue({:?}: {})", ct, ty))?;
2838             return Ok(());
2839         }
2840 
2841         let u8_type = tcx.types.u8;
2842         match (ct, ty.kind()) {
2843             // Byte/string slices, printed as (byte) string literals.
2844             (ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
2845                 match inner.kind() {
2846                     ty::Slice(t) => {
2847                         if *t == u8_type {
2848                             // The `inspect` here is okay since we checked the bounds, and `u8` carries
2849                             // no provenance (we have an active slice reference here). We don't use
2850                             // this result to affect interpreter execution.
2851                             let byte_str = data
2852                                 .inner()
2853                                 .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
2854                             pretty_print_byte_str(fmt, byte_str)?;
2855                             return Ok(());
2856                         }
2857                     }
2858                     ty::Str => {
2859                         // The `inspect` here is okay since we checked the bounds, and `str` carries
2860                         // no provenance (we have an active `str` reference here). We don't use this
2861                         // result to affect interpreter execution.
2862                         let slice = data
2863                             .inner()
2864                             .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
2865                         fmt.write_str(&format!("{:?}", String::from_utf8_lossy(slice)))?;
2866                         return Ok(());
2867                     }
2868                     _ => {}
2869                 }
2870             }
2871             (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
2872                 let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap();
2873                 // cast is ok because we already checked for pointer size (32 or 64 bit) above
2874                 let range = AllocRange { start: offset, size: Size::from_bytes(n) };
2875                 let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
2876                 fmt.write_str("*")?;
2877                 pretty_print_byte_str(fmt, byte_str)?;
2878                 return Ok(());
2879             }
2880             // Aggregates, printed as array/tuple/struct/variant construction syntax.
2881             //
2882             // NB: the `has_non_region_param` check ensures that we can use
2883             // the `destructure_const` query with an empty `ty::ParamEnv` without
2884             // introducing ICEs (e.g. via `layout_of`) from missing bounds.
2885             // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
2886             // to be able to destructure the tuple into `(0u8, *mut T)`
2887             (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
2888                 let ct = tcx.lift(ct).unwrap();
2889                 let ty = tcx.lift(ty).unwrap();
2890                 if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics((ct, ty)) {
2891                     let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec();
2892                     match *ty.kind() {
2893                         ty::Array(..) => {
2894                             fmt.write_str("[")?;
2895                             comma_sep(fmt, fields)?;
2896                             fmt.write_str("]")?;
2897                         }
2898                         ty::Tuple(..) => {
2899                             fmt.write_str("(")?;
2900                             comma_sep(fmt, fields)?;
2901                             if contents.fields.len() == 1 {
2902                                 fmt.write_str(",")?;
2903                             }
2904                             fmt.write_str(")")?;
2905                         }
2906                         ty::Adt(def, _) if def.variants().is_empty() => {
2907                             fmt.write_str(&format!("{{unreachable(): {}}}", ty))?;
2908                         }
2909                         ty::Adt(def, substs) => {
2910                             let variant_idx = contents
2911                                 .variant
2912                                 .expect("destructed mir constant of adt without variant idx");
2913                             let variant_def = &def.variant(variant_idx);
2914                             let substs = tcx.lift(substs).unwrap();
2915                             let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
2916                             cx.print_alloc_ids = true;
2917                             let cx = cx.print_value_path(variant_def.def_id, substs)?;
2918                             fmt.write_str(&cx.into_buffer())?;
2919 
2920                             match variant_def.ctor_kind() {
2921                                 Some(CtorKind::Const) => {}
2922                                 Some(CtorKind::Fn) => {
2923                                     fmt.write_str("(")?;
2924                                     comma_sep(fmt, fields)?;
2925                                     fmt.write_str(")")?;
2926                                 }
2927                                 None => {
2928                                     fmt.write_str(" {{ ")?;
2929                                     let mut first = true;
2930                                     for (field_def, (ct, ty)) in
2931                                         iter::zip(&variant_def.fields, fields)
2932                                     {
2933                                         if !first {
2934                                             fmt.write_str(", ")?;
2935                                         }
2936                                         write!(fmt, "{}: ", field_def.name)?;
2937                                         pretty_print_const_value(ct, ty, fmt)?;
2938                                         first = false;
2939                                     }
2940                                     fmt.write_str(" }}")?;
2941                                 }
2942                             }
2943                         }
2944                         _ => unreachable!(),
2945                     }
2946                     return Ok(());
2947                 }
2948             }
2949             (ConstValue::Scalar(scalar), _) => {
2950                 let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
2951                 cx.print_alloc_ids = true;
2952                 let ty = tcx.lift(ty).unwrap();
2953                 cx = cx.pretty_print_const_scalar(scalar, ty)?;
2954                 fmt.write_str(&cx.into_buffer())?;
2955                 return Ok(());
2956             }
2957             (ConstValue::ZeroSized, ty::FnDef(d, s)) => {
2958                 let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
2959                 cx.print_alloc_ids = true;
2960                 let cx = cx.print_value_path(*d, s)?;
2961                 fmt.write_str(&cx.into_buffer())?;
2962                 return Ok(());
2963             }
2964             // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
2965             // their fields instead of just dumping the memory.
2966             _ => {}
2967         }
2968         // Fall back to debug pretty printing for invalid constants.
2969         write!(fmt, "{ct:?}: {ty}")
2970     })
2971 }
2972 
2973 /// `Location` represents the position of the start of the statement; or, if
2974 /// `statement_index` equals the number of statements, then the start of the
2975 /// terminator.
2976 #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
2977 pub struct Location {
2978     /// The block that the location is within.
2979     pub block: BasicBlock,
2980 
2981     pub statement_index: usize,
2982 }
2983 
2984 impl fmt::Debug for Location {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result2985     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2986         write!(fmt, "{:?}[{}]", self.block, self.statement_index)
2987     }
2988 }
2989 
2990 impl Location {
2991     pub const START: Location = Location { block: START_BLOCK, statement_index: 0 };
2992 
2993     /// Returns the location immediately after this one within the enclosing block.
2994     ///
2995     /// Note that if this location represents a terminator, then the
2996     /// resulting location would be out of bounds and invalid.
successor_within_block(&self) -> Location2997     pub fn successor_within_block(&self) -> Location {
2998         Location { block: self.block, statement_index: self.statement_index + 1 }
2999     }
3000 
3001     /// Returns `true` if `other` is earlier in the control flow graph than `self`.
is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool3002     pub fn is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool {
3003         // If we are in the same block as the other location and are an earlier statement
3004         // then we are a predecessor of `other`.
3005         if self.block == other.block && self.statement_index < other.statement_index {
3006             return true;
3007         }
3008 
3009         let predecessors = body.basic_blocks.predecessors();
3010 
3011         // If we're in another block, then we want to check that block is a predecessor of `other`.
3012         let mut queue: Vec<BasicBlock> = predecessors[other.block].to_vec();
3013         let mut visited = FxHashSet::default();
3014 
3015         while let Some(block) = queue.pop() {
3016             // If we haven't visited this block before, then make sure we visit its predecessors.
3017             if visited.insert(block) {
3018                 queue.extend(predecessors[block].iter().cloned());
3019             } else {
3020                 continue;
3021             }
3022 
3023             // If we found the block that `self` is in, then we are a predecessor of `other` (since
3024             // we found that block by looking at the predecessors of `other`).
3025             if self.block == block {
3026                 return true;
3027             }
3028         }
3029 
3030         false
3031     }
3032 
dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool3033     pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
3034         if self.block == other.block {
3035             self.statement_index <= other.statement_index
3036         } else {
3037             dominators.dominates(self.block, other.block)
3038         }
3039     }
3040 }
3041 
3042 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
3043 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
3044 mod size_asserts {
3045     use super::*;
3046     use rustc_data_structures::static_assert_size;
3047     // tidy-alphabetical-start
3048     static_assert_size!(BasicBlockData<'_>, 136);
3049     static_assert_size!(LocalDecl<'_>, 40);
3050     static_assert_size!(SourceScopeData<'_>, 72);
3051     static_assert_size!(Statement<'_>, 32);
3052     static_assert_size!(StatementKind<'_>, 16);
3053     static_assert_size!(Terminator<'_>, 104);
3054     static_assert_size!(TerminatorKind<'_>, 88);
3055     static_assert_size!(VarDebugInfo<'_>, 80);
3056     // tidy-alphabetical-end
3057 }
3058