]> git.proxmox.com Git - rustc.git/blame - src/librustc_middle/mir/mod.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_middle / mir / mod.rs
CommitLineData
ba9703b0 1//! MIR datatypes and passes. See the [rustc dev guide] for more info.
ff7c6d11 2//!
ba9703b0 3//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
7cac9316 4
3dfed10e
XL
5use crate::mir::coverage::{CodeRegion, CoverageKind};
6use crate::mir::interpret::{Allocation, ConstValue, GlobalAlloc, Scalar};
9fa01778 7use crate::mir::visit::MirVisitable;
416331ca 8use crate::ty::adjustment::PointerCast;
3dfed10e 9use crate::ty::codec::{TyDecoder, TyEncoder};
416331ca 10use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
416331ca
XL
11use crate::ty::print::{FmtPrinter, Printer};
12use crate::ty::subst::{Subst, SubstsRef};
13use crate::ty::{
e74abb32 14 self, AdtDef, CanonicalUserTypeAnnotations, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex,
416331ca 15};
dfeec247
XL
16use rustc_hir as hir;
17use rustc_hir::def::{CtorKind, Namespace};
18use rustc_hir::def_id::DefId;
19use rustc_hir::{self, GeneratorKind};
ba9703b0 20use rustc_target::abi::VariantIdx;
e1599b0c 21
416331ca 22use polonius_engine::Atom;
3dfed10e 23pub use rustc_ast::Mutability;
a1dfa0c6 24use rustc_data_structures::fx::FxHashSet;
f9f354fc 25use rustc_data_structures::graph::dominators::{dominators, Dominators};
60c5eb7d 26use rustc_data_structures::graph::{self, GraphSuccessors};
dfeec247 27use rustc_index::bit_set::BitMatrix;
e74abb32 28use rustc_index::vec::{Idx, IndexVec};
dfeec247
XL
29use rustc_serialize::{Decodable, Encodable};
30use rustc_span::symbol::Symbol;
31use rustc_span::{Span, DUMMY_SP};
f035d41b 32use rustc_target::abi;
f9f354fc 33use rustc_target::asm::InlineAsmRegOrRegClass;
94b46f34 34use std::borrow::Cow;
416331ca 35use std::fmt::{self, Debug, Display, Formatter, Write};
f9f354fc 36use std::ops::{Index, IndexMut};
94b46f34 37use std::slice;
ba9703b0 38use std::{iter, mem, option};
83c7162d 39
f9f354fc 40use self::predecessors::{PredecessorCache, Predecessors};
dfeec247 41pub use self::query::*;
3157f602 42
f035d41b 43pub mod coverage;
ff7c6d11
XL
44pub mod interpret;
45pub mod mono;
f9f354fc 46mod predecessors;
dfeec247 47mod query;
94b46f34 48pub mod tcx;
f035d41b
XL
49pub mod terminator;
50pub use terminator::*;
94b46f34 51pub mod traversal;
ba9703b0 52mod type_foldable;
94b46f34 53pub mod visit;
3157f602 54
041b39d2
XL
55/// Types for locals
56type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>;
57
58pub trait HasLocalDecls<'tcx> {
59 fn local_decls(&self) -> &LocalDecls<'tcx>;
60}
61
62impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
63 fn local_decls(&self) -> &LocalDecls<'tcx> {
64 self
65 }
66}
67
dc9dc135 68impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
041b39d2
XL
69 fn local_decls(&self) -> &LocalDecls<'tcx> {
70 &self.local_decls
71 }
72}
73
a1dfa0c6
XL
74/// The various "big phases" that MIR goes through.
75///
3dfed10e
XL
76/// These phases all describe dialects of MIR. Since all MIR uses the same datastructures, the
77/// dialects forbid certain variants or values in certain phases.
78///
79/// Note: Each phase's validation checks all invariants of the *previous* phases' dialects. A phase
80/// that changes the dialect documents what invariants must be upheld *after* that phase finishes.
81///
e1599b0c 82/// Warning: ordering of variants is significant.
3dfed10e 83#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
ba9703b0 84#[derive(HashStable)]
a1dfa0c6
XL
85pub enum MirPhase {
86 Build = 0,
3dfed10e
XL
87 // FIXME(oli-obk): it's unclear whether we still need this phase (and its corresponding query).
88 // We used to have this for pre-miri MIR based const eval.
a1dfa0c6 89 Const = 1,
3dfed10e
XL
90 /// This phase checks the MIR for promotable elements and takes them out of the main MIR body
91 /// by creating a new MIR body per promoted element. After this phase (and thus the termination
92 /// of the `mir_promoted` query), these promoted elements are available in the `promoted_mir`
93 /// query.
94 ConstPromotion = 2,
95 /// After this phase
96 /// * the only `AggregateKind`s allowed are `Array` and `Generator`,
97 /// * `DropAndReplace` is gone for good
98 /// * `Drop` now uses explicit drop flags visible in the MIR and reaching a `Drop` terminator
99 /// means that the auto-generated drop glue will be invoked.
100 DropLowering = 3,
101 /// After this phase, generators are explicit state machines (no more `Yield`).
102 /// `AggregateKind::Generator` is gone for good.
103 GeneratorLowering = 4,
104 Optimization = 5,
a1dfa0c6
XL
105}
106
107impl MirPhase {
e1599b0c 108 /// Gets the index of the current MirPhase within the set of all `MirPhase`s.
a1dfa0c6
XL
109 pub fn phase_index(&self) -> usize {
110 *self as usize
111 }
112}
113
e1599b0c 114/// The lowered representation of a single function.
3dfed10e 115#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)]
dc9dc135 116pub struct Body<'tcx> {
e1599b0c 117 /// A list of basic blocks. References to basic block use a newtyped index type `BasicBlock`
92a42be0 118 /// that indexes into this vector.
3157f602 119 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
e9174d1e 120
a1dfa0c6
XL
121 /// Records how far through the "desugaring and optimization" process this particular
122 /// MIR has traversed. This is particularly useful when inlining, since in that context
123 /// we instantiate the promoted constants and add them to our promoted vector -- but those
124 /// promoted items have already been optimized, whereas ours have not. This field allows
125 /// us to see the difference and forego optimization on the inlined promoted items.
126 pub phase: MirPhase,
127
e1599b0c 128 /// A list of source scopes; these are referenced by statements
94b46f34
XL
129 /// and used for debuginfo. Indexed by a `SourceScope`.
130 pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
54a0048b 131
e1599b0c 132 /// The yield type of the function, if it is a generator.
ea8adc8c
XL
133 pub yield_ty: Option<Ty<'tcx>>,
134
e1599b0c 135 /// Generator drop glue.
f9f354fc 136 pub generator_drop: Option<Box<Body<'tcx>>>,
ea8adc8c
XL
137
138 /// The layout of a generator. Produced by the state transformation.
139 pub generator_layout: Option<GeneratorLayout<'tcx>>,
140
60c5eb7d
XL
141 /// If this is a generator then record the type of source expression that caused this generator
142 /// to be created.
143 pub generator_kind: Option<GeneratorKind>,
144
c30ab7b3
SL
145 /// Declarations of locals.
146 ///
147 /// The first local is the return value pointer, followed by `arg_count`
148 /// locals for the function arguments, followed by any user-declared
149 /// variables and temporaries.
041b39d2 150 pub local_decls: LocalDecls<'tcx>,
92a42be0 151
e1599b0c 152 /// User type annotations.
0731742a
XL
153 pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
154
e1599b0c 155 /// The number of arguments this function takes.
c30ab7b3
SL
156 ///
157 /// Starting at local 1, `arg_count` locals will be provided by the caller
158 /// and can be assumed to be initialized.
159 ///
160 /// If this MIR was built for a constant, this will be 0.
161 pub arg_count: usize,
7453a54e 162
c30ab7b3
SL
163 /// Mark an argument local (which must be a tuple) as getting passed as
164 /// its individual components at the LLVM level.
165 ///
166 /// This is used for the "rust-call" ABI.
167 pub spread_arg: Option<Local>,
168
60c5eb7d
XL
169 /// Debug information pertaining to user variables, including captures.
170 pub var_debug_info: Vec<VarDebugInfo<'tcx>>,
48663c56 171
e1599b0c 172 /// A span representing this MIR, for error reporting.
7453a54e 173 pub span: Span,
dfeec247 174
f9f354fc
XL
175 /// Constants that are required to evaluate successfully for this MIR to be well-formed.
176 /// We hold in this field all the constants we are not able to evaluate yet.
177 pub required_consts: Vec<Constant<'tcx>>,
178
179 /// The user may be writing e.g. `&[(SOME_CELL, 42)][i].1` and this would get promoted, because
dfeec247
XL
180 /// we'd statically know that no thing with interior mutability will ever be available to the
181 /// user without some serious unsafe code. Now this means that our promoted is actually
f035d41b
XL
182 /// `&[(SOME_CELL, 42)]` and the MIR using it will do the `&promoted[i].1` projection because
183 /// the index may be a runtime value. Such a promoted value is illegal because it has reachable
dfeec247
XL
184 /// interior mutability. This flag just makes this situation very obvious where the previous
185 /// implementation without the flag hid this situation silently.
186 /// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
187 pub ignore_interior_mut_in_const_validation: bool,
f9f354fc
XL
188
189 predecessor_cache: PredecessorCache,
e9174d1e
SL
190}
191
dc9dc135 192impl<'tcx> Body<'tcx> {
94b46f34
XL
193 pub fn new(
194 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
195 source_scopes: IndexVec<SourceScope, SourceScopeData>,
0731742a
XL
196 local_decls: LocalDecls<'tcx>,
197 user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
94b46f34 198 arg_count: usize,
60c5eb7d 199 var_debug_info: Vec<VarDebugInfo<'tcx>>,
94b46f34 200 span: Span,
dfeec247 201 generator_kind: Option<GeneratorKind>,
94b46f34 202 ) -> Self {
e1599b0c 203 // We need `arg_count` locals, and one for the return place.
94b46f34 204 assert!(
74b04a01 205 local_decls.len() > arg_count,
94b46f34
XL
206 "expected at least {} locals, got {}",
207 arg_count + 1,
208 local_decls.len()
209 );
c30ab7b3 210
dc9dc135 211 Body {
a1dfa0c6 212 phase: MirPhase::Build,
041b39d2 213 basic_blocks,
94b46f34 214 source_scopes,
60c5eb7d 215 yield_ty: None,
ea8adc8c
XL
216 generator_drop: None,
217 generator_layout: None,
60c5eb7d 218 generator_kind,
041b39d2 219 local_decls,
0731742a 220 user_type_annotations,
041b39d2 221 arg_count,
c30ab7b3 222 spread_arg: None,
60c5eb7d 223 var_debug_info,
041b39d2 224 span,
f9f354fc 225 required_consts: Vec::new(),
dfeec247 226 ignore_interior_mut_in_const_validation: false,
f9f354fc 227 predecessor_cache: PredecessorCache::new(),
3157f602
XL
228 }
229 }
230
dfeec247
XL
231 /// Returns a partially initialized MIR body containing only a list of basic blocks.
232 ///
233 /// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
234 /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
235 /// crate.
236 pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
237 Body {
238 phase: MirPhase::Build,
239 basic_blocks,
240 source_scopes: IndexVec::new(),
241 yield_ty: None,
242 generator_drop: None,
243 generator_layout: None,
244 local_decls: IndexVec::new(),
245 user_type_annotations: IndexVec::new(),
246 arg_count: 0,
247 spread_arg: None,
248 span: DUMMY_SP,
f9f354fc 249 required_consts: Vec::new(),
dfeec247
XL
250 generator_kind: None,
251 var_debug_info: Vec::new(),
252 ignore_interior_mut_in_const_validation: false,
f9f354fc 253 predecessor_cache: PredecessorCache::new(),
dfeec247
XL
254 }
255 }
256
3157f602
XL
257 #[inline]
258 pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
259 &self.basic_blocks
260 }
261
f9f354fc
XL
262 #[inline]
263 pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
264 // Because the user could mutate basic block terminators via this reference, we need to
265 // invalidate the predecessor cache.
266 //
267 // FIXME: Use a finer-grained API for this, so only transformations that alter terminators
268 // invalidate the predecessor cache.
269 self.predecessor_cache.invalidate();
270 &mut self.basic_blocks
271 }
272
273 #[inline]
274 pub fn basic_blocks_and_local_decls_mut(
275 &mut self,
276 ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
277 self.predecessor_cache.invalidate();
278 (&mut self.basic_blocks, &mut self.local_decls)
279 }
280
f035d41b
XL
281 #[inline]
282 pub fn basic_blocks_local_decls_mut_and_var_debug_info(
283 &mut self,
284 ) -> (
285 &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
286 &mut LocalDecls<'tcx>,
287 &mut Vec<VarDebugInfo<'tcx>>,
288 ) {
289 self.predecessor_cache.invalidate();
290 (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
291 }
292
e74abb32
XL
293 /// Returns `true` if a cycle exists in the control-flow graph that is reachable from the
294 /// `START_BLOCK`.
295 pub fn is_cfg_cyclic(&self) -> bool {
296 graph::is_cyclic(self)
297 }
298
c30ab7b3
SL
299 #[inline]
300 pub fn local_kind(&self, local: Local) -> LocalKind {
b7449926 301 let index = local.as_usize();
c30ab7b3 302 if index == 0 {
94b46f34
XL
303 debug_assert!(
304 self.local_decls[local].mutability == Mutability::Mut,
305 "return place should be mutable"
306 );
c30ab7b3
SL
307
308 LocalKind::ReturnPointer
309 } else if index < self.arg_count + 1 {
310 LocalKind::Arg
60c5eb7d 311 } else if self.local_decls[local].is_user_variable() {
c30ab7b3
SL
312 LocalKind::Var
313 } else {
c30ab7b3
SL
314 LocalKind::Temp
315 }
316 }
317
318 /// Returns an iterator over all temporaries.
319 #[inline]
94b46f34
XL
320 pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
321 (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
c30ab7b3 322 let local = Local::new(index);
dfeec247 323 if self.local_decls[local].is_user_variable() { None } else { Some(local) }
c30ab7b3
SL
324 })
325 }
326
327 /// Returns an iterator over all user-declared locals.
328 #[inline]
94b46f34
XL
329 pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
330 (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
c30ab7b3 331 let local = Local::new(index);
60c5eb7d 332 self.local_decls[local].is_user_variable().then_some(local)
c30ab7b3 333 })
3157f602
XL
334 }
335
a1dfa0c6
XL
336 /// Returns an iterator over all user-declared mutable locals.
337 #[inline]
338 pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
339 (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
340 let local = Local::new(index);
341 let decl = &self.local_decls[local];
60c5eb7d 342 if decl.is_user_variable() && decl.mutability == Mutability::Mut {
a1dfa0c6
XL
343 Some(local)
344 } else {
345 None
346 }
347 })
348 }
349
83c7162d
XL
350 /// Returns an iterator over all user-declared mutable arguments and locals.
351 #[inline]
94b46f34 352 pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
83c7162d
XL
353 (1..self.local_decls.len()).filter_map(move |index| {
354 let local = Local::new(index);
355 let decl = &self.local_decls[local];
60c5eb7d 356 if (decl.is_user_variable() || index < self.arg_count + 1)
94b46f34 357 && decl.mutability == Mutability::Mut
83c7162d
XL
358 {
359 Some(local)
360 } else {
361 None
362 }
363 })
364 }
365
c30ab7b3
SL
366 /// Returns an iterator over all function arguments.
367 #[inline]
60c5eb7d 368 pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
c30ab7b3 369 let arg_count = self.arg_count;
60c5eb7d 370 (1..arg_count + 1).map(Local::new)
e9174d1e 371 }
9e0c209e 372
c30ab7b3 373 /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
ff7c6d11 374 /// locals that are neither arguments nor the return place).
c30ab7b3 375 #[inline]
60c5eb7d 376 pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
c30ab7b3
SL
377 let arg_count = self.arg_count;
378 let local_count = self.local_decls.len();
94b46f34 379 (arg_count + 1..local_count).map(Local::new)
9e0c209e
SL
380 }
381
382 /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
383 /// invalidating statement indices in `Location`s.
384 pub fn make_statement_nop(&mut self, location: Location) {
60c5eb7d 385 let block = &mut self.basic_blocks[location.block];
9e0c209e
SL
386 debug_assert!(location.statement_index < block.statements.len());
387 block.statements[location.statement_index].make_nop()
388 }
ea8adc8c
XL
389
390 /// Returns the source info associated with `location`.
391 pub fn source_info(&self, location: Location) -> &SourceInfo {
392 let block = &self[location.block];
393 let stmts = &block.statements;
394 let idx = location.statement_index;
abe05a73 395 if idx < stmts.len() {
ea8adc8c
XL
396 &stmts[idx].source_info
397 } else {
0bf4aa26 398 assert_eq!(idx, stmts.len());
ea8adc8c
XL
399 &block.terminator().source_info
400 }
401 }
abe05a73 402
9fa01778 403 /// Checks if `sub` is a sub scope of `sup`
94b46f34 404 pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool {
0bf4aa26 405 while sub != sup {
94b46f34
XL
406 match self.source_scopes[sub].parent_scope {
407 None => return false,
408 Some(p) => sub = p,
409 }
410 }
0bf4aa26 411 true
94b46f34
XL
412 }
413
e1599b0c 414 /// Returns the return type; it always return first element from `local_decls` array.
f9f354fc 415 #[inline]
abe05a73 416 pub fn return_ty(&self) -> Ty<'tcx> {
ff7c6d11 417 self.local_decls[RETURN_PLACE].ty
abe05a73 418 }
b7449926 419
e1599b0c 420 /// Gets the location of the terminator for the given block.
f9f354fc 421 #[inline]
b7449926 422 pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
416331ca 423 Location { block: bb, statement_index: self[bb].statements.len() }
b7449926 424 }
f9f354fc
XL
425
426 #[inline]
427 pub fn predecessors(&self) -> impl std::ops::Deref<Target = Predecessors> + '_ {
428 self.predecessor_cache.compute(&self.basic_blocks)
429 }
430
431 #[inline]
432 pub fn dominators(&self) -> Dominators<BasicBlock> {
433 dominators(self)
434 }
ea8adc8c
XL
435}
436
3dfed10e 437#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
ea8adc8c
XL
438pub enum Safety {
439 Safe,
440 /// Unsafe because of a PushUnsafeBlock
441 BuiltinUnsafe,
442 /// Unsafe because of an unsafe fn
443 FnUnsafe,
444 /// Unsafe because of an `unsafe` block
532ac7d7 445 ExplicitUnsafe(hir::HirId),
e9174d1e
SL
446}
447
dc9dc135 448impl<'tcx> Index<BasicBlock> for Body<'tcx> {
9cc50fc6
SL
449 type Output = BasicBlockData<'tcx>;
450
451 #[inline]
452 fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
3157f602 453 &self.basic_blocks()[index]
9cc50fc6
SL
454 }
455}
456
f9f354fc
XL
457impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
458 #[inline]
459 fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
460 &mut self.basic_blocks_mut()[index]
461 }
462}
463
60c5eb7d 464#[derive(Copy, Clone, Debug, HashStable, TypeFoldable)]
ff7c6d11 465pub enum ClearCrossCrate<T> {
ea8adc8c 466 Clear,
94b46f34 467 Set(T),
ea8adc8c
XL
468}
469
8faf50e0 470impl<T> ClearCrossCrate<T> {
ba9703b0 471 pub fn as_ref(&self) -> ClearCrossCrate<&T> {
60c5eb7d
XL
472 match self {
473 ClearCrossCrate::Clear => ClearCrossCrate::Clear,
474 ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
475 }
476 }
477
8faf50e0
XL
478 pub fn assert_crate_local(self) -> T {
479 match self {
480 ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
481 ClearCrossCrate::Set(v) => v,
482 }
483 }
484}
485
f035d41b
XL
486const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
487const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
488
3dfed10e 489impl<'tcx, E: TyEncoder<'tcx>, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> {
f035d41b 490 #[inline]
3dfed10e
XL
491 fn encode(&self, e: &mut E) -> Result<(), E::Error> {
492 if E::CLEAR_CROSS_CRATE {
493 return Ok(());
494 }
495
f035d41b
XL
496 match *self {
497 ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
498 ClearCrossCrate::Set(ref val) => {
499 TAG_CLEAR_CROSS_CRATE_SET.encode(e)?;
500 val.encode(e)
501 }
502 }
503 }
504}
3dfed10e 505impl<'tcx, D: TyDecoder<'tcx>, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> {
f035d41b 506 #[inline]
3dfed10e
XL
507 fn decode(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error> {
508 if D::CLEAR_CROSS_CRATE {
509 return Ok(ClearCrossCrate::Clear);
510 }
511
f035d41b
XL
512 let discr = u8::decode(d)?;
513
514 match discr {
515 TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(ClearCrossCrate::Clear),
516 TAG_CLEAR_CROSS_CRATE_SET => {
517 let val = T::decode(d)?;
518 Ok(ClearCrossCrate::Set(val))
519 }
3dfed10e 520 tag => Err(d.error(&format!("Invalid tag for ClearCrossCrate: {:?}", tag))),
f035d41b
XL
521 }
522 }
523}
ea8adc8c 524
3157f602
XL
525/// Grouped information about the source code origin of a MIR entity.
526/// Intended to be inspected by diagnostics and debuginfo.
527/// Most passes can work with it as a whole, within a single function.
60c5eb7d 528// The unofficial Cranelift backend, at least as of #65828, needs `SourceInfo` to implement `Eq` and
e74abb32 529// `Hash`. Please ping @bjorn3 if removing them.
3dfed10e 530#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
3157f602 531pub struct SourceInfo {
e1599b0c 532 /// The source span for the AST pertaining to this MIR entity.
3157f602
XL
533 pub span: Span,
534
94b46f34
XL
535 /// The source scope, keeping track of which bindings can be
536 /// seen by debuginfo, active lint levels, `unsafe {...}`, etc.
537 pub scope: SourceScope,
3157f602
XL
538}
539
f9f354fc
XL
540impl SourceInfo {
541 #[inline]
542 pub fn outermost(span: Span) -> Self {
543 SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }
544 }
545}
546
e9174d1e 547///////////////////////////////////////////////////////////////////////////
dfeec247 548// Borrow kinds
94b46f34 549
3dfed10e 550#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
ba9703b0 551#[derive(HashStable)]
e9174d1e
SL
552pub enum BorrowKind {
553 /// Data must be immutable and is aliasable.
554 Shared,
555
0bf4aa26
XL
556 /// The immediately borrowed place must be immutable, but projections from
557 /// it don't need to be. For example, a shallow borrow of `a.b` doesn't
558 /// conflict with a mutable borrow of `a.b.c`.
559 ///
560 /// This is used when lowering matches: when matching on a place we want to
561 /// ensure that place have the same value from the start of the match until
562 /// an arm is selected. This prevents this code from compiling:
563 ///
564 /// let mut x = &Some(0);
565 /// match *x {
566 /// None => (),
567 /// Some(_) if { x = &None; false } => (),
568 /// Some(_) => (),
569 /// }
570 ///
571 /// This can't be a shared borrow because mutably borrowing (*x as Some).0
572 /// should not prevent `if let None = x { ... }`, for example, because the
573 /// mutating `(*x as Some).0` can't affect the discriminant of `x`.
574 /// We can also report errors with this kind of borrow differently.
575 Shallow,
576
9fa01778 577 /// Data must be immutable but not aliasable. This kind of borrow
e9174d1e 578 /// cannot currently be expressed by the user and is used only in
b7449926
XL
579 /// implicit closure bindings. It is needed when the closure is
580 /// borrowing or mutating a mutable referent, e.g.:
e9174d1e 581 ///
a1dfa0c6
XL
582 /// let x: &mut isize = ...;
583 /// let y = || *x += 5;
e9174d1e
SL
584 ///
585 /// If we were to try to translate this closure into a more explicit
586 /// form, we'd encounter an error with the code as written:
587 ///
a1dfa0c6
XL
588 /// struct Env { x: & &mut isize }
589 /// let x: &mut isize = ...;
590 /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
591 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
e9174d1e 592 ///
b7449926 593 /// This is then illegal because you cannot mutate an `&mut` found
e9174d1e
SL
594 /// in an aliasable location. To solve, you'd have to translate with
595 /// an `&mut` borrow:
596 ///
a1dfa0c6
XL
597 /// struct Env { x: & &mut isize }
598 /// let x: &mut isize = ...;
599 /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
600 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
e9174d1e
SL
601 ///
602 /// Now the assignment to `**env.x` is legal, but creating a
603 /// mutable pointer to `x` is not because `x` is not mutable. We
604 /// could fix this by declaring `x` as `let mut x`. This is ok in
605 /// user code, if awkward, but extra weird for closures, since the
606 /// borrow is hidden.
607 ///
608 /// So we introduce a "unique imm" borrow -- the referent is
609 /// immutable, but not aliasable. This solves the problem. For
610 /// simplicity, we don't give users the way to express this
611 /// borrow, it's just used when translating closures.
612 Unique,
613
614 /// Data is mutable and not aliasable.
2c00a5a8 615 Mut {
9fa01778
XL
616 /// `true` if this borrow arose from method-call auto-ref
617 /// (i.e., `adjustment::Adjust::Borrow`).
94b46f34
XL
618 allow_two_phase_borrow: bool,
619 },
2c00a5a8
XL
620}
621
622impl BorrowKind {
623 pub fn allows_two_phase_borrow(&self) -> bool {
624 match *self {
0bf4aa26
XL
625 BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
626 BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow,
2c00a5a8
XL
627 }
628 }
e9174d1e
SL
629}
630
631///////////////////////////////////////////////////////////////////////////
632// Variables and temps
633
e74abb32 634rustc_index::newtype_index! {
b7449926 635 pub struct Local {
532ac7d7 636 derive [HashStable]
abe05a73 637 DEBUG_FORMAT = "_{}",
ff7c6d11 638 const RETURN_PLACE = 0,
b7449926
XL
639 }
640}
54a0048b 641
416331ca
XL
642impl Atom for Local {
643 fn index(self) -> usize {
644 Idx::index(self)
645 }
646}
647
dc9dc135 648/// Classifies locals into categories. See `Body::local_kind`.
532ac7d7 649#[derive(PartialEq, Eq, Debug, HashStable)]
c30ab7b3 650pub enum LocalKind {
e1599b0c 651 /// User-declared variable binding.
c30ab7b3 652 Var,
e1599b0c 653 /// Compiler-introduced temporary.
c30ab7b3 654 Temp,
e1599b0c 655 /// Function argument.
c30ab7b3 656 Arg,
e1599b0c 657 /// Location of function's return value.
c30ab7b3 658 ReturnPointer,
e9174d1e
SL
659}
660
3dfed10e 661#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
8faf50e0 662pub struct VarBindingForm<'tcx> {
94b46f34
XL
663 /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
664 pub binding_mode: ty::BindingMode,
665 /// If an explicit type was provided for this variable binding,
666 /// this holds the source Span of that type.
667 ///
9fa01778 668 /// NOTE: if you want to change this to a `HirId`, be wary that
94b46f34
XL
669 /// doing so breaks incremental compilation (as of this writing),
670 /// while a `Span` does not cause our tests to fail.
671 pub opt_ty_info: Option<Span>,
8faf50e0
XL
672 /// Place of the RHS of the =, or the subject of the `match` where this
673 /// variable is initialized. None in the case of `let PATTERN;`.
674 /// Some((None, ..)) in the case of and `let [mut] x = ...` because
675 /// (a) the right-hand side isn't evaluated as a place expression.
676 /// (b) it gives a way to separate this case from the remaining cases
677 /// for diagnostics.
678 pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
e1599b0c 679 /// The span of the pattern in which this variable was bound.
b7449926 680 pub pat_span: Span,
94b46f34
XL
681}
682
3dfed10e 683#[derive(Clone, Debug, TyEncodable, TyDecodable)]
8faf50e0 684pub enum BindingForm<'tcx> {
94b46f34 685 /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
8faf50e0 686 Var(VarBindingForm<'tcx>),
94b46f34 687 /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
0bf4aa26 688 ImplicitSelf(ImplicitSelfKind),
8faf50e0
XL
689 /// Reference used in a guard expression to ensure immutability.
690 RefForGuard,
94b46f34
XL
691}
692
0bf4aa26 693/// Represents what type of implicit self a function has, if any.
3dfed10e 694#[derive(Clone, Copy, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
0bf4aa26
XL
695pub enum ImplicitSelfKind {
696 /// Represents a `fn x(self);`.
697 Imm,
698 /// Represents a `fn x(mut self);`.
699 Mut,
700 /// Represents a `fn x(&self);`.
701 ImmRef,
702 /// Represents a `fn x(&mut self);`.
703 MutRef,
704 /// Represents when a function does not have a self argument or
705 /// when a function has a `self: X` argument.
416331ca 706 None,
0bf4aa26
XL
707}
708
8faf50e0 709CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, }
94b46f34 710
8faf50e0 711mod binding_form_impl {
9fa01778 712 use crate::ich::StableHashingContext;
e74abb32 713 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
8faf50e0
XL
714
715 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for super::BindingForm<'tcx> {
e74abb32 716 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
8faf50e0
XL
717 use super::BindingForm::*;
718 ::std::mem::discriminant(self).hash_stable(hcx, hasher);
719
720 match self {
721 Var(binding) => binding.hash_stable(hcx, hasher),
0bf4aa26 722 ImplicitSelf(kind) => kind.hash_stable(hcx, hasher),
8faf50e0
XL
723 RefForGuard => (),
724 }
725 }
726 }
727}
94b46f34 728
0bf4aa26
XL
729/// `BlockTailInfo` is attached to the `LocalDecl` for temporaries
730/// created during evaluation of expressions in a block tail
731/// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`.
732///
733/// It is used to improve diagnostics when such temporaries are
0731742a 734/// involved in borrow_check errors, e.g., explanations of where the
0bf4aa26
XL
735/// temporaries come from, when their destructors are run, and/or how
736/// one might revise the code to satisfy the borrow checker's rules.
3dfed10e 737#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
0bf4aa26
XL
738pub struct BlockTailInfo {
739 /// If `true`, then the value resulting from evaluating this tail
740 /// expression is ignored by the block's expression context.
741 ///
742 /// Examples include `{ ...; tail };` and `let _ = { ...; tail };`
0731742a 743 /// but not e.g., `let _x = { ...; tail };`
0bf4aa26 744 pub tail_result_is_ignored: bool,
f9f354fc
XL
745
746 /// `Span` of the tail expression.
747 pub span: Span,
0bf4aa26
XL
748}
749
c30ab7b3 750/// A MIR local.
7453a54e 751///
c30ab7b3 752/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
ff7c6d11 753/// argument, or the return place.
3dfed10e 754#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
c30ab7b3 755pub struct LocalDecl<'tcx> {
e1599b0c 756 /// Whether this is a mutable minding (i.e., `let x` or `let mut x`).
c30ab7b3 757 ///
ff7c6d11 758 /// Temporaries and the return place are always mutable.
c30ab7b3
SL
759 pub mutability: Mutability,
760
60c5eb7d 761 // FIXME(matthewjasper) Don't store in this in `Body`
f9f354fc 762 pub local_info: Option<Box<LocalInfo<'tcx>>>,
cc61c64b 763
9fa01778 764 /// `true` if this is an internal local.
ea8adc8c
XL
765 ///
766 /// These locals are not based on types in the source code and are only used
767 /// for a few desugarings at the moment.
768 ///
769 /// The generator transformation will sanity check the locals which are live
770 /// across a suspension point against the type components of the generator
771 /// which type checking knows are live across a suspension point. We need to
772 /// flag drop flags to avoid triggering this check as they are introduced
773 /// after typeck.
774 ///
775 /// Unsafety checking will also ignore dereferences of these locals,
776 /// so they can be used for raw pointers only used in a desugaring.
777 ///
778 /// This should be sound because the drop flags are fully algebraic, and
779 /// therefore don't affect the OIBIT or outlives properties of the
780 /// generator.
781 pub internal: bool,
782
0bf4aa26
XL
783 /// If this local is a temporary and `is_block_tail` is `Some`,
784 /// then it is a temporary created for evaluation of some
785 /// subexpression of some block's tail expression (with no
786 /// intervening statement context).
60c5eb7d 787 // FIXME(matthewjasper) Don't store in this in `Body`
0bf4aa26
XL
788 pub is_block_tail: Option<BlockTailInfo>,
789
e1599b0c 790 /// The type of this local.
b039eaaf 791 pub ty: Ty<'tcx>,
54a0048b 792
b7449926 793 /// If the user manually ascribed a type to this variable,
0731742a 794 /// e.g., via `let x: T`, then we carry that type here. The MIR
b7449926
XL
795 /// borrow checker needs this information since it can affect
796 /// region inference.
60c5eb7d 797 // FIXME(matthewjasper) Don't store in this in `Body`
f9f354fc 798 pub user_ty: Option<Box<UserTypeProjections>>,
b7449926 799
0731742a 800 /// The *syntactic* (i.e., not visibility) source scope the local is defined
ea8adc8c
XL
801 /// in. If the local was defined in a let-statement, this
802 /// is *within* the let-statement, rather than outside
803 /// of it.
ff7c6d11 804 ///
94b46f34
XL
805 /// This is needed because the visibility source scope of locals within
806 /// a let-statement is weird.
ff7c6d11
XL
807 ///
808 /// The reason is that we want the local to be *within* the let-statement
809 /// for lint purposes, but we want the local to be *after* the let-statement
810 /// for names-in-scope purposes.
811 ///
812 /// That's it, if we have a let-statement like the one in this
813 /// function:
814 ///
815 /// ```
816 /// fn foo(x: &str) {
817 /// #[allow(unused_mut)]
818 /// let mut x: u32 = { // <- one unused mut
819 /// let mut y: u32 = x.parse().unwrap();
820 /// y + 2
821 /// };
822 /// drop(x);
823 /// }
824 /// ```
825 ///
826 /// Then, from a lint point of view, the declaration of `x: u32`
827 /// (and `y: u32`) are within the `#[allow(unused_mut)]` scope - the
828 /// lint scopes are the same as the AST/HIR nesting.
829 ///
830 /// However, from a name lookup point of view, the scopes look more like
831 /// as if the let-statements were `match` expressions:
832 ///
833 /// ```
834 /// fn foo(x: &str) {
835 /// match {
836 /// match x.parse().unwrap() {
837 /// y => y + 2
838 /// }
839 /// } {
840 /// x => drop(x)
841 /// };
842 /// }
843 /// ```
844 ///
845 /// We care about the name-lookup scopes for debuginfo - if the
846 /// debuginfo instruction pointer is at the call to `x.parse()`, we
847 /// want `x` to refer to `x: &str`, but if it is at the call to
848 /// `drop(x)`, we want it to refer to `x: u32`.
849 ///
850 /// To allow both uses to work, we need to have more than a single scope
60c5eb7d
XL
851 /// for a local. We have the `source_info.scope` represent the "syntactic"
852 /// lint scope (with a variable being under its let block) while the
853 /// `var_debug_info.source_info.scope` represents the "local variable"
ff7c6d11
XL
854 /// scope (where the "rest" of a block is under all prior let-statements).
855 ///
856 /// The end result looks like this:
857 ///
858 /// ```text
859 /// ROOT SCOPE
860 /// │{ argument x: &str }
861 /// │
e1599b0c
XL
862 /// │ │{ #[allow(unused_mut)] } // This is actually split into 2 scopes
863 /// │ │ // in practice because I'm lazy.
ff7c6d11 864 /// │ │
94b46f34 865 /// │ │← x.source_info.scope
ff7c6d11
XL
866 /// │ │← `x.parse().unwrap()`
867 /// │ │
94b46f34 868 /// │ │ │← y.source_info.scope
ff7c6d11
XL
869 /// │ │
870 /// │ │ │{ let y: u32 }
871 /// │ │ │
60c5eb7d 872 /// │ │ │← y.var_debug_info.source_info.scope
ff7c6d11
XL
873 /// │ │ │← `y + 2`
874 /// │
875 /// │ │{ let x: u32 }
60c5eb7d 876 /// │ │← x.var_debug_info.source_info.scope
e1599b0c 877 /// │ │← `drop(x)` // This accesses `x: u32`.
ff7c6d11 878 /// ```
94b46f34 879 pub source_info: SourceInfo,
60c5eb7d 880}
94b46f34 881
f9f354fc
XL
882// `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger.
883#[cfg(target_arch = "x86_64")]
884static_assert_size!(LocalDecl<'_>, 56);
885
3dfed10e
XL
886/// Extra information about a some locals that's used for diagnostics and for
887/// classifying variables into local variables, statics, etc, which is needed e.g.
888/// for unsafety checking.
889///
890/// Not used for non-StaticRef temporaries, the return place, or anonymous
891/// function parameters.
892#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
60c5eb7d
XL
893pub enum LocalInfo<'tcx> {
894 /// A user-defined local variable or function parameter
895 ///
896 /// The `BindingForm` is solely used for local diagnostics when generating
897 /// warnings/errors when compiling the current crate, and therefore it need
898 /// not be visible across crates.
899 User(ClearCrossCrate<BindingForm<'tcx>>),
900 /// A temporary created that references the static with the given `DefId`.
901 StaticRef { def_id: DefId, is_thread_local: bool },
c30ab7b3
SL
902}
903
904impl<'tcx> LocalDecl<'tcx> {
9fa01778 905 /// Returns `true` only if local is a binding that can itself be
94b46f34
XL
906 /// made mutable via the addition of the `mut` keyword, namely
907 /// something like the occurrences of `x` in:
908 /// - `fn foo(x: Type) { ... }`,
909 /// - `let x = ...`,
910 /// - or `match ... { C(x) => ... }`
911 pub fn can_be_made_mutable(&self) -> bool {
60c5eb7d 912 match self.local_info {
f9f354fc 913 Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
94b46f34
XL
914 binding_mode: ty::BindingMode::BindByValue(_),
915 opt_ty_info: _,
8faf50e0 916 opt_match_place: _,
b7449926 917 pat_span: _,
f9f354fc 918 })))) => true,
94b46f34 919
f9f354fc 920 Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
dfeec247 921 ImplicitSelfKind::Imm,
f9f354fc 922 )))) => true,
0bf4aa26 923
94b46f34
XL
924 _ => false,
925 }
926 }
927
9fa01778 928 /// Returns `true` if local is definitely not a `ref ident` or
94b46f34
XL
929 /// `ref mut ident` binding. (Such bindings cannot be made into
930 /// mutable bindings, but the inverse does not necessarily hold).
931 pub fn is_nonref_binding(&self) -> bool {
60c5eb7d 932 match self.local_info {
f9f354fc 933 Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
94b46f34
XL
934 binding_mode: ty::BindingMode::BindByValue(_),
935 opt_ty_info: _,
8faf50e0 936 opt_match_place: _,
b7449926 937 pat_span: _,
f9f354fc 938 })))) => true,
94b46f34 939
f9f354fc 940 Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_)))) => true,
60c5eb7d
XL
941
942 _ => false,
943 }
944 }
94b46f34 945
60c5eb7d
XL
946 /// Returns `true` if this variable is a named variable or function
947 /// parameter declared by the user.
948 #[inline]
949 pub fn is_user_variable(&self) -> bool {
950 match self.local_info {
f9f354fc 951 Some(box LocalInfo::User(_)) => true,
94b46f34
XL
952 _ => false,
953 }
954 }
955
dc9dc135
XL
956 /// Returns `true` if this is a reference to a variable bound in a `match`
957 /// expression that is used to access said variable for the guard of the
958 /// match arm.
959 pub fn is_ref_for_guard(&self) -> bool {
60c5eb7d 960 match self.local_info {
f9f354fc 961 Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) => true,
60c5eb7d
XL
962 _ => false,
963 }
964 }
965
966 /// Returns `Some` if this is a reference to a static item that is used to
967 /// access that static
968 pub fn is_ref_to_static(&self) -> bool {
969 match self.local_info {
f9f354fc 970 Some(box LocalInfo::StaticRef { .. }) => true,
60c5eb7d
XL
971 _ => false,
972 }
973 }
974
975 /// Returns `Some` if this is a reference to a static item that is used to
976 /// access that static
977 pub fn is_ref_to_thread_local(&self) -> bool {
978 match self.local_info {
f9f354fc 979 Some(box LocalInfo::StaticRef { is_thread_local, .. }) => is_thread_local,
dc9dc135
XL
980 _ => false,
981 }
982 }
983
984 /// Returns `true` is the local is from a compiler desugaring, e.g.,
985 /// `__next` from a `for` loop.
986 #[inline]
987 pub fn from_compiler_desugaring(&self) -> bool {
416331ca 988 self.source_info.span.desugaring_kind().is_some()
dc9dc135
XL
989 }
990
f9f354fc 991 /// Creates a new `LocalDecl` for a temporary: mutable, non-internal.
c30ab7b3 992 #[inline]
f9f354fc
XL
993 pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
994 Self::with_source_info(ty, SourceInfo::outermost(span))
995 }
996
997 /// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
998 #[inline]
999 pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
1000 LocalDecl {
1001 mutability: Mutability::Mut,
1002 local_info: None,
1003 internal: false,
1004 is_block_tail: None,
1005 ty,
1006 user_ty: None,
1007 source_info,
1008 }
1009 }
1010
1011 /// Converts `self` into same `LocalDecl` except tagged as internal.
1012 #[inline]
1013 pub fn internal(mut self) -> Self {
1014 self.internal = true;
1015 self
b7449926
XL
1016 }
1017
0bf4aa26 1018 /// Converts `self` into same `LocalDecl` except tagged as immutable.
b7449926 1019 #[inline]
0bf4aa26
XL
1020 pub fn immutable(mut self) -> Self {
1021 self.mutability = Mutability::Not;
1022 self
1023 }
1024
1025 /// Converts `self` into same `LocalDecl` except tagged as internal temporary.
1026 #[inline]
1027 pub fn block_tail(mut self, info: BlockTailInfo) -> Self {
1028 assert!(self.is_block_tail.is_none());
1029 self.is_block_tail = Some(info);
1030 self
ea8adc8c 1031 }
a7813a04
XL
1032}
1033
60c5eb7d 1034/// Debug information pertaining to a user variable.
3dfed10e 1035#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
60c5eb7d 1036pub struct VarDebugInfo<'tcx> {
f9f354fc 1037 pub name: Symbol,
60c5eb7d
XL
1038
1039 /// Source info of the user variable, including the scope
1040 /// within which the variable is visible (to debuginfo)
1041 /// (see `LocalDecl`'s `source_info` field for more details).
1042 pub source_info: SourceInfo,
a7813a04 1043
60c5eb7d
XL
1044 /// Where the data for this user variable is to be found.
1045 /// NOTE(eddyb) There's an unenforced invariant that this `Place` is
1046 /// based on a `Local`, not a `Static`, and contains no indexing.
1047 pub place: Place<'tcx>,
e9174d1e
SL
1048}
1049
e9174d1e
SL
1050///////////////////////////////////////////////////////////////////////////
1051// BasicBlock
1052
e74abb32 1053rustc_index::newtype_index! {
b7449926 1054 pub struct BasicBlock {
532ac7d7 1055 derive [HashStable]
b7449926
XL
1056 DEBUG_FORMAT = "bb{}",
1057 const START_BLOCK = 0,
1058 }
1059}
abe05a73
XL
1060
1061impl BasicBlock {
1062 pub fn start_location(self) -> Location {
416331ca 1063 Location { block: self, statement_index: 0 }
abe05a73
XL
1064 }
1065}
e9174d1e
SL
1066
1067///////////////////////////////////////////////////////////////////////////
54a0048b 1068// BasicBlockData and Terminator
e9174d1e 1069
3dfed10e 1070#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
b039eaaf 1071pub struct BasicBlockData<'tcx> {
54a0048b 1072 /// List of statements in this block.
b039eaaf 1073 pub statements: Vec<Statement<'tcx>>,
54a0048b
SL
1074
1075 /// Terminator for this block.
1076 ///
9fa01778 1077 /// N.B., this should generally ONLY be `None` during construction.
54a0048b
SL
1078 /// Therefore, you should generally access it via the
1079 /// `terminator()` or `terminator_mut()` methods. The only
1080 /// exception is that certain passes, such as `simplify_cfg`, swap
1081 /// out the terminator temporarily with `None` while they continue
1082 /// to recurse over the set of basic blocks.
9cc50fc6 1083 pub terminator: Option<Terminator<'tcx>>,
54a0048b
SL
1084
1085 /// If true, this block lies on an unwind path. This is used
94b46f34 1086 /// during codegen where distinct kinds of basic blocks may be
54a0048b
SL
1087 /// generated (particularly for MSVC cleanup). Unwind blocks must
1088 /// only branch to other unwind blocks.
9cc50fc6 1089 pub is_cleanup: bool,
e9174d1e
SL
1090}
1091
74b04a01 1092/// Information about an assertion failure.
3dfed10e 1093#[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)]
74b04a01
XL
1094pub enum AssertKind<O> {
1095 BoundsCheck { len: O, index: O },
f035d41b
XL
1096 Overflow(BinOp, O, O),
1097 OverflowNeg(O),
1098 DivisionByZero(O),
1099 RemainderByZero(O),
74b04a01
XL
1100 ResumedAfterReturn(GeneratorKind),
1101 ResumedAfterPanic(GeneratorKind),
1102}
1103
3dfed10e 1104#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
f9f354fc
XL
1105pub enum InlineAsmOperand<'tcx> {
1106 In {
1107 reg: InlineAsmRegOrRegClass,
1108 value: Operand<'tcx>,
1109 },
1110 Out {
1111 reg: InlineAsmRegOrRegClass,
1112 late: bool,
1113 place: Option<Place<'tcx>>,
1114 },
1115 InOut {
1116 reg: InlineAsmRegOrRegClass,
1117 late: bool,
1118 in_value: Operand<'tcx>,
1119 out_place: Option<Place<'tcx>>,
1120 },
1121 Const {
1122 value: Operand<'tcx>,
1123 },
1124 SymFn {
1125 value: Box<Constant<'tcx>>,
1126 },
1127 SymStatic {
f035d41b 1128 def_id: DefId,
f9f354fc
XL
1129 },
1130}
1131
74b04a01
XL
1132/// Type for MIR `Assert` terminator error messages.
1133pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
1134
83c7162d
XL
1135pub type Successors<'a> =
1136 iter::Chain<option::IntoIter<&'a BasicBlock>, slice::Iter<'a, BasicBlock>>;
1137pub type SuccessorsMut<'a> =
1138 iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
1139
b039eaaf 1140impl<'tcx> BasicBlockData<'tcx> {
9cc50fc6 1141 pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
416331ca 1142 BasicBlockData { statements: vec![], terminator, is_cleanup: false }
e9174d1e 1143 }
9cc50fc6
SL
1144
1145 /// Accessor for terminator.
1146 ///
1147 /// Terminator may not be None after construction of the basic block is complete. This accessor
1148 /// provides a convenience way to reach the terminator.
1149 pub fn terminator(&self) -> &Terminator<'tcx> {
1150 self.terminator.as_ref().expect("invalid terminator state")
1151 }
1152
1153 pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
1154 self.terminator.as_mut().expect("invalid terminator state")
1155 }
ea8adc8c 1156
94b46f34
XL
1157 pub fn retain_statements<F>(&mut self, mut f: F)
1158 where
0bf4aa26 1159 F: FnMut(&mut Statement<'_>) -> bool,
94b46f34 1160 {
ea8adc8c
XL
1161 for s in &mut self.statements {
1162 if !f(s) {
0531ce1d 1163 s.make_nop();
ea8adc8c
XL
1164 }
1165 }
1166 }
ff7c6d11 1167
0531ce1d 1168 pub fn expand_statements<F, I>(&mut self, mut f: F)
94b46f34
XL
1169 where
1170 F: FnMut(&mut Statement<'tcx>) -> Option<I>,
1171 I: iter::TrustedLen<Item = Statement<'tcx>>,
0531ce1d
XL
1172 {
1173 // Gather all the iterators we'll need to splice in, and their positions.
1174 let mut splices: Vec<(usize, I)> = vec![];
1175 let mut extra_stmts = 0;
1176 for (i, s) in self.statements.iter_mut().enumerate() {
1177 if let Some(mut new_stmts) = f(s) {
1178 if let Some(first) = new_stmts.next() {
1179 // We can already store the first new statement.
1180 *s = first;
1181
1182 // Save the other statements for optimized splicing.
1183 let remaining = new_stmts.size_hint().0;
1184 if remaining > 0 {
1185 splices.push((i + 1 + extra_stmts, new_stmts));
1186 extra_stmts += remaining;
1187 }
1188 } else {
1189 s.make_nop();
1190 }
1191 }
1192 }
1193
1194 // Splice in the new statements, from the end of the block.
1195 // FIXME(eddyb) This could be more efficient with a "gap buffer"
1196 // where a range of elements ("gap") is left uninitialized, with
1197 // splicing adding new elements to the end of that gap and moving
1198 // existing elements from before the gap to the end of the gap.
1199 // For now, this is safe code, emulating a gap but initializing it.
94b46f34
XL
1200 let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
1201 self.statements.resize(
1202 gap.end,
f9f354fc 1203 Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
94b46f34 1204 );
0531ce1d
XL
1205 for (splice_start, new_stmts) in splices.into_iter().rev() {
1206 let splice_end = splice_start + new_stmts.size_hint().0;
1207 while gap.end > splice_end {
1208 gap.start -= 1;
1209 gap.end -= 1;
1210 self.statements.swap(gap.start, gap.end);
1211 }
1212 self.statements.splice(splice_start..splice_end, new_stmts);
1213 gap.end = splice_start;
1214 }
1215 }
1216
ff7c6d11 1217 pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
dfeec247 1218 if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
ff7c6d11 1219 }
e9174d1e
SL
1220}
1221
74b04a01
XL
1222impl<O> AssertKind<O> {
1223 /// Getting a description does not require `O` to be printable, and does not
1224 /// require allocation.
1225 /// The caller is expected to handle `BoundsCheck` separately.
1226 pub fn description(&self) -> &'static str {
1227 use AssertKind::*;
1228 match self {
f035d41b
XL
1229 Overflow(BinOp::Add, _, _) => "attempt to add with overflow",
1230 Overflow(BinOp::Sub, _, _) => "attempt to subtract with overflow",
1231 Overflow(BinOp::Mul, _, _) => "attempt to multiply with overflow",
1232 Overflow(BinOp::Div, _, _) => "attempt to divide with overflow",
1233 Overflow(BinOp::Rem, _, _) => "attempt to calculate the remainder with overflow",
1234 OverflowNeg(_) => "attempt to negate with overflow",
1235 Overflow(BinOp::Shr, _, _) => "attempt to shift right with overflow",
1236 Overflow(BinOp::Shl, _, _) => "attempt to shift left with overflow",
1237 Overflow(op, _, _) => bug!("{:?} cannot overflow", op),
1238 DivisionByZero(_) => "attempt to divide by zero",
1239 RemainderByZero(_) => "attempt to calculate the remainder with a divisor of zero",
74b04a01
XL
1240 ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion",
1241 ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion",
1242 ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking",
1243 ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking",
1244 BoundsCheck { .. } => bug!("Unexpected AssertKind"),
1245 }
1246 }
ba9703b0
XL
1247
1248 /// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing.
1249 fn fmt_assert_args<W: Write>(&self, f: &mut W) -> fmt::Result
1250 where
1251 O: Debug,
1252 {
f035d41b 1253 use AssertKind::*;
ba9703b0 1254 match self {
f035d41b 1255 BoundsCheck { ref len, ref index } => write!(
ba9703b0
XL
1256 f,
1257 "\"index out of bounds: the len is {{}} but the index is {{}}\", {:?}, {:?}",
1258 len, index
1259 ),
f035d41b
XL
1260
1261 OverflowNeg(op) => {
1262 write!(f, "\"attempt to negate {{}} which would overflow\", {:?}", op)
1263 }
1264 DivisionByZero(op) => write!(f, "\"attempt to divide {{}} by zero\", {:?}", op),
1265 RemainderByZero(op) => write!(
1266 f,
1267 "\"attempt to calculate the remainder of {{}} with a divisor of zero\", {:?}",
1268 op
1269 ),
1270 Overflow(BinOp::Add, l, r) => write!(
1271 f,
1272 "\"attempt to compute `{{}} + {{}}` which would overflow\", {:?}, {:?}",
1273 l, r
1274 ),
1275 Overflow(BinOp::Sub, l, r) => write!(
1276 f,
1277 "\"attempt to compute `{{}} - {{}}` which would overflow\", {:?}, {:?}",
1278 l, r
1279 ),
1280 Overflow(BinOp::Mul, l, r) => write!(
1281 f,
1282 "\"attempt to compute `{{}} * {{}}` which would overflow\", {:?}, {:?}",
1283 l, r
1284 ),
1285 Overflow(BinOp::Div, l, r) => write!(
1286 f,
1287 "\"attempt to compute `{{}} / {{}}` which would overflow\", {:?}, {:?}",
1288 l, r
1289 ),
1290 Overflow(BinOp::Rem, l, r) => write!(
1291 f,
1292 "\"attempt to compute the remainder of `{{}} % {{}}` which would overflow\", {:?}, {:?}",
1293 l, r
1294 ),
1295 Overflow(BinOp::Shr, _, r) => {
1296 write!(f, "\"attempt to shift right by {{}} which would overflow\", {:?}", r)
1297 }
1298 Overflow(BinOp::Shl, _, r) => {
1299 write!(f, "\"attempt to shift left by {{}} which would overflow\", {:?}", r)
1300 }
ba9703b0
XL
1301 _ => write!(f, "\"{}\"", self.description()),
1302 }
1303 }
74b04a01
XL
1304}
1305
1306impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
1307 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1308 use AssertKind::*;
1309 match self {
1310 BoundsCheck { ref len, ref index } => {
1311 write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index)
1312 }
f035d41b
XL
1313 OverflowNeg(op) => write!(f, "attempt to negate {:#?} which would overflow", op),
1314 DivisionByZero(op) => write!(f, "attempt to divide {:#?} by zero", op),
1315 RemainderByZero(op) => {
1316 write!(f, "attempt to calculate the remainder of {:#?} with a divisor of zero", op)
416331ca 1317 }
f035d41b
XL
1318 Overflow(BinOp::Add, l, r) => {
1319 write!(f, "attempt to compute `{:#?} + {:#?}` which would overflow", l, r)
e9174d1e 1320 }
f035d41b
XL
1321 Overflow(BinOp::Sub, l, r) => {
1322 write!(f, "attempt to compute `{:#?} - {:#?}` which would overflow", l, r)
94b46f34 1323 }
f035d41b
XL
1324 Overflow(BinOp::Mul, l, r) => {
1325 write!(f, "attempt to compute `{:#?} * {:#?}` which would overflow", l, r)
f9f354fc 1326 }
f035d41b
XL
1327 Overflow(BinOp::Div, l, r) => {
1328 write!(f, "attempt to compute `{:#?} / {:#?}` which would overflow", l, r)
9cc50fc6 1329 }
f035d41b
XL
1330 Overflow(BinOp::Rem, l, r) => write!(
1331 f,
1332 "attempt to compute the remainder of `{:#?} % {:#?}` which would overflow",
1333 l, r
1334 ),
1335 Overflow(BinOp::Shr, _, r) => {
1336 write!(f, "attempt to shift right by {:#?} which would overflow", r)
94b46f34 1337 }
f035d41b
XL
1338 Overflow(BinOp::Shl, _, r) => {
1339 write!(f, "attempt to shift left by {:#?} which would overflow", r)
3157f602 1340 }
f035d41b 1341 _ => write!(f, "{}", self.description()),
9cc50fc6
SL
1342 }
1343 }
e9174d1e
SL
1344}
1345
e9174d1e
SL
1346///////////////////////////////////////////////////////////////////////////
1347// Statements
1348
3dfed10e 1349#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
b039eaaf 1350pub struct Statement<'tcx> {
3157f602 1351 pub source_info: SourceInfo,
b039eaaf 1352 pub kind: StatementKind<'tcx>,
e9174d1e
SL
1353}
1354
a1dfa0c6
XL
1355// `Statement` is used a lot. Make sure it doesn't unintentionally get bigger.
1356#[cfg(target_arch = "x86_64")]
e1599b0c 1357static_assert_size!(Statement<'_>, 32);
a1dfa0c6 1358
e1599b0c 1359impl Statement<'_> {
9e0c209e
SL
1360 /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
1361 /// invalidating statement indices in `Location`s.
1362 pub fn make_nop(&mut self) {
1363 self.kind = StatementKind::Nop
1364 }
0531ce1d
XL
1365
1366 /// Changes a statement to a nop and returns the original statement.
1367 pub fn replace_nop(&mut self) -> Self {
1368 Statement {
1369 source_info: self.source_info,
94b46f34 1370 kind: mem::replace(&mut self.kind, StatementKind::Nop),
0531ce1d
XL
1371 }
1372 }
9e0c209e
SL
1373}
1374
3dfed10e 1375#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
b039eaaf 1376pub enum StatementKind<'tcx> {
ff7c6d11 1377 /// Write the RHS Rvalue to the LHS Place.
e1599b0c 1378 Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
5bcae85e 1379
94b46f34 1380 /// This represents all the reading that a pattern match may do
0731742a 1381 /// (e.g., inspecting constants and discriminant values), and the
0bf4aa26
XL
1382 /// kind of pattern it comes from. This is in order to adapt potential
1383 /// error messages to these specific patterns.
0731742a
XL
1384 ///
1385 /// Note that this also is emitted for regular `let` bindings to ensure that locals that are
9fa01778 1386 /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
e1599b0c 1387 FakeRead(FakeReadCause, Box<Place<'tcx>>),
94b46f34 1388
ff7c6d11 1389 /// Write the discriminant for a variant to the enum Place.
e1599b0c 1390 SetDiscriminant { place: Box<Place<'tcx>>, variant_index: VariantIdx },
5bcae85e
SL
1391
1392 /// Start a live range for the storage of the local.
ea8adc8c 1393 StorageLive(Local),
5bcae85e
SL
1394
1395 /// End the current live range for the storage of the local.
ea8adc8c 1396 StorageDead(Local),
9e0c209e 1397
532ac7d7
XL
1398 /// Executes a piece of inline Assembly. Stored in a Box to keep the size
1399 /// of `StatementKind` low.
ba9703b0 1400 LlvmInlineAsm(Box<LlvmInlineAsm<'tcx>>),
8bb4bdeb 1401
9fa01778 1402 /// Retag references in the given place, ensuring they got fresh tags. This is
a1dfa0c6
XL
1403 /// part of the Stacked Borrows model. These statements are currently only interpreted
1404 /// by miri and only generated when "-Z mir-emit-retag" is passed.
1405 /// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
1406 /// for more details.
e1599b0c 1407 Retag(RetagKind, Box<Place<'tcx>>),
041b39d2 1408
b7449926
XL
1409 /// Encodes a user's type ascription. These need to be preserved
1410 /// intact so that NLL can respect them. For example:
0531ce1d 1411 ///
b7449926 1412 /// let a: T = y;
0531ce1d 1413 ///
b7449926
XL
1414 /// The effect of this annotation is to relate the type `T_y` of the place `y`
1415 /// to the user-given type `T`. The effect depends on the specified variance:
0531ce1d 1416 ///
b7449926
XL
1417 /// - `Covariant` -- requires that `T_y <: T`
1418 /// - `Contravariant` -- requires that `T_y :> T`
1419 /// - `Invariant` -- requires that `T_y == T`
1420 /// - `Bivariant` -- no effect
e1599b0c 1421 AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance),
0531ce1d 1422
3dfed10e
XL
1423 /// Marks the start of a "coverage region", injected with '-Zinstrument-coverage'. A
1424 /// `CoverageInfo` statement carries metadata about the coverage region, used to inject a coverage
1425 /// map into the binary. The `Counter` kind also generates executable code, to increment a
1426 /// counter varible at runtime, each time the code region is executed.
1427 Coverage(Box<Coverage>),
1428
9e0c209e
SL
1429 /// No-op. Useful for deleting instructions without affecting statement indices.
1430 Nop,
e9174d1e
SL
1431}
1432
e1599b0c 1433/// Describes what kind of retag is to be performed.
3dfed10e 1434#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, HashStable)]
0731742a 1435pub enum RetagKind {
e1599b0c 1436 /// The initial retag when entering a function.
0731742a 1437 FnEntry,
e1599b0c 1438 /// Retag preparing for a two-phase borrow.
0731742a 1439 TwoPhase,
e1599b0c 1440 /// Retagging raw pointers.
0731742a 1441 Raw,
e1599b0c 1442 /// A "normal" retag.
0731742a
XL
1443 Default,
1444}
1445
e1599b0c 1446/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
3dfed10e 1447#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, HashStable, PartialEq)]
0bf4aa26 1448pub enum FakeReadCause {
9fa01778
XL
1449 /// Inject a fake read of the borrowed input at the end of each guards
1450 /// code.
0bf4aa26 1451 ///
9fa01778
XL
1452 /// This should ensure that you cannot change the variant for an enum while
1453 /// you are in the midst of matching on it.
0bf4aa26
XL
1454 ForMatchGuard,
1455
1456 /// `let x: !; match x {}` doesn't generate any read of x so we need to
1457 /// generate a read of x to check that it is initialized and safe.
1458 ForMatchedPlace,
1459
9fa01778
XL
1460 /// A fake read of the RefWithinGuard version of a bind-by-value variable
1461 /// in a match guard to ensure that it's value hasn't change by the time
1462 /// we create the OutsideGuard version.
1463 ForGuardBinding,
1464
0bf4aa26
XL
1465 /// Officially, the semantics of
1466 ///
1467 /// `let pattern = <expr>;`
1468 ///
1469 /// is that `<expr>` is evaluated into a temporary and then this temporary is
1470 /// into the pattern.
1471 ///
1472 /// However, if we see the simple pattern `let var = <expr>`, we optimize this to
1473 /// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable,
1474 /// but in some cases it can affect the borrow checker, as in #53695.
1475 /// Therefore, we insert a "fake read" here to ensure that we get
1476 /// appropriate errors.
1477 ForLet,
60c5eb7d
XL
1478
1479 /// If we have an index expression like
1480 ///
1481 /// (*x)[1][{ x = y; 4}]
1482 ///
1483 /// then the first bounds check is invalidated when we evaluate the second
1484 /// index expression. Thus we create a fake borrow of `x` across the second
1485 /// indexer, which will cause a borrow check error.
1486 ForIndex,
0bf4aa26
XL
1487}
1488
3dfed10e 1489#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
ba9703b0
XL
1490pub struct LlvmInlineAsm<'tcx> {
1491 pub asm: hir::LlvmInlineAsmInner,
532ac7d7
XL
1492 pub outputs: Box<[Place<'tcx>]>,
1493 pub inputs: Box<[(Span, Operand<'tcx>)]>,
1494}
1495
e1599b0c 1496impl Debug for Statement<'_> {
0bf4aa26 1497 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
e9174d1e
SL
1498 use self::StatementKind::*;
1499 match self.kind {
dfeec247 1500 Assign(box (ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv),
0bf4aa26 1501 FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
416331ca
XL
1502 Retag(ref kind, ref place) => write!(
1503 fmt,
1504 "Retag({}{:?})",
1505 match kind {
1506 RetagKind::FnEntry => "[fn entry] ",
1507 RetagKind::TwoPhase => "[2phase] ",
1508 RetagKind::Raw => "[raw] ",
1509 RetagKind::Default => "",
1510 },
1511 place,
1512 ),
ff7c6d11
XL
1513 StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
1514 StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
416331ca
XL
1515 SetDiscriminant { ref place, variant_index } => {
1516 write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
1517 }
ba9703b0
XL
1518 LlvmInlineAsm(ref asm) => {
1519 write!(fmt, "llvm_asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs)
416331ca 1520 }
dfeec247 1521 AscribeUserType(box (ref place, ref c_ty), ref variance) => {
b7449926 1522 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
94b46f34 1523 }
3dfed10e 1524 Coverage(box ref coverage) => write!(fmt, "{:?}", coverage),
9e0c209e 1525 Nop => write!(fmt, "nop"),
e9174d1e
SL
1526 }
1527 }
1528}
54a0048b 1529
3dfed10e
XL
1530#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
1531pub struct Coverage {
1532 pub kind: CoverageKind,
1533 pub code_region: CodeRegion,
1534}
1535
e9174d1e 1536///////////////////////////////////////////////////////////////////////////
ff7c6d11 1537// Places
e9174d1e
SL
1538
1539/// A path to a value; something that can be evaluated without
1540/// changing or disturbing program state.
3dfed10e 1541#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
416331ca 1542pub struct Place<'tcx> {
dfeec247 1543 pub local: Local,
532ac7d7
XL
1544
1545 /// projection out of a place (access a field, deref a pointer, etc)
e74abb32 1546 pub projection: &'tcx List<PlaceElem<'tcx>>,
532ac7d7
XL
1547}
1548
60c5eb7d 1549#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3dfed10e 1550#[derive(TyEncodable, TyDecodable, HashStable)]
532ac7d7 1551pub enum ProjectionElem<V, T> {
e9174d1e 1552 Deref,
3b2f2976 1553 Field(Field, T),
e9174d1e
SL
1554 Index(V),
1555
7453a54e
SL
1556 /// These indices are generated by slice patterns. Easiest to explain
1557 /// by example:
1558 ///
1559 /// ```
1560 /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
1561 /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
1562 /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
1563 /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true },
1564 /// ```
e9174d1e 1565 ConstantIndex {
7453a54e
SL
1566 /// index or -index (in Python terms), depending on from_end
1567 offset: u32,
60c5eb7d
XL
1568 /// The thing being indexed must be at least this long. For arrays this
1569 /// is always the exact length.
7453a54e 1570 min_length: u32,
60c5eb7d
XL
1571 /// Counting backwards from end? This is always false when indexing an
1572 /// array.
7453a54e 1573 from_end: bool,
e9174d1e
SL
1574 },
1575
3157f602
XL
1576 /// These indices are generated by slice patterns.
1577 ///
60c5eb7d
XL
1578 /// If `from_end` is true `slice[from..slice.len() - to]`.
1579 /// Otherwise `array[from..to]`.
3157f602
XL
1580 Subslice {
1581 from: u32,
1582 to: u32,
60c5eb7d
XL
1583 /// Whether `to` counts from the start or end of the array/slice.
1584 /// For `PlaceElem`s this is `true` if and only if the base is a slice.
1585 /// For `ProjectionKind`, this can also be `true` for arrays.
1586 from_end: bool,
3157f602
XL
1587 },
1588
7453a54e
SL
1589 /// "Downcast" to a variant of an ADT. Currently, we only introduce
1590 /// this for ADTs with more than one variant. It may be better to
1591 /// just introduce it always, or always for enums.
532ac7d7
XL
1592 ///
1593 /// The included Symbol is the name of the variant, used for printing MIR.
1594 Downcast(Option<Symbol>, VariantIdx),
e9174d1e
SL
1595}
1596
e1599b0c
XL
1597impl<V, T> ProjectionElem<V, T> {
1598 /// Returns `true` if the target of this projection may refer to a different region of memory
1599 /// than the base.
1600 fn is_indirect(&self) -> bool {
1601 match self {
1602 Self::Deref => true,
1603
dfeec247 1604 Self::Field(_, _)
e1599b0c
XL
1605 | Self::Index(_)
1606 | Self::ConstantIndex { .. }
1607 | Self::Subslice { .. }
dfeec247 1608 | Self::Downcast(_, _) => false,
e1599b0c
XL
1609 }
1610 }
1611}
1612
ff7c6d11 1613/// Alias for projections as they appear in places, where the base is a place
ea8adc8c 1614/// and the index is a local.
532ac7d7 1615pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
e9174d1e 1616
48663c56
XL
1617// At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
1618#[cfg(target_arch = "x86_64")]
1619static_assert_size!(PlaceElem<'_>, 16);
a1dfa0c6 1620
0bf4aa26
XL
1621/// Alias for projections as they appear in `UserTypeProjection`, where we
1622/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
532ac7d7 1623pub type ProjectionKind = ProjectionElem<(), ()>;
0bf4aa26 1624
e74abb32 1625rustc_index::newtype_index! {
b7449926 1626 pub struct Field {
532ac7d7 1627 derive [HashStable]
b7449926
XL
1628 DEBUG_FORMAT = "field[{}]"
1629 }
1630}
e9174d1e 1631
416331ca 1632#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
74b04a01
XL
1633pub struct PlaceRef<'tcx> {
1634 pub local: Local,
1635 pub projection: &'tcx [PlaceElem<'tcx>],
416331ca
XL
1636}
1637
ff7c6d11 1638impl<'tcx> Place<'tcx> {
e74abb32 1639 // FIXME change this to a const fn by also making List::empty a const fn.
e1599b0c 1640 pub fn return_place() -> Place<'tcx> {
dfeec247 1641 Place { local: RETURN_PLACE, projection: List::empty() }
e9174d1e 1642 }
0bf4aa26 1643
e1599b0c
XL
1644 /// Returns `true` if this `Place` contains a `Deref` projection.
1645 ///
1646 /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the
1647 /// same region of memory as its base.
1648 pub fn is_indirect(&self) -> bool {
1649 self.projection.iter().any(|elem| elem.is_indirect())
1650 }
1651
9fa01778 1652 /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
0bf4aa26 1653 /// a single deref of a local.
9fa01778
XL
1654 //
1655 // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
dc9dc135 1656 pub fn local_or_deref_local(&self) -> Option<Local> {
e74abb32 1657 match self.as_ref() {
74b04a01
XL
1658 PlaceRef { local, projection: [] }
1659 | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local),
0bf4aa26
XL
1660 _ => None,
1661 }
1662 }
1663
e1599b0c
XL
1664 /// If this place represents a local variable like `_X` with no
1665 /// projections, return `Some(_X)`.
1666 pub fn as_local(&self) -> Option<Local> {
e74abb32 1667 self.as_ref().as_local()
416331ca
XL
1668 }
1669
74b04a01
XL
1670 pub fn as_ref(&self) -> PlaceRef<'tcx> {
1671 PlaceRef { local: self.local, projection: &self.projection }
0bf4aa26 1672 }
e9174d1e
SL
1673}
1674
dc9dc135
XL
1675impl From<Local> for Place<'_> {
1676 fn from(local: Local) -> Self {
dfeec247 1677 Place { local, projection: List::empty() }
dc9dc135
XL
1678 }
1679}
1680
74b04a01 1681impl<'tcx> PlaceRef<'tcx> {
416331ca
XL
1682 /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
1683 /// a single deref of a local.
1684 //
1685 // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
1686 pub fn local_or_deref_local(&self) -> Option<Local> {
74b04a01 1687 match *self {
dfeec247 1688 PlaceRef { local, projection: [] }
74b04a01 1689 | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local),
416331ca
XL
1690 _ => None,
1691 }
1692 }
e74abb32
XL
1693
1694 /// If this place represents a local variable like `_X` with no
1695 /// projections, return `Some(_X)`.
1696 pub fn as_local(&self) -> Option<Local> {
74b04a01
XL
1697 match *self {
1698 PlaceRef { local, projection: [] } => Some(local),
e74abb32
XL
1699 _ => None,
1700 }
1701 }
416331ca
XL
1702}
1703
e1599b0c 1704impl Debug for Place<'_> {
0bf4aa26 1705 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
e1599b0c
XL
1706 for elem in self.projection.iter().rev() {
1707 match elem {
1708 ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
1709 write!(fmt, "(").unwrap();
1710 }
1711 ProjectionElem::Deref => {
1712 write!(fmt, "(*").unwrap();
94b46f34 1713 }
e1599b0c
XL
1714 ProjectionElem::Index(_)
1715 | ProjectionElem::ConstantIndex { .. }
1716 | ProjectionElem::Subslice { .. } => {}
48663c56 1717 }
e1599b0c 1718 }
48663c56 1719
dfeec247 1720 write!(fmt, "{:?}", self.local)?;
48663c56 1721
e1599b0c
XL
1722 for elem in self.projection.iter() {
1723 match elem {
1724 ProjectionElem::Downcast(Some(name), _index) => {
1725 write!(fmt, " as {})", name)?;
1726 }
1727 ProjectionElem::Downcast(None, index) => {
1728 write!(fmt, " as variant#{:?})", index)?;
1729 }
1730 ProjectionElem::Deref => {
1731 write!(fmt, ")")?;
1732 }
1733 ProjectionElem::Field(field, ty) => {
1734 write!(fmt, ".{:?}: {:?})", field.index(), ty)?;
1735 }
1736 ProjectionElem::Index(ref index) => {
1737 write!(fmt, "[{:?}]", index)?;
1738 }
1739 ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => {
1740 write!(fmt, "[{:?} of {:?}]", offset, min_length)?;
1741 }
1742 ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
1743 write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
1744 }
f9f354fc 1745 ProjectionElem::Subslice { from, to, from_end: true } if to == 0 => {
e1599b0c
XL
1746 write!(fmt, "[{:?}:]", from)?;
1747 }
f9f354fc 1748 ProjectionElem::Subslice { from, to, from_end: true } if from == 0 => {
e1599b0c
XL
1749 write!(fmt, "[:-{:?}]", to)?;
1750 }
60c5eb7d 1751 ProjectionElem::Subslice { from, to, from_end: true } => {
e1599b0c 1752 write!(fmt, "[{:?}:-{:?}]", from, to)?;
94b46f34 1753 }
60c5eb7d
XL
1754 ProjectionElem::Subslice { from, to, from_end: false } => {
1755 write!(fmt, "[{:?}..{:?}]", from, to)?;
1756 }
48663c56 1757 }
e1599b0c 1758 }
48663c56 1759
e1599b0c 1760 Ok(())
e9174d1e
SL
1761 }
1762}
1763
54a0048b
SL
1764///////////////////////////////////////////////////////////////////////////
1765// Scopes
1766
e74abb32 1767rustc_index::newtype_index! {
b7449926 1768 pub struct SourceScope {
532ac7d7 1769 derive [HashStable]
abe05a73 1770 DEBUG_FORMAT = "scope[{}]",
94b46f34 1771 const OUTERMOST_SOURCE_SCOPE = 0,
b7449926
XL
1772 }
1773}
54a0048b 1774
3dfed10e 1775#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
94b46f34 1776pub struct SourceScopeData {
a7813a04 1777 pub span: Span,
94b46f34 1778 pub parent_scope: Option<SourceScope>,
60c5eb7d
XL
1779
1780 /// Crate-local information for this source scope, that can't (and
1781 /// needn't) be tracked across crates.
1782 pub local_data: ClearCrossCrate<SourceScopeLocalData>,
94b46f34
XL
1783}
1784
3dfed10e 1785#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
94b46f34 1786pub struct SourceScopeLocalData {
e1599b0c 1787 /// An `HirId` with lint levels equivalent to this scope's lint levels.
532ac7d7 1788 pub lint_root: hir::HirId,
94b46f34
XL
1789 /// The unsafe block that contains this node.
1790 pub safety: Safety,
54a0048b
SL
1791}
1792
e9174d1e
SL
1793///////////////////////////////////////////////////////////////////////////
1794// Operands
54a0048b 1795
0bf4aa26
XL
1796/// These are values that can appear inside an rvalue. They are intentionally
1797/// limited to prevent rvalues from being nested in one another.
3dfed10e 1798#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
b039eaaf 1799pub enum Operand<'tcx> {
ff7c6d11
XL
1800 /// Copy: The value must be available for use afterwards.
1801 ///
1802 /// This implies that the type of the place must be `Copy`; this is true
1803 /// by construction during build, but also checked by the MIR type checker.
1804 Copy(Place<'tcx>),
b7449926 1805
ff7c6d11
XL
1806 /// Move: The value (including old borrows of it) will not be used again.
1807 ///
1808 /// Safe for values of all types (modulo future developments towards `?Move`).
1809 /// Correct usage patterns are enforced by the borrow checker for safe code.
1810 /// `Copy` may be converted to `Move` to enable "last-use" optimizations.
1811 Move(Place<'tcx>),
b7449926
XL
1812
1813 /// Synthesizes a constant value.
cc61c64b 1814 Constant(Box<Constant<'tcx>>),
e9174d1e
SL
1815}
1816
b039eaaf 1817impl<'tcx> Debug for Operand<'tcx> {
0bf4aa26 1818 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
e9174d1e
SL
1819 use self::Operand::*;
1820 match *self {
1821 Constant(ref a) => write!(fmt, "{:?}", a),
ff7c6d11
XL
1822 Copy(ref place) => write!(fmt, "{:?}", place),
1823 Move(ref place) => write!(fmt, "move {:?}", place),
e9174d1e
SL
1824 }
1825 }
1826}
1827
cc61c64b 1828impl<'tcx> Operand<'tcx> {
b7449926 1829 /// Convenience helper to make a constant that refers to the fn
9fa01778 1830 /// with given `DefId` and substs. Since this is used to synthesize
b7449926 1831 /// MIR, assumes `user_ty` is None.
dc9dc135
XL
1832 pub fn function_handle(
1833 tcx: TyCtxt<'tcx>,
cc61c64b 1834 def_id: DefId,
532ac7d7 1835 substs: SubstsRef<'tcx>,
cc61c64b
XL
1836 span: Span,
1837 ) -> Self {
ea8adc8c 1838 let ty = tcx.type_of(def_id).subst(tcx, substs);
cc61c64b 1839 Operand::Constant(box Constant {
041b39d2 1840 span,
b7449926 1841 user_ty: None,
dc9dc135 1842 literal: ty::Const::zero_sized(tcx, ty),
cc61c64b
XL
1843 })
1844 }
1845
f035d41b
XL
1846 /// Convenience helper to make a literal-like constant from a given scalar value.
1847 /// Since this is used to synthesize MIR, assumes `user_ty` is None.
1848 pub fn const_from_scalar(
1849 tcx: TyCtxt<'tcx>,
1850 ty: Ty<'tcx>,
1851 val: Scalar,
1852 span: Span,
1853 ) -> Operand<'tcx> {
1854 debug_assert!({
1855 let param_env_and_ty = ty::ParamEnv::empty().and(ty);
1856 let type_size = tcx
1857 .layout_of(param_env_and_ty)
1858 .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
1859 .size;
1860 let scalar_size = abi::Size::from_bytes(match val {
1861 Scalar::Raw { size, .. } => size,
1862 _ => panic!("Invalid scalar type {:?}", val),
1863 });
1864 scalar_size == type_size
1865 });
1866 Operand::Constant(box Constant {
1867 span,
1868 user_ty: None,
1869 literal: ty::Const::from_scalar(tcx, val, ty),
1870 })
1871 }
1872
1873 /// Convenience helper to make a `Scalar` from the given `Operand`, assuming that `Operand`
1874 /// wraps a constant literal value. Panics if this is not the case.
1875 pub fn scalar_from_const(operand: &Operand<'tcx>) -> Scalar {
1876 match operand {
1877 Operand::Constant(constant) => match constant.literal.val.try_to_scalar() {
1878 Some(scalar) => scalar,
1879 _ => panic!("{:?}: Scalar value expected", constant.literal.val),
1880 },
1881 _ => panic!("{:?}: Constant expected", operand),
1882 }
1883 }
1884
3dfed10e
XL
1885 /// Convenience helper to make a literal-like constant from a given `&str` slice.
1886 /// Since this is used to synthesize MIR, assumes `user_ty` is None.
1887 pub fn const_from_str(tcx: TyCtxt<'tcx>, val: &str, span: Span) -> Operand<'tcx> {
1888 let tcx = tcx;
1889 let allocation = Allocation::from_byte_aligned_bytes(val.as_bytes());
1890 let allocation = tcx.intern_const_alloc(allocation);
1891 let const_val = ConstValue::Slice { data: allocation, start: 0, end: val.len() };
1892 let ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.types.str_);
1893 Operand::Constant(box Constant {
1894 span,
1895 user_ty: None,
1896 literal: ty::Const::from_value(tcx, const_val, ty),
1897 })
1898 }
1899
1900 /// Convenience helper to make a `ConstValue` from the given `Operand`, assuming that `Operand`
1901 /// wraps a constant value (such as a `&str` slice). Panics if this is not the case.
1902 pub fn value_from_const(operand: &Operand<'tcx>) -> ConstValue<'tcx> {
1903 match operand {
1904 Operand::Constant(constant) => match constant.literal.val.try_to_value() {
1905 Some(const_value) => const_value,
1906 _ => panic!("{:?}: ConstValue expected", constant.literal.val),
1907 },
1908 _ => panic!("{:?}: Constant expected", operand),
1909 }
1910 }
1911
ff7c6d11
XL
1912 pub fn to_copy(&self) -> Self {
1913 match *self {
1914 Operand::Copy(_) | Operand::Constant(_) => self.clone(),
dfeec247 1915 Operand::Move(place) => Operand::Copy(place),
ff7c6d11
XL
1916 }
1917 }
74b04a01
XL
1918
1919 /// Returns the `Place` that is the target of this `Operand`, or `None` if this `Operand` is a
1920 /// constant.
ba9703b0 1921 pub fn place(&self) -> Option<Place<'tcx>> {
74b04a01 1922 match self {
ba9703b0 1923 Operand::Copy(place) | Operand::Move(place) => Some(*place),
74b04a01
XL
1924 Operand::Constant(_) => None,
1925 }
1926 }
cc61c64b
XL
1927}
1928
e9174d1e 1929///////////////////////////////////////////////////////////////////////////
7453a54e 1930/// Rvalues
e9174d1e 1931
3dfed10e 1932#[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)]
b039eaaf 1933pub enum Rvalue<'tcx> {
7453a54e 1934 /// x (either a move or copy, depending on type of x)
b039eaaf 1935 Use(Operand<'tcx>),
e9174d1e 1936
7453a54e 1937 /// [x; 32]
ba9703b0 1938 Repeat(Operand<'tcx>, &'tcx ty::Const<'tcx>),
e9174d1e 1939
7453a54e 1940 /// &x or &mut x
ff7c6d11 1941 Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
e9174d1e 1942
f9f354fc
XL
1943 /// Accessing a thread local static. This is inherently a runtime operation, even if llvm
1944 /// treats it as an access to a static. This `Rvalue` yields a reference to the thread local
1945 /// static.
1946 ThreadLocalRef(DefId),
1947
dfeec247
XL
1948 /// Create a raw pointer to the given place
1949 /// Can be generated by raw address of expressions (`&raw const x`),
1950 /// or when casting a reference to a raw pointer.
1951 AddressOf(Mutability, Place<'tcx>),
1952
f9f354fc 1953 /// length of a `[X]` or `[X;n]` value
ff7c6d11 1954 Len(Place<'tcx>),
e9174d1e 1955
b039eaaf 1956 Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
e9174d1e 1957
b039eaaf 1958 BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
3157f602 1959 CheckedBinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
e9174d1e 1960
7cac9316 1961 NullaryOp(NullOp, Ty<'tcx>),
b039eaaf 1962 UnaryOp(UnOp, Operand<'tcx>),
e9174d1e 1963
8bb4bdeb
XL
1964 /// Read the discriminant of an ADT.
1965 ///
0731742a 1966 /// Undefined (i.e., no effort is made to make it defined, but there’s no reason why it cannot
8bb4bdeb 1967 /// be defined to return, say, a 0) if ADT is not an enum.
ff7c6d11 1968 Discriminant(Place<'tcx>),
8bb4bdeb 1969
9fa01778 1970 /// Creates an aggregate value, like a tuple or struct. This is
7453a54e
SL
1971 /// only needed because we want to distinguish `dest = Foo { x:
1972 /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
1973 /// that `Foo` has a destructor. These rvalues can be optimized
1974 /// away after type-checking and before lowering.
cc61c64b 1975 Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
e9174d1e
SL
1976}
1977
3dfed10e 1978#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
e9174d1e
SL
1979pub enum CastKind {
1980 Misc,
48663c56 1981 Pointer(PointerCast),
e9174d1e
SL
1982}
1983
3dfed10e 1984#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
b039eaaf 1985pub enum AggregateKind<'tcx> {
8bb4bdeb
XL
1986 /// The type is of the element
1987 Array(Ty<'tcx>),
e9174d1e 1988 Tuple,
ff7c6d11 1989
2c00a5a8
XL
1990 /// The second field is the variant index. It's equal to 0 for struct
1991 /// and union expressions. The fourth field is
ff7c6d11 1992 /// active field number and is present only for union expressions
0731742a 1993 /// -- e.g., for a union expression `SomeUnion { c: .. }`, the
ff7c6d11 1994 /// active field index would identity the field `c`
416331ca 1995 Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
ff7c6d11 1996
e74abb32 1997 Closure(DefId, SubstsRef<'tcx>),
60c5eb7d 1998 Generator(DefId, SubstsRef<'tcx>, hir::Movability),
e9174d1e
SL
1999}
2000
3dfed10e 2001#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
e9174d1e
SL
2002pub enum BinOp {
2003 /// The `+` operator (addition)
2004 Add,
2005 /// The `-` operator (subtraction)
2006 Sub,
2007 /// The `*` operator (multiplication)
2008 Mul,
2009 /// The `/` operator (division)
2010 Div,
2011 /// The `%` operator (modulus)
2012 Rem,
2013 /// The `^` operator (bitwise xor)
2014 BitXor,
2015 /// The `&` operator (bitwise and)
2016 BitAnd,
2017 /// The `|` operator (bitwise or)
2018 BitOr,
2019 /// The `<<` operator (shift left)
2020 Shl,
2021 /// The `>>` operator (shift right)
2022 Shr,
2023 /// The `==` operator (equality)
2024 Eq,
2025 /// The `<` operator (less than)
2026 Lt,
2027 /// The `<=` operator (less than or equal to)
2028 Le,
2029 /// The `!=` operator (not equal to)
2030 Ne,
2031 /// The `>=` operator (greater than or equal to)
2032 Ge,
2033 /// The `>` operator (greater than)
2034 Gt,
7cac9316
XL
2035 /// The `ptr.offset` operator
2036 Offset,
e9174d1e
SL
2037}
2038
3157f602
XL
2039impl BinOp {
2040 pub fn is_checkable(self) -> bool {
2041 use self::BinOp::*;
2042 match self {
2043 Add | Sub | Mul | Shl | Shr => true,
94b46f34 2044 _ => false,
3157f602
XL
2045 }
2046 }
2047}
2048
3dfed10e 2049#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
7cac9316 2050pub enum NullOp {
9fa01778 2051 /// Returns the size of a value of that type
7cac9316 2052 SizeOf,
9fa01778 2053 /// Creates a new uninitialized box for a value of that type
7cac9316
XL
2054 Box,
2055}
2056
3dfed10e 2057#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
e9174d1e
SL
2058pub enum UnOp {
2059 /// The `!` operator for logical inversion
2060 Not,
2061 /// The `-` operator for negation
b039eaaf 2062 Neg,
e9174d1e
SL
2063}
2064
b039eaaf 2065impl<'tcx> Debug for Rvalue<'tcx> {
0bf4aa26 2066 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
e9174d1e
SL
2067 use self::Rvalue::*;
2068
2069 match *self {
ff7c6d11 2070 Use(ref place) => write!(fmt, "{:?}", place),
ba9703b0
XL
2071 Repeat(ref a, ref b) => {
2072 write!(fmt, "[{:?}; ", a)?;
2073 pretty_print_const(b, fmt, false)?;
2074 write!(fmt, "]")
2075 }
9cc50fc6 2076 Len(ref a) => write!(fmt, "Len({:?})", a),
ff7c6d11
XL
2077 Cast(ref kind, ref place, ref ty) => {
2078 write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind)
2079 }
9cc50fc6 2080 BinaryOp(ref op, ref a, ref b) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
3157f602
XL
2081 CheckedBinaryOp(ref op, ref a, ref b) => {
2082 write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
2083 }
e9174d1e 2084 UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
ff7c6d11 2085 Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
7cac9316 2086 NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
f9f354fc
XL
2087 ThreadLocalRef(did) => ty::tls::with(|tcx| {
2088 let muta = tcx.static_mutability(did).unwrap().prefix_str();
2089 write!(fmt, "&/*tls*/ {}{}", muta, tcx.def_path_str(did))
2090 }),
ff7c6d11 2091 Ref(region, borrow_kind, ref place) => {
9cc50fc6
SL
2092 let kind_str = match borrow_kind {
2093 BorrowKind::Shared => "",
0bf4aa26 2094 BorrowKind::Shallow => "shallow ",
2c00a5a8 2095 BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
9cc50fc6 2096 };
041b39d2 2097
3b2f2976 2098 // When printing regions, add trailing space if necessary.
532ac7d7
XL
2099 let print_region = ty::tls::with(|tcx| {
2100 tcx.sess.verbose() || tcx.sess.opts.debugging_opts.identify_regions
2101 });
2102 let region = if print_region {
8faf50e0 2103 let mut region = region.to_string();
74b04a01 2104 if !region.is_empty() {
94b46f34
XL
2105 region.push(' ');
2106 }
041b39d2
XL
2107 region
2108 } else {
3b2f2976 2109 // Do not even print 'static
b7449926 2110 String::new()
041b39d2 2111 };
ff7c6d11 2112 write!(fmt, "&{}{}{:?}", region, kind_str, place)
9cc50fc6
SL
2113 }
2114
dfeec247
XL
2115 AddressOf(mutability, ref place) => {
2116 let kind_str = match mutability {
2117 Mutability::Mut => "mut",
2118 Mutability::Not => "const",
2119 };
2120
2121 write!(fmt, "&raw {} {:?}", kind_str, place)
2122 }
2123
ff7c6d11 2124 Aggregate(ref kind, ref places) => {
ba9703b0
XL
2125 let fmt_tuple = |fmt: &mut Formatter<'_>, name: &str| {
2126 let mut tuple_fmt = fmt.debug_tuple(name);
ff7c6d11
XL
2127 for place in places {
2128 tuple_fmt.field(place);
9cc50fc6
SL
2129 }
2130 tuple_fmt.finish()
ba9703b0 2131 };
9cc50fc6 2132
cc61c64b 2133 match **kind {
ff7c6d11 2134 AggregateKind::Array(_) => write!(fmt, "{:?}", places),
9cc50fc6 2135
ba9703b0
XL
2136 AggregateKind::Tuple => {
2137 if places.is_empty() {
2138 write!(fmt, "()")
2139 } else {
2140 fmt_tuple(fmt, "")
2141 }
2142 }
9cc50fc6 2143
b7449926 2144 AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => {
9cc50fc6 2145 let variant_def = &adt_def.variants[variant];
54a0048b 2146
ba9703b0
XL
2147 let name = ty::tls::with(|tcx| {
2148 let mut name = String::new();
532ac7d7 2149 let substs = tcx.lift(&substs).expect("could not lift for printing");
ba9703b0 2150 FmtPrinter::new(tcx, &mut name, Namespace::ValueNS)
532ac7d7 2151 .print_def_path(variant_def.def_id, substs)?;
ba9703b0 2152 Ok(name)
532ac7d7 2153 })?;
9cc50fc6 2154
c30ab7b3 2155 match variant_def.ctor_kind {
ba9703b0
XL
2156 CtorKind::Const => fmt.write_str(&name),
2157 CtorKind::Fn => fmt_tuple(fmt, &name),
c30ab7b3 2158 CtorKind::Fictive => {
ba9703b0 2159 let mut struct_fmt = fmt.debug_struct(&name);
ff7c6d11 2160 for (field, place) in variant_def.fields.iter().zip(places) {
94b46f34 2161 struct_fmt.field(&field.ident.as_str(), place);
9cc50fc6
SL
2162 }
2163 struct_fmt.finish()
2164 }
2165 }
2166 }
2167
60c5eb7d 2168 AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
f9f354fc 2169 if let Some(def_id) = def_id.as_local() {
3dfed10e 2170 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
041b39d2 2171 let name = if tcx.sess.opts.debugging_opts.span_free_formats {
60c5eb7d
XL
2172 let substs = tcx.lift(&substs).unwrap();
2173 format!(
2174 "[closure@{}]",
f9f354fc 2175 tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
60c5eb7d 2176 )
041b39d2 2177 } else {
f035d41b
XL
2178 let span = tcx.hir().span(hir_id);
2179 format!("[closure@{}]", tcx.sess.source_map().span_to_string(span))
041b39d2 2180 };
9cc50fc6
SL
2181 let mut struct_fmt = fmt.debug_struct(&name);
2182
f9f354fc 2183 if let Some(upvars) = tcx.upvars_mentioned(def_id) {
dc9dc135
XL
2184 for (&var_id, place) in upvars.keys().zip(places) {
2185 let var_name = tcx.hir().name(var_id);
ff7c6d11 2186 struct_fmt.field(&var_name.as_str(), place);
9cc50fc6 2187 }
48663c56 2188 }
9cc50fc6
SL
2189
2190 struct_fmt.finish()
2191 } else {
2192 write!(fmt, "[closure]")
2193 }
2194 }),
ea8adc8c
XL
2195
2196 AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
f9f354fc 2197 if let Some(def_id) = def_id.as_local() {
3dfed10e 2198 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
416331ca 2199 let name = format!("[generator@{:?}]", tcx.hir().span(hir_id));
ea8adc8c
XL
2200 let mut struct_fmt = fmt.debug_struct(&name);
2201
f9f354fc 2202 if let Some(upvars) = tcx.upvars_mentioned(def_id) {
dc9dc135
XL
2203 for (&var_id, place) in upvars.keys().zip(places) {
2204 let var_name = tcx.hir().name(var_id);
ff7c6d11 2205 struct_fmt.field(&var_name.as_str(), place);
ea8adc8c 2206 }
48663c56 2207 }
ea8adc8c
XL
2208
2209 struct_fmt.finish()
2210 } else {
2211 write!(fmt, "[generator]")
2212 }
2213 }),
9cc50fc6
SL
2214 }
2215 }
e9174d1e
SL
2216 }
2217 }
2218}
2219
2220///////////////////////////////////////////////////////////////////////////
7453a54e
SL
2221/// Constants
2222///
2223/// Two constants are equal if they are the same constant. Note that
2224/// this does not necessarily mean that they are "==" in Rust -- in
2225/// particular one must be wary of `NaN`!
e9174d1e 2226
3dfed10e 2227#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, HashStable)]
b039eaaf
SL
2228pub struct Constant<'tcx> {
2229 pub span: Span,
b7449926
XL
2230
2231 /// Optional user-given type: for something like
2232 /// `collect::<Vec<_>>`, this would be present and would
2233 /// indicate that `Vec<_>` was explicitly specified.
2234 ///
2235 /// Needed for NLL to impose user-given type constraints.
0731742a 2236 pub user_ty: Option<UserTypeAnnotationIndex>,
b7449926 2237
532ac7d7 2238 pub literal: &'tcx ty::Const<'tcx>,
0bf4aa26
XL
2239}
2240
60c5eb7d
XL
2241impl Constant<'tcx> {
2242 pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
2243 match self.literal.val.try_to_scalar() {
f9f354fc
XL
2244 Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) {
2245 GlobalAlloc::Static(def_id) => {
2246 assert!(!tcx.is_thread_local_static(def_id));
2247 Some(def_id)
dfeec247 2248 }
f9f354fc 2249 _ => None,
60c5eb7d
XL
2250 },
2251 _ => None,
2252 }
2253 }
2254}
2255
0bf4aa26
XL
2256/// A collection of projections into user types.
2257///
2258/// They are projections because a binding can occur a part of a
2259/// parent pattern that has been ascribed a type.
2260///
2261/// Its a collection because there can be multiple type ascriptions on
2262/// the path from the root of the pattern down to the binding itself.
2263///
2264/// An example:
2265///
2266/// ```rust
2267/// struct S<'a>((i32, &'a str), String);
2268/// let S((_, w): (i32, &'static str), _): S = ...;
2269/// // ------ ^^^^^^^^^^^^^^^^^^^ (1)
2270/// // --------------------------------- ^ (2)
2271/// ```
2272///
2273/// The highlights labelled `(1)` show the subpattern `(_, w)` being
2274/// ascribed the type `(i32, &'static str)`.
2275///
2276/// The highlights labelled `(2)` show the whole pattern being
2277/// ascribed the type `S`.
2278///
2279/// In this example, when we descend to `w`, we will have built up the
2280/// following two projected types:
2281///
2282/// * base: `S`, projection: `(base.0).1`
2283/// * base: `(i32, &'static str)`, projection: `base.1`
2284///
2285/// The first will lead to the constraint `w: &'1 str` (for some
2286/// inferred region `'1`). The second will lead to the constraint `w:
2287/// &'static str`.
3dfed10e 2288#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
532ac7d7 2289pub struct UserTypeProjections {
f9f354fc 2290 pub contents: Vec<(UserTypeProjection, Span)>,
0bf4aa26
XL
2291}
2292
532ac7d7 2293impl<'tcx> UserTypeProjections {
0bf4aa26
XL
2294 pub fn none() -> Self {
2295 UserTypeProjections { contents: vec![] }
2296 }
2297
f9f354fc
XL
2298 pub fn is_empty(&self) -> bool {
2299 self.contents.is_empty()
2300 }
2301
416331ca 2302 pub fn from_projections(projs: impl Iterator<Item = (UserTypeProjection, Span)>) -> Self {
0bf4aa26
XL
2303 UserTypeProjections { contents: projs.collect() }
2304 }
2305
dfeec247
XL
2306 pub fn projections_and_spans(
2307 &self,
2308 ) -> impl Iterator<Item = &(UserTypeProjection, Span)> + ExactSizeIterator {
0bf4aa26
XL
2309 self.contents.iter()
2310 }
2311
dfeec247 2312 pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator {
0bf4aa26
XL
2313 self.contents.iter().map(|&(ref user_type, _span)| user_type)
2314 }
0731742a 2315
416331ca 2316 pub fn push_projection(mut self, user_ty: &UserTypeProjection, span: Span) -> Self {
0731742a
XL
2317 self.contents.push((user_ty.clone(), span));
2318 self
2319 }
2320
2321 fn map_projections(
2322 mut self,
416331ca 2323 mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
0731742a
XL
2324 ) -> Self {
2325 self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
2326 self
2327 }
2328
2329 pub fn index(self) -> Self {
2330 self.map_projections(|pat_ty_proj| pat_ty_proj.index())
2331 }
2332
2333 pub fn subslice(self, from: u32, to: u32) -> Self {
2334 self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
2335 }
2336
2337 pub fn deref(self) -> Self {
2338 self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
2339 }
2340
2341 pub fn leaf(self, field: Field) -> Self {
2342 self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
2343 }
2344
416331ca 2345 pub fn variant(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx, field: Field) -> Self {
0731742a
XL
2346 self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
2347 }
0bf4aa26
XL
2348}
2349
2350/// Encodes the effect of a user-supplied type annotation on the
2351/// subcomponents of a pattern. The effect is determined by applying the
2352/// given list of proejctions to some underlying base type. Often,
2353/// the projection element list `projs` is empty, in which case this
2354/// directly encodes a type in `base`. But in the case of complex patterns with
2355/// subpatterns and bindings, we want to apply only a *part* of the type to a variable,
2356/// in which case the `projs` vector is used.
2357///
2358/// Examples:
2359///
2360/// * `let x: T = ...` -- here, the `projs` vector is empty.
2361///
2362/// * `let (x, _): T = ...` -- here, the `projs` vector would contain
2363/// `field[0]` (aka `.0`), indicating that the type of `s` is
2364/// determined by finding the type of the `.0` field from `T`.
3dfed10e 2365#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, PartialEq)]
532ac7d7 2366pub struct UserTypeProjection {
0731742a 2367 pub base: UserTypeAnnotationIndex,
dc9dc135 2368 pub projs: Vec<ProjectionKind>,
0bf4aa26
XL
2369}
2370
416331ca 2371impl Copy for ProjectionKind {}
0bf4aa26 2372
532ac7d7 2373impl UserTypeProjection {
0731742a
XL
2374 pub(crate) fn index(mut self) -> Self {
2375 self.projs.push(ProjectionElem::Index(()));
2376 self
2377 }
2378
2379 pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
60c5eb7d 2380 self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
0731742a
XL
2381 self
2382 }
2383
2384 pub(crate) fn deref(mut self) -> Self {
2385 self.projs.push(ProjectionElem::Deref);
2386 self
2387 }
2388
2389 pub(crate) fn leaf(mut self, field: Field) -> Self {
2390 self.projs.push(ProjectionElem::Field(field, ()));
2391 self
2392 }
2393
2394 pub(crate) fn variant(
2395 mut self,
ba9703b0 2396 adt_def: &AdtDef,
0731742a
XL
2397 variant_index: VariantIdx,
2398 field: Field,
2399 ) -> Self {
532ac7d7
XL
2400 self.projs.push(ProjectionElem::Downcast(
2401 Some(adt_def.variants[variant_index].ident.name),
416331ca
XL
2402 variant_index,
2403 ));
0731742a
XL
2404 self.projs.push(ProjectionElem::Field(field, ()));
2405 self
2406 }
2407}
2408
532ac7d7 2409CloneTypeFoldableAndLiftImpls! { ProjectionKind, }
0bf4aa26 2410
532ac7d7 2411impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
dc9dc135 2412 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
9fa01778 2413 use crate::mir::ProjectionElem::*;
0bf4aa26
XL
2414
2415 let base = self.base.fold_with(folder);
416331ca
XL
2416 let projs: Vec<_> = self
2417 .projs
0bf4aa26 2418 .iter()
dfeec247 2419 .map(|&elem| match elem {
416331ca 2420 Deref => Deref,
dfeec247 2421 Field(f, ()) => Field(f, ()),
416331ca 2422 Index(()) => Index(()),
dfeec247
XL
2423 Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
2424 ConstantIndex { offset, min_length, from_end } => {
2425 ConstantIndex { offset, min_length, from_end }
2426 }
2427 Subslice { from, to, from_end } => Subslice { from, to, from_end },
416331ca 2428 })
0bf4aa26
XL
2429 .collect();
2430
2431 UserTypeProjection { base, projs }
2432 }
2433
2434 fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
2435 self.base.visit_with(visitor)
2436 // Note: there's nothing in `self.proj` to visit.
2437 }
2438}
2439
e74abb32 2440rustc_index::newtype_index! {
b7449926 2441 pub struct Promoted {
532ac7d7 2442 derive [HashStable]
b7449926
XL
2443 DEBUG_FORMAT = "promoted[{}]"
2444 }
2445}
abe05a73 2446
9cc50fc6 2447impl<'tcx> Debug for Constant<'tcx> {
0bf4aa26 2448 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
dc9dc135 2449 write!(fmt, "{}", self)
9cc50fc6
SL
2450 }
2451}
2452
dc9dc135
XL
2453impl<'tcx> Display for Constant<'tcx> {
2454 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
3dfed10e
XL
2455 match self.literal.ty.kind {
2456 ty::FnDef(..) => {}
2457 _ => write!(fmt, "const ")?,
2458 }
ba9703b0 2459 pretty_print_const(self.literal, fmt, true)
dc9dc135 2460 }
9cc50fc6 2461}
3157f602 2462
ba9703b0
XL
2463fn pretty_print_const(
2464 c: &ty::Const<'tcx>,
2465 fmt: &mut Formatter<'_>,
2466 print_types: bool,
2467) -> fmt::Result {
2468 use crate::ty::print::PrettyPrinter;
2469 ty::tls::with(|tcx| {
2470 let literal = tcx.lift(&c).unwrap();
2471 let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
2472 cx.print_alloc_ids = true;
2473 cx.pretty_print_const(literal, print_types)?;
2474 Ok(())
2475 })
2476}
2477
dc9dc135 2478impl<'tcx> graph::DirectedGraph for Body<'tcx> {
3157f602 2479 type Node = BasicBlock;
8faf50e0 2480}
3157f602 2481
dc9dc135 2482impl<'tcx> graph::WithNumNodes for Body<'tcx> {
f9f354fc 2483 #[inline]
94b46f34
XL
2484 fn num_nodes(&self) -> usize {
2485 self.basic_blocks.len()
2486 }
8faf50e0 2487}
3157f602 2488
dc9dc135 2489impl<'tcx> graph::WithStartNode for Body<'tcx> {
f9f354fc 2490 #[inline]
94b46f34
XL
2491 fn start_node(&self) -> Self::Node {
2492 START_BLOCK
2493 }
8faf50e0 2494}
3157f602 2495
dc9dc135 2496impl<'tcx> graph::WithSuccessors for Body<'tcx> {
f9f354fc 2497 #[inline]
dfeec247 2498 fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter {
83c7162d 2499 self.basic_blocks[node].terminator().successors().cloned()
3157f602
XL
2500 }
2501}
2502
dc9dc135 2503impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
3157f602 2504 type Item = BasicBlock;
83c7162d 2505 type Iter = iter::Cloned<Successors<'b>>;
3157f602 2506}
9e0c209e 2507
f9f354fc
XL
2508impl graph::GraphPredecessors<'graph> for Body<'tcx> {
2509 type Item = BasicBlock;
2510 type Iter = smallvec::IntoIter<[BasicBlock; 4]>;
2511}
2512
2513impl graph::WithPredecessors for Body<'tcx> {
2514 #[inline]
2515 fn predecessors(&self, node: Self::Node) -> <Self as graph::GraphPredecessors<'_>>::Iter {
2516 self.predecessors()[node].clone().into_iter()
2517 }
2518}
2519
ba9703b0
XL
2520/// `Location` represents the position of the start of the statement; or, if
2521/// `statement_index` equals the number of statements, then the start of the
2522/// terminator.
532ac7d7 2523#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
9e0c209e 2524pub struct Location {
e1599b0c 2525 /// The block that the location is within.
9e0c209e
SL
2526 pub block: BasicBlock,
2527
9e0c209e
SL
2528 pub statement_index: usize,
2529}
2530
2531impl fmt::Debug for Location {
0bf4aa26 2532 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
9e0c209e
SL
2533 write!(fmt, "{:?}[{}]", self.block, self.statement_index)
2534 }
2535}
2536
2537impl Location {
416331ca 2538 pub const START: Location = Location { block: START_BLOCK, statement_index: 0 };
83c7162d 2539
abe05a73
XL
2540 /// Returns the location immediately after this one within the enclosing block.
2541 ///
2542 /// Note that if this location represents a terminator, then the
2543 /// resulting location would be out of bounds and invalid.
2544 pub fn successor_within_block(&self) -> Location {
416331ca 2545 Location { block: self.block, statement_index: self.statement_index + 1 }
abe05a73
XL
2546 }
2547
a1dfa0c6 2548 /// Returns `true` if `other` is earlier in the control flow graph than `self`.
f9f354fc 2549 pub fn is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool {
a1dfa0c6
XL
2550 // If we are in the same block as the other location and are an earlier statement
2551 // then we are a predecessor of `other`.
2552 if self.block == other.block && self.statement_index < other.statement_index {
2553 return true;
2554 }
2555
f9f354fc
XL
2556 let predecessors = body.predecessors();
2557
a1dfa0c6 2558 // If we're in another block, then we want to check that block is a predecessor of `other`.
f9f354fc 2559 let mut queue: Vec<BasicBlock> = predecessors[other.block].to_vec();
a1dfa0c6
XL
2560 let mut visited = FxHashSet::default();
2561
2562 while let Some(block) = queue.pop() {
2563 // If we haven't visited this block before, then make sure we visit it's predecessors.
2564 if visited.insert(block) {
f9f354fc 2565 queue.extend(predecessors[block].iter().cloned());
a1dfa0c6
XL
2566 } else {
2567 continue;
2568 }
2569
2570 // If we found the block that `self` is in, then we are a predecessor of `other` (since
2571 // we found that block by looking at the predecessors of `other`).
2572 if self.block == block {
2573 return true;
2574 }
2575 }
2576
2577 false
2578 }
2579
83c7162d 2580 pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
9e0c209e
SL
2581 if self.block == other.block {
2582 self.statement_index <= other.statement_index
2583 } else {
2584 dominators.is_dominated_by(other.block, self.block)
2585 }
2586 }
2587}