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