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