]> git.proxmox.com Git - rustc.git/blame - src/librustc/mir/mod.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / src / librustc / mir / mod.rs
CommitLineData
48663c56
XL
1// ignore-tidy-filelength
2
0531ce1d 3//! MIR datatypes and passes. See the [rustc guide] for more info.
ff7c6d11 4//!
a1dfa0c6 5//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
7cac9316 6
532ac7d7 7use crate::hir::def::{CtorKind, Namespace};
9fa01778 8use crate::hir::def_id::DefId;
48663c56 9use crate::hir::{self, InlineAsm as HirInlineAsm};
416331ca 10use crate::mir::interpret::{ConstValue, PanicInfo, Scalar};
9fa01778 11use crate::mir::visit::MirVisitable;
416331ca
XL
12use crate::ty::adjustment::PointerCast;
13use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
14use crate::ty::layout::VariantIdx;
15use crate::ty::print::{FmtPrinter, Printer};
16use crate::ty::subst::{Subst, SubstsRef};
17use crate::ty::{
18 self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
19 UserTypeAnnotationIndex,
20};
21use polonius_engine::Atom;
dc9dc135 22use rustc_data_structures::bit_set::BitMatrix;
a1dfa0c6 23use rustc_data_structures::fx::FxHashSet;
8faf50e0
XL
24use rustc_data_structures::graph::dominators::{dominators, Dominators};
25use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
94b46f34 26use rustc_data_structures::indexed_vec::{Idx, IndexVec};
94b46f34 27use rustc_data_structures::sync::Lrc;
b7449926 28use rustc_data_structures::sync::MappedReadGuard;
532ac7d7 29use rustc_macros::HashStable;
416331ca 30use rustc_serialize::{Encodable, Decodable};
b7449926 31use smallvec::SmallVec;
94b46f34 32use std::borrow::Cow;
416331ca 33use std::fmt::{self, Debug, Display, Formatter, Write};
48663c56 34use std::iter::FusedIterator;
9cc50fc6 35use std::ops::{Index, IndexMut};
94b46f34 36use std::slice;
3157f602 37use std::vec::IntoIter;
94b46f34 38use std::{iter, mem, option, u32};
dc9dc135 39use syntax::ast::Name;
532ac7d7 40use syntax::symbol::{InternedString, Symbol};
0531ce1d 41use syntax_pos::{Span, DUMMY_SP};
83c7162d 42
9fa01778 43pub use crate::mir::interpret::AssertMessage;
3157f602 44
c30ab7b3 45mod cache;
ff7c6d11
XL
46pub mod interpret;
47pub mod mono;
94b46f34
XL
48pub mod tcx;
49pub mod traversal;
50pub mod visit;
3157f602 51
041b39d2
XL
52/// Types for locals
53type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>;
54
55pub trait HasLocalDecls<'tcx> {
56 fn local_decls(&self) -> &LocalDecls<'tcx>;
57}
58
59impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
60 fn local_decls(&self) -> &LocalDecls<'tcx> {
61 self
62 }
63}
64
dc9dc135 65impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
041b39d2
XL
66 fn local_decls(&self) -> &LocalDecls<'tcx> {
67 &self.local_decls
68 }
69}
70
a1dfa0c6
XL
71/// The various "big phases" that MIR goes through.
72///
73/// Warning: ordering of variants is significant
74#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
75pub enum MirPhase {
76 Build = 0,
77 Const = 1,
78 Validated = 2,
79 Optimized = 3,
80}
81
82impl MirPhase {
83 /// Gets the index of the current MirPhase within the set of all MirPhases.
84 pub fn phase_index(&self) -> usize {
85 *self as usize
86 }
87}
88
e9174d1e 89/// Lowered representation of a single function.
8bb4bdeb 90#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
dc9dc135 91pub struct Body<'tcx> {
92a42be0
SL
92 /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
93 /// that indexes into this vector.
3157f602 94 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
e9174d1e 95
a1dfa0c6
XL
96 /// Records how far through the "desugaring and optimization" process this particular
97 /// MIR has traversed. This is particularly useful when inlining, since in that context
98 /// we instantiate the promoted constants and add them to our promoted vector -- but those
99 /// promoted items have already been optimized, whereas ours have not. This field allows
100 /// us to see the difference and forego optimization on the inlined promoted items.
101 pub phase: MirPhase,
102
94b46f34
XL
103 /// List of source scopes; these are referenced by statements
104 /// and used for debuginfo. Indexed by a `SourceScope`.
105 pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
54a0048b 106
94b46f34 107 /// Crate-local information for each source scope, that can't (and
ea8adc8c 108 /// needn't) be tracked across crates.
94b46f34 109 pub source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
ea8adc8c 110
a7813a04 111 /// Rvalues promoted from this function, such as borrows of constants.
dc9dc135 112 /// Each of them is the Body of a constant with the fn's type parameters
c30ab7b3 113 /// in scope, but a separate set of locals.
dc9dc135 114 pub promoted: IndexVec<Promoted, Body<'tcx>>,
a7813a04 115
9fa01778 116 /// Yields type of the function, if it is a generator.
ea8adc8c
XL
117 pub yield_ty: Option<Ty<'tcx>>,
118
119 /// Generator drop glue
dc9dc135 120 pub generator_drop: Option<Box<Body<'tcx>>>,
ea8adc8c
XL
121
122 /// The layout of a generator. Produced by the state transformation.
123 pub generator_layout: Option<GeneratorLayout<'tcx>>,
124
c30ab7b3
SL
125 /// Declarations of locals.
126 ///
127 /// The first local is the return value pointer, followed by `arg_count`
128 /// locals for the function arguments, followed by any user-declared
129 /// variables and temporaries.
041b39d2 130 pub local_decls: LocalDecls<'tcx>,
92a42be0 131
0731742a
XL
132 /// User type annotations
133 pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
134
c30ab7b3
SL
135 /// Number of arguments this function takes.
136 ///
137 /// Starting at local 1, `arg_count` locals will be provided by the caller
138 /// and can be assumed to be initialized.
139 ///
140 /// If this MIR was built for a constant, this will be 0.
141 pub arg_count: usize,
7453a54e 142
c30ab7b3
SL
143 /// Mark an argument local (which must be a tuple) as getting passed as
144 /// its individual components at the LLVM level.
145 ///
146 /// This is used for the "rust-call" ABI.
147 pub spread_arg: Option<Local>,
148
48663c56
XL
149 /// Names and capture modes of all the closure upvars, assuming
150 /// the first argument is either the closure or a reference to it.
151 // NOTE(eddyb) This is *strictly* a temporary hack for codegen
152 // debuginfo generation, and will be removed at some point.
153 // Do **NOT** use it for anything else, upvar information should not be
154 // in the MIR, please rely on local crate HIR or other side-channels.
155 pub __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
156
0731742a
XL
157 /// Mark this MIR of a const context other than const functions as having converted a `&&` or
158 /// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
159 /// this conversion from happening and use short circuiting, we will cause the following code
160 /// to change the value of `x`: `let mut x = 42; false && { x = 55; true };`
161 ///
162 /// List of places where control flow was destroyed. Used for error reporting.
163 pub control_flow_destroyed: Vec<(Span, String)>,
164
7453a54e
SL
165 /// A span representing this MIR, for error reporting
166 pub span: Span,
3157f602
XL
167
168 /// A cache for various calculations
94b46f34 169 cache: cache::Cache,
e9174d1e
SL
170}
171
dc9dc135 172impl<'tcx> Body<'tcx> {
94b46f34
XL
173 pub fn new(
174 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
175 source_scopes: IndexVec<SourceScope, SourceScopeData>,
176 source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
dc9dc135 177 promoted: IndexVec<Promoted, Body<'tcx>>,
94b46f34 178 yield_ty: Option<Ty<'tcx>>,
0731742a
XL
179 local_decls: LocalDecls<'tcx>,
180 user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
94b46f34 181 arg_count: usize,
48663c56 182 __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
94b46f34 183 span: Span,
0731742a 184 control_flow_destroyed: Vec<(Span, String)>,
94b46f34 185 ) -> Self {
ff7c6d11 186 // We need `arg_count` locals, and one for the return place
94b46f34
XL
187 assert!(
188 local_decls.len() >= arg_count + 1,
189 "expected at least {} locals, got {}",
190 arg_count + 1,
191 local_decls.len()
192 );
c30ab7b3 193
dc9dc135 194 Body {
a1dfa0c6 195 phase: MirPhase::Build,
041b39d2 196 basic_blocks,
94b46f34
XL
197 source_scopes,
198 source_scope_local_data,
041b39d2 199 promoted,
ea8adc8c
XL
200 yield_ty,
201 generator_drop: None,
202 generator_layout: None,
041b39d2 203 local_decls,
0731742a 204 user_type_annotations,
041b39d2 205 arg_count,
48663c56 206 __upvar_debuginfo_codegen_only_do_not_use,
c30ab7b3 207 spread_arg: None,
041b39d2 208 span,
94b46f34 209 cache: cache::Cache::new(),
0731742a 210 control_flow_destroyed,
3157f602
XL
211 }
212 }
213
214 #[inline]
215 pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
216 &self.basic_blocks
217 }
218
219 #[inline]
220 pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
221 self.cache.invalidate();
222 &mut self.basic_blocks
e9174d1e
SL
223 }
224
ff7c6d11 225 #[inline]
94b46f34
XL
226 pub fn basic_blocks_and_local_decls_mut(
227 &mut self,
416331ca 228 ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
ff7c6d11
XL
229 self.cache.invalidate();
230 (&mut self.basic_blocks, &mut self.local_decls)
231 }
232
3157f602 233 #[inline]
b7449926 234 pub fn predecessors(&self) -> MappedReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
3157f602 235 self.cache.predecessors(self)
e9174d1e
SL
236 }
237
3157f602 238 #[inline]
b7449926
XL
239 pub fn predecessors_for(&self, bb: BasicBlock) -> MappedReadGuard<'_, Vec<BasicBlock>> {
240 MappedReadGuard::map(self.predecessors(), |p| &p[bb])
241 }
242
243 #[inline]
244 pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
245 let if_zero_locations = if loc.statement_index == 0 {
246 let predecessor_blocks = self.predecessors_for(loc.block);
247 let num_predecessor_blocks = predecessor_blocks.len();
248 Some(
249 (0..num_predecessor_blocks)
250 .map(move |i| predecessor_blocks[i])
251 .map(move |bb| self.terminator_loc(bb)),
252 )
253 } else {
254 None
255 };
256
257 let if_not_zero_locations = if loc.statement_index == 0 {
258 None
259 } else {
416331ca 260 Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
b7449926
XL
261 };
262
416331ca 263 if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
3157f602
XL
264 }
265
266 #[inline]
267 pub fn dominators(&self) -> Dominators<BasicBlock> {
268 dominators(self)
269 }
270
c30ab7b3
SL
271 #[inline]
272 pub fn local_kind(&self, local: Local) -> LocalKind {
b7449926 273 let index = local.as_usize();
c30ab7b3 274 if index == 0 {
94b46f34
XL
275 debug_assert!(
276 self.local_decls[local].mutability == Mutability::Mut,
277 "return place should be mutable"
278 );
c30ab7b3
SL
279
280 LocalKind::ReturnPointer
281 } else if index < self.arg_count + 1 {
282 LocalKind::Arg
283 } else if self.local_decls[local].name.is_some() {
284 LocalKind::Var
285 } else {
c30ab7b3
SL
286 LocalKind::Temp
287 }
288 }
289
290 /// Returns an iterator over all temporaries.
291 #[inline]
94b46f34
XL
292 pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
293 (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
c30ab7b3 294 let local = Local::new(index);
94b46f34 295 if self.local_decls[local].is_user_variable.is_some() {
c30ab7b3 296 None
cc61c64b
XL
297 } else {
298 Some(local)
3157f602 299 }
c30ab7b3
SL
300 })
301 }
302
303 /// Returns an iterator over all user-declared locals.
304 #[inline]
94b46f34
XL
305 pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
306 (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
c30ab7b3 307 let local = Local::new(index);
94b46f34 308 if self.local_decls[local].is_user_variable.is_some() {
c30ab7b3 309 Some(local)
cc61c64b
XL
310 } else {
311 None
3157f602 312 }
c30ab7b3 313 })
3157f602
XL
314 }
315
a1dfa0c6
XL
316 /// Returns an iterator over all user-declared mutable locals.
317 #[inline]
318 pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
319 (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
320 let local = Local::new(index);
321 let decl = &self.local_decls[local];
322 if decl.is_user_variable.is_some() && decl.mutability == Mutability::Mut {
323 Some(local)
324 } else {
325 None
326 }
327 })
328 }
329
83c7162d
XL
330 /// Returns an iterator over all user-declared mutable arguments and locals.
331 #[inline]
94b46f34 332 pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
83c7162d
XL
333 (1..self.local_decls.len()).filter_map(move |index| {
334 let local = Local::new(index);
335 let decl = &self.local_decls[local];
94b46f34
XL
336 if (decl.is_user_variable.is_some() || index < self.arg_count + 1)
337 && decl.mutability == Mutability::Mut
83c7162d
XL
338 {
339 Some(local)
340 } else {
341 None
342 }
343 })
344 }
345
c30ab7b3
SL
346 /// Returns an iterator over all function arguments.
347 #[inline]
94b46f34 348 pub fn args_iter(&self) -> impl Iterator<Item = Local> {
c30ab7b3 349 let arg_count = self.arg_count;
0731742a 350 (1..=arg_count).map(Local::new)
e9174d1e 351 }
9e0c209e 352
c30ab7b3 353 /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
ff7c6d11 354 /// locals that are neither arguments nor the return place).
c30ab7b3 355 #[inline]
94b46f34 356 pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> {
c30ab7b3
SL
357 let arg_count = self.arg_count;
358 let local_count = self.local_decls.len();
94b46f34 359 (arg_count + 1..local_count).map(Local::new)
9e0c209e
SL
360 }
361
362 /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
363 /// invalidating statement indices in `Location`s.
364 pub fn make_statement_nop(&mut self, location: Location) {
365 let block = &mut self[location.block];
366 debug_assert!(location.statement_index < block.statements.len());
367 block.statements[location.statement_index].make_nop()
368 }
ea8adc8c
XL
369
370 /// Returns the source info associated with `location`.
371 pub fn source_info(&self, location: Location) -> &SourceInfo {
372 let block = &self[location.block];
373 let stmts = &block.statements;
374 let idx = location.statement_index;
abe05a73 375 if idx < stmts.len() {
ea8adc8c
XL
376 &stmts[idx].source_info
377 } else {
0bf4aa26 378 assert_eq!(idx, stmts.len());
ea8adc8c
XL
379 &block.terminator().source_info
380 }
381 }
abe05a73 382
9fa01778 383 /// Checks if `sub` is a sub scope of `sup`
94b46f34 384 pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool {
0bf4aa26 385 while sub != sup {
94b46f34
XL
386 match self.source_scopes[sub].parent_scope {
387 None => return false,
388 Some(p) => sub = p,
389 }
390 }
0bf4aa26 391 true
94b46f34
XL
392 }
393
9fa01778 394 /// Returns the return type, it always return first element from `local_decls` array
abe05a73 395 pub fn return_ty(&self) -> Ty<'tcx> {
ff7c6d11 396 self.local_decls[RETURN_PLACE].ty
abe05a73 397 }
b7449926 398
9fa01778 399 /// Gets the location of the terminator for the given block
b7449926 400 pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
416331ca 401 Location { block: bb, statement_index: self[bb].statements.len() }
b7449926 402 }
ea8adc8c
XL
403}
404
532ac7d7 405#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
ea8adc8c
XL
406pub enum Safety {
407 Safe,
408 /// Unsafe because of a PushUnsafeBlock
409 BuiltinUnsafe,
410 /// Unsafe because of an unsafe fn
411 FnUnsafe,
412 /// Unsafe because of an `unsafe` block
532ac7d7 413 ExplicitUnsafe(hir::HirId),
e9174d1e
SL
414}
415
dc9dc135 416impl_stable_hash_for!(struct Body<'tcx> {
a1dfa0c6 417 phase,
cc61c64b 418 basic_blocks,
94b46f34
XL
419 source_scopes,
420 source_scope_local_data,
cc61c64b 421 promoted,
ea8adc8c
XL
422 yield_ty,
423 generator_drop,
424 generator_layout,
cc61c64b 425 local_decls,
0731742a 426 user_type_annotations,
cc61c64b 427 arg_count,
48663c56 428 __upvar_debuginfo_codegen_only_do_not_use,
cc61c64b 429 spread_arg,
0731742a 430 control_flow_destroyed,
cc61c64b
XL
431 span,
432 cache
433});
434
dc9dc135 435impl<'tcx> Index<BasicBlock> for Body<'tcx> {
9cc50fc6
SL
436 type Output = BasicBlockData<'tcx>;
437
438 #[inline]
439 fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
3157f602 440 &self.basic_blocks()[index]
9cc50fc6
SL
441 }
442}
443
dc9dc135 444impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
9cc50fc6
SL
445 #[inline]
446 fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
3157f602 447 &mut self.basic_blocks_mut()[index]
9cc50fc6
SL
448 }
449}
450
532ac7d7 451#[derive(Copy, Clone, Debug, HashStable)]
ff7c6d11 452pub enum ClearCrossCrate<T> {
ea8adc8c 453 Clear,
94b46f34 454 Set(T),
ea8adc8c
XL
455}
456
8faf50e0
XL
457impl<T> ClearCrossCrate<T> {
458 pub fn assert_crate_local(self) -> T {
459 match self {
460 ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
461 ClearCrossCrate::Set(v) => v,
462 }
463 }
464}
465
416331ca
XL
466impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {}
467impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {}
ea8adc8c 468
3157f602
XL
469/// Grouped information about the source code origin of a MIR entity.
470/// Intended to be inspected by diagnostics and debuginfo.
471/// Most passes can work with it as a whole, within a single function.
532ac7d7 472#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, HashStable)]
3157f602
XL
473pub struct SourceInfo {
474 /// Source span for the AST pertaining to this MIR entity.
475 pub span: Span,
476
94b46f34
XL
477 /// The source scope, keeping track of which bindings can be
478 /// seen by debuginfo, active lint levels, `unsafe {...}`, etc.
479 pub scope: SourceScope,
3157f602
XL
480}
481
e9174d1e
SL
482///////////////////////////////////////////////////////////////////////////
483// Mutability and borrow kinds
484
532ac7d7 485#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
e9174d1e
SL
486pub enum Mutability {
487 Mut,
488 Not,
489}
490
94b46f34
XL
491impl From<Mutability> for hir::Mutability {
492 fn from(m: Mutability) -> Self {
493 match m {
494 Mutability::Mut => hir::MutMutable,
495 Mutability::Not => hir::MutImmutable,
496 }
497 }
498}
499
416331ca
XL
500#[derive(
501 Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, HashStable,
502)]
e9174d1e
SL
503pub enum BorrowKind {
504 /// Data must be immutable and is aliasable.
505 Shared,
506
0bf4aa26
XL
507 /// The immediately borrowed place must be immutable, but projections from
508 /// it don't need to be. For example, a shallow borrow of `a.b` doesn't
509 /// conflict with a mutable borrow of `a.b.c`.
510 ///
511 /// This is used when lowering matches: when matching on a place we want to
512 /// ensure that place have the same value from the start of the match until
513 /// an arm is selected. This prevents this code from compiling:
514 ///
515 /// let mut x = &Some(0);
516 /// match *x {
517 /// None => (),
518 /// Some(_) if { x = &None; false } => (),
519 /// Some(_) => (),
520 /// }
521 ///
522 /// This can't be a shared borrow because mutably borrowing (*x as Some).0
523 /// should not prevent `if let None = x { ... }`, for example, because the
524 /// mutating `(*x as Some).0` can't affect the discriminant of `x`.
525 /// We can also report errors with this kind of borrow differently.
526 Shallow,
527
9fa01778 528 /// Data must be immutable but not aliasable. This kind of borrow
e9174d1e 529 /// cannot currently be expressed by the user and is used only in
b7449926
XL
530 /// implicit closure bindings. It is needed when the closure is
531 /// borrowing or mutating a mutable referent, e.g.:
e9174d1e 532 ///
a1dfa0c6
XL
533 /// let x: &mut isize = ...;
534 /// let y = || *x += 5;
e9174d1e
SL
535 ///
536 /// If we were to try to translate this closure into a more explicit
537 /// form, we'd encounter an error with the code as written:
538 ///
a1dfa0c6
XL
539 /// struct Env { x: & &mut isize }
540 /// let x: &mut isize = ...;
541 /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
542 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
e9174d1e 543 ///
b7449926 544 /// This is then illegal because you cannot mutate an `&mut` found
e9174d1e
SL
545 /// in an aliasable location. To solve, you'd have to translate with
546 /// an `&mut` borrow:
547 ///
a1dfa0c6
XL
548 /// struct Env { x: & &mut isize }
549 /// let x: &mut isize = ...;
550 /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
551 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
e9174d1e
SL
552 ///
553 /// Now the assignment to `**env.x` is legal, but creating a
554 /// mutable pointer to `x` is not because `x` is not mutable. We
555 /// could fix this by declaring `x` as `let mut x`. This is ok in
556 /// user code, if awkward, but extra weird for closures, since the
557 /// borrow is hidden.
558 ///
559 /// So we introduce a "unique imm" borrow -- the referent is
560 /// immutable, but not aliasable. This solves the problem. For
561 /// simplicity, we don't give users the way to express this
562 /// borrow, it's just used when translating closures.
563 Unique,
564
565 /// Data is mutable and not aliasable.
2c00a5a8 566 Mut {
9fa01778
XL
567 /// `true` if this borrow arose from method-call auto-ref
568 /// (i.e., `adjustment::Adjust::Borrow`).
94b46f34
XL
569 allow_two_phase_borrow: bool,
570 },
2c00a5a8
XL
571}
572
573impl BorrowKind {
574 pub fn allows_two_phase_borrow(&self) -> bool {
575 match *self {
0bf4aa26
XL
576 BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
577 BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow,
2c00a5a8
XL
578 }
579 }
e9174d1e
SL
580}
581
582///////////////////////////////////////////////////////////////////////////
583// Variables and temps
584
b7449926
XL
585newtype_index! {
586 pub struct Local {
532ac7d7 587 derive [HashStable]
abe05a73 588 DEBUG_FORMAT = "_{}",
ff7c6d11 589 const RETURN_PLACE = 0,
b7449926
XL
590 }
591}
54a0048b 592
416331ca
XL
593impl Atom for Local {
594 fn index(self) -> usize {
595 Idx::index(self)
596 }
597}
598
dc9dc135 599/// Classifies locals into categories. See `Body::local_kind`.
532ac7d7 600#[derive(PartialEq, Eq, Debug, HashStable)]
c30ab7b3
SL
601pub enum LocalKind {
602 /// User-declared variable binding
603 Var,
604 /// Compiler-introduced temporary
605 Temp,
606 /// Function argument
607 Arg,
608 /// Location of function's return value
609 ReturnPointer,
e9174d1e
SL
610}
611
8faf50e0
XL
612#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
613pub struct VarBindingForm<'tcx> {
94b46f34
XL
614 /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
615 pub binding_mode: ty::BindingMode,
616 /// If an explicit type was provided for this variable binding,
617 /// this holds the source Span of that type.
618 ///
9fa01778 619 /// NOTE: if you want to change this to a `HirId`, be wary that
94b46f34
XL
620 /// doing so breaks incremental compilation (as of this writing),
621 /// while a `Span` does not cause our tests to fail.
622 pub opt_ty_info: Option<Span>,
8faf50e0
XL
623 /// Place of the RHS of the =, or the subject of the `match` where this
624 /// variable is initialized. None in the case of `let PATTERN;`.
625 /// Some((None, ..)) in the case of and `let [mut] x = ...` because
626 /// (a) the right-hand side isn't evaluated as a place expression.
627 /// (b) it gives a way to separate this case from the remaining cases
628 /// for diagnostics.
629 pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
b7449926
XL
630 /// Span of the pattern in which this variable was bound.
631 pub pat_span: Span,
94b46f34
XL
632}
633
8faf50e0
XL
634#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
635pub enum BindingForm<'tcx> {
94b46f34 636 /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
8faf50e0 637 Var(VarBindingForm<'tcx>),
94b46f34 638 /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
0bf4aa26 639 ImplicitSelf(ImplicitSelfKind),
8faf50e0
XL
640 /// Reference used in a guard expression to ensure immutability.
641 RefForGuard,
94b46f34
XL
642}
643
0bf4aa26
XL
644/// Represents what type of implicit self a function has, if any.
645#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
646pub enum ImplicitSelfKind {
647 /// Represents a `fn x(self);`.
648 Imm,
649 /// Represents a `fn x(mut self);`.
650 Mut,
651 /// Represents a `fn x(&self);`.
652 ImmRef,
653 /// Represents a `fn x(&mut self);`.
654 MutRef,
655 /// Represents when a function does not have a self argument or
656 /// when a function has a `self: X` argument.
416331ca 657 None,
0bf4aa26
XL
658}
659
8faf50e0 660CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, }
94b46f34 661
8faf50e0
XL
662impl_stable_hash_for!(struct self::VarBindingForm<'tcx> {
663 binding_mode,
664 opt_ty_info,
b7449926
XL
665 opt_match_place,
666 pat_span
8faf50e0 667});
94b46f34 668
0bf4aa26
XL
669impl_stable_hash_for!(enum self::ImplicitSelfKind {
670 Imm,
671 Mut,
672 ImmRef,
673 MutRef,
674 None
675});
676
a1dfa0c6
XL
677impl_stable_hash_for!(enum self::MirPhase {
678 Build,
679 Const,
680 Validated,
681 Optimized,
682});
683
8faf50e0 684mod binding_form_impl {
9fa01778 685 use crate::ich::StableHashingContext;
b7449926 686 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
8faf50e0
XL
687
688 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for super::BindingForm<'tcx> {
b7449926
XL
689 fn hash_stable<W: StableHasherResult>(
690 &self,
691 hcx: &mut StableHashingContext<'a>,
692 hasher: &mut StableHasher<W>,
693 ) {
8faf50e0
XL
694 use super::BindingForm::*;
695 ::std::mem::discriminant(self).hash_stable(hcx, hasher);
696
697 match self {
698 Var(binding) => binding.hash_stable(hcx, hasher),
0bf4aa26 699 ImplicitSelf(kind) => kind.hash_stable(hcx, hasher),
8faf50e0
XL
700 RefForGuard => (),
701 }
702 }
703 }
704}
94b46f34 705
0bf4aa26
XL
706/// `BlockTailInfo` is attached to the `LocalDecl` for temporaries
707/// created during evaluation of expressions in a block tail
708/// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`.
709///
710/// It is used to improve diagnostics when such temporaries are
0731742a 711/// involved in borrow_check errors, e.g., explanations of where the
0bf4aa26
XL
712/// temporaries come from, when their destructors are run, and/or how
713/// one might revise the code to satisfy the borrow checker's rules.
714#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
715pub struct BlockTailInfo {
716 /// If `true`, then the value resulting from evaluating this tail
717 /// expression is ignored by the block's expression context.
718 ///
719 /// Examples include `{ ...; tail };` and `let _ = { ...; tail };`
0731742a 720 /// but not e.g., `let _x = { ...; tail };`
0bf4aa26
XL
721 pub tail_result_is_ignored: bool,
722}
723
724impl_stable_hash_for!(struct BlockTailInfo { tail_result_is_ignored });
725
c30ab7b3 726/// A MIR local.
7453a54e 727///
c30ab7b3 728/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
ff7c6d11 729/// argument, or the return place.
532ac7d7 730#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
c30ab7b3
SL
731pub struct LocalDecl<'tcx> {
732 /// `let mut x` vs `let x`.
733 ///
ff7c6d11 734 /// Temporaries and the return place are always mutable.
c30ab7b3
SL
735 pub mutability: Mutability,
736
94b46f34
XL
737 /// Some(binding_mode) if this corresponds to a user-declared local variable.
738 ///
739 /// This is solely used for local diagnostics when generating
740 /// warnings/errors when compiling the current crate, and
741 /// therefore it need not be visible across crates. pnkfelix
742 /// currently hypothesized we *need* to wrap this in a
743 /// `ClearCrossCrate` as long as it carries as `HirId`.
8faf50e0 744 pub is_user_variable: Option<ClearCrossCrate<BindingForm<'tcx>>>,
cc61c64b 745
9fa01778 746 /// `true` if this is an internal local.
ea8adc8c
XL
747 ///
748 /// These locals are not based on types in the source code and are only used
749 /// for a few desugarings at the moment.
750 ///
751 /// The generator transformation will sanity check the locals which are live
752 /// across a suspension point against the type components of the generator
753 /// which type checking knows are live across a suspension point. We need to
754 /// flag drop flags to avoid triggering this check as they are introduced
755 /// after typeck.
756 ///
757 /// Unsafety checking will also ignore dereferences of these locals,
758 /// so they can be used for raw pointers only used in a desugaring.
759 ///
760 /// This should be sound because the drop flags are fully algebraic, and
761 /// therefore don't affect the OIBIT or outlives properties of the
762 /// generator.
763 pub internal: bool,
764
0bf4aa26
XL
765 /// If this local is a temporary and `is_block_tail` is `Some`,
766 /// then it is a temporary created for evaluation of some
767 /// subexpression of some block's tail expression (with no
768 /// intervening statement context).
769 pub is_block_tail: Option<BlockTailInfo>,
770
c30ab7b3 771 /// Type of this local.
b039eaaf 772 pub ty: Ty<'tcx>,
54a0048b 773
b7449926 774 /// If the user manually ascribed a type to this variable,
0731742a 775 /// e.g., via `let x: T`, then we carry that type here. The MIR
b7449926
XL
776 /// borrow checker needs this information since it can affect
777 /// region inference.
532ac7d7 778 pub user_ty: UserTypeProjections,
b7449926 779
c30ab7b3
SL
780 /// Name of the local, used in debuginfo and pretty-printing.
781 ///
782 /// Note that function arguments can also have this set to `Some(_)`
783 /// to generate better debuginfo.
784 pub name: Option<Name>,
a7813a04 785
0731742a 786 /// The *syntactic* (i.e., not visibility) source scope the local is defined
ea8adc8c
XL
787 /// in. If the local was defined in a let-statement, this
788 /// is *within* the let-statement, rather than outside
789 /// of it.
ff7c6d11 790 ///
94b46f34
XL
791 /// This is needed because the visibility source scope of locals within
792 /// a let-statement is weird.
ff7c6d11
XL
793 ///
794 /// The reason is that we want the local to be *within* the let-statement
795 /// for lint purposes, but we want the local to be *after* the let-statement
796 /// for names-in-scope purposes.
797 ///
798 /// That's it, if we have a let-statement like the one in this
799 /// function:
800 ///
801 /// ```
802 /// fn foo(x: &str) {
803 /// #[allow(unused_mut)]
804 /// let mut x: u32 = { // <- one unused mut
805 /// let mut y: u32 = x.parse().unwrap();
806 /// y + 2
807 /// };
808 /// drop(x);
809 /// }
810 /// ```
811 ///
812 /// Then, from a lint point of view, the declaration of `x: u32`
813 /// (and `y: u32`) are within the `#[allow(unused_mut)]` scope - the
814 /// lint scopes are the same as the AST/HIR nesting.
815 ///
816 /// However, from a name lookup point of view, the scopes look more like
817 /// as if the let-statements were `match` expressions:
818 ///
819 /// ```
820 /// fn foo(x: &str) {
821 /// match {
822 /// match x.parse().unwrap() {
823 /// y => y + 2
824 /// }
825 /// } {
826 /// x => drop(x)
827 /// };
828 /// }
829 /// ```
830 ///
831 /// We care about the name-lookup scopes for debuginfo - if the
832 /// debuginfo instruction pointer is at the call to `x.parse()`, we
833 /// want `x` to refer to `x: &str`, but if it is at the call to
834 /// `drop(x)`, we want it to refer to `x: u32`.
835 ///
836 /// To allow both uses to work, we need to have more than a single scope
94b46f34 837 /// for a local. We have the `source_info.scope` represent the
ff7c6d11 838 /// "syntactic" lint scope (with a variable being under its let
94b46f34 839 /// block) while the `visibility_scope` represents the "local variable"
ff7c6d11
XL
840 /// scope (where the "rest" of a block is under all prior let-statements).
841 ///
842 /// The end result looks like this:
843 ///
844 /// ```text
845 /// ROOT SCOPE
846 /// │{ argument x: &str }
847 /// │
b7449926 848 /// │ │{ #[allow(unused_mut)] } // this is actually split into 2 scopes
ff7c6d11
XL
849 /// │ │ // in practice because I'm lazy.
850 /// │ │
94b46f34 851 /// │ │← x.source_info.scope
ff7c6d11
XL
852 /// │ │← `x.parse().unwrap()`
853 /// │ │
94b46f34 854 /// │ │ │← y.source_info.scope
ff7c6d11
XL
855 /// │ │
856 /// │ │ │{ let y: u32 }
857 /// │ │ │
94b46f34 858 /// │ │ │← y.visibility_scope
ff7c6d11
XL
859 /// │ │ │← `y + 2`
860 /// │
861 /// │ │{ let x: u32 }
94b46f34 862 /// │ │← x.visibility_scope
ff7c6d11
XL
863 /// │ │← `drop(x)` // this accesses `x: u32`
864 /// ```
94b46f34
XL
865 pub source_info: SourceInfo,
866
867 /// Source scope within which the local is visible (for debuginfo)
868 /// (see `source_info` for more details).
869 pub visibility_scope: SourceScope,
c30ab7b3
SL
870}
871
872impl<'tcx> LocalDecl<'tcx> {
9fa01778 873 /// Returns `true` only if local is a binding that can itself be
94b46f34
XL
874 /// made mutable via the addition of the `mut` keyword, namely
875 /// something like the occurrences of `x` in:
876 /// - `fn foo(x: Type) { ... }`,
877 /// - `let x = ...`,
878 /// - or `match ... { C(x) => ... }`
879 pub fn can_be_made_mutable(&self) -> bool {
880 match self.is_user_variable {
881 Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
882 binding_mode: ty::BindingMode::BindByValue(_),
883 opt_ty_info: _,
8faf50e0 884 opt_match_place: _,
b7449926 885 pat_span: _,
94b46f34
XL
886 }))) => true,
887
416331ca 888 Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm))) => true,
0bf4aa26 889
94b46f34
XL
890 _ => false,
891 }
892 }
893
9fa01778 894 /// Returns `true` if local is definitely not a `ref ident` or
94b46f34
XL
895 /// `ref mut ident` binding. (Such bindings cannot be made into
896 /// mutable bindings, but the inverse does not necessarily hold).
897 pub fn is_nonref_binding(&self) -> bool {
898 match self.is_user_variable {
899 Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
900 binding_mode: ty::BindingMode::BindByValue(_),
901 opt_ty_info: _,
8faf50e0 902 opt_match_place: _,
b7449926 903 pat_span: _,
94b46f34
XL
904 }))) => true,
905
0bf4aa26 906 Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true,
94b46f34
XL
907
908 _ => false,
909 }
910 }
911
dc9dc135
XL
912 /// Returns `true` if this is a reference to a variable bound in a `match`
913 /// expression that is used to access said variable for the guard of the
914 /// match arm.
915 pub fn is_ref_for_guard(&self) -> bool {
916 match self.is_user_variable {
917 Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true,
918 _ => false,
919 }
920 }
921
922 /// Returns `true` is the local is from a compiler desugaring, e.g.,
923 /// `__next` from a `for` loop.
924 #[inline]
925 pub fn from_compiler_desugaring(&self) -> bool {
416331ca 926 self.source_info.span.desugaring_kind().is_some()
dc9dc135
XL
927 }
928
9fa01778 929 /// Creates a new `LocalDecl` for a temporary.
c30ab7b3 930 #[inline]
cc61c64b 931 pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
b7449926
XL
932 Self::new_local(ty, Mutability::Mut, false, span)
933 }
934
0bf4aa26 935 /// Converts `self` into same `LocalDecl` except tagged as immutable.
b7449926 936 #[inline]
0bf4aa26
XL
937 pub fn immutable(mut self) -> Self {
938 self.mutability = Mutability::Not;
939 self
940 }
941
942 /// Converts `self` into same `LocalDecl` except tagged as internal temporary.
943 #[inline]
944 pub fn block_tail(mut self, info: BlockTailInfo) -> Self {
945 assert!(self.is_block_tail.is_none());
946 self.is_block_tail = Some(info);
947 self
ea8adc8c
XL
948 }
949
9fa01778 950 /// Creates a new `LocalDecl` for a internal temporary.
ea8adc8c
XL
951 #[inline]
952 pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self {
b7449926
XL
953 Self::new_local(ty, Mutability::Mut, true, span)
954 }
955
956 #[inline]
416331ca 957 fn new_local(ty: Ty<'tcx>, mutability: Mutability, internal: bool, span: Span) -> Self {
ea8adc8c 958 LocalDecl {
b7449926 959 mutability,
ea8adc8c 960 ty,
0bf4aa26 961 user_ty: UserTypeProjections::none(),
ea8adc8c 962 name: None,
416331ca 963 source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
94b46f34 964 visibility_scope: OUTERMOST_SOURCE_SCOPE,
b7449926 965 internal,
94b46f34 966 is_user_variable: None,
0bf4aa26 967 is_block_tail: None,
c30ab7b3
SL
968 }
969 }
970
ff7c6d11 971 /// Builds a `LocalDecl` for the return place.
c30ab7b3
SL
972 ///
973 /// This must be inserted into the `local_decls` list as the first local.
974 #[inline]
0bf4aa26 975 pub fn new_return_place(return_ty: Ty<'_>, span: Span) -> LocalDecl<'_> {
c30ab7b3
SL
976 LocalDecl {
977 mutability: Mutability::Mut,
978 ty: return_ty,
0bf4aa26 979 user_ty: UserTypeProjections::none(),
416331ca 980 source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
94b46f34 981 visibility_scope: OUTERMOST_SOURCE_SCOPE,
ea8adc8c 982 internal: false,
0bf4aa26 983 is_block_tail: None,
94b46f34
XL
984 name: None, // FIXME maybe we do want some name here?
985 is_user_variable: None,
c30ab7b3
SL
986 }
987 }
a7813a04
XL
988}
989
990/// A closure capture, with its name and mode.
532ac7d7 991#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
48663c56 992pub struct UpvarDebuginfo {
a7813a04
XL
993 pub debug_name: Name,
994
995 /// If true, the capture is behind a reference.
ff7c6d11 996 pub by_ref: bool,
e9174d1e
SL
997}
998
e9174d1e
SL
999///////////////////////////////////////////////////////////////////////////
1000// BasicBlock
1001
b7449926
XL
1002newtype_index! {
1003 pub struct BasicBlock {
532ac7d7 1004 derive [HashStable]
b7449926
XL
1005 DEBUG_FORMAT = "bb{}",
1006 const START_BLOCK = 0,
1007 }
1008}
abe05a73
XL
1009
1010impl BasicBlock {
1011 pub fn start_location(self) -> Location {
416331ca 1012 Location { block: self, statement_index: 0 }
abe05a73
XL
1013 }
1014}
e9174d1e
SL
1015
1016///////////////////////////////////////////////////////////////////////////
54a0048b 1017// BasicBlockData and Terminator
e9174d1e 1018
532ac7d7 1019#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
b039eaaf 1020pub struct BasicBlockData<'tcx> {
54a0048b 1021 /// List of statements in this block.
b039eaaf 1022 pub statements: Vec<Statement<'tcx>>,
54a0048b
SL
1023
1024 /// Terminator for this block.
1025 ///
9fa01778 1026 /// N.B., this should generally ONLY be `None` during construction.
54a0048b
SL
1027 /// Therefore, you should generally access it via the
1028 /// `terminator()` or `terminator_mut()` methods. The only
1029 /// exception is that certain passes, such as `simplify_cfg`, swap
1030 /// out the terminator temporarily with `None` while they continue
1031 /// to recurse over the set of basic blocks.
9cc50fc6 1032 pub terminator: Option<Terminator<'tcx>>,
54a0048b
SL
1033
1034 /// If true, this block lies on an unwind path. This is used
94b46f34 1035 /// during codegen where distinct kinds of basic blocks may be
54a0048b
SL
1036 /// generated (particularly for MSVC cleanup). Unwind blocks must
1037 /// only branch to other unwind blocks.
9cc50fc6 1038 pub is_cleanup: bool,
e9174d1e
SL
1039}
1040
532ac7d7 1041#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
54a0048b 1042pub struct Terminator<'tcx> {
3157f602 1043 pub source_info: SourceInfo,
94b46f34 1044 pub kind: TerminatorKind<'tcx>,
54a0048b
SL
1045}
1046
532ac7d7 1047#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
54a0048b 1048pub enum TerminatorKind<'tcx> {
e9174d1e 1049 /// block should have one successor in the graph; we jump there
94b46f34 1050 Goto { target: BasicBlock },
e9174d1e 1051
92a42be0
SL
1052 /// operand evaluates to an integer; jump depending on its value
1053 /// to one of the targets, and otherwise fallback to `otherwise`
1054 SwitchInt {
1055 /// discriminant value being tested
8bb4bdeb 1056 discr: Operand<'tcx>,
92a42be0
SL
1057
1058 /// type of value being tested
1059 switch_ty: Ty<'tcx>,
1060
1061 /// Possible values. The locations to branch to in each case
1062 /// are found in the corresponding indices from the `targets` vector.
0531ce1d 1063 values: Cow<'tcx, [u128]>,
8bb4bdeb
XL
1064
1065 /// Possible branch sites. The last element of this vector is used
cc61c64b 1066 /// for the otherwise branch, so targets.len() == values.len() + 1
8bb4bdeb
XL
1067 /// should hold.
1068 // This invariant is quite non-obvious and also could be improved.
1069 // One way to make this invariant is to have something like this instead:
1070 //
1071 // branches: Vec<(ConstInt, BasicBlock)>,
1072 // otherwise: Option<BasicBlock> // exhaustive if None
1073 //
1074 // However we’ve decided to keep this as-is until we figure a case
1075 // where some other approach seems to be strictly better than other.
b039eaaf
SL
1076 targets: Vec<BasicBlock>,
1077 },
e9174d1e 1078
9cc50fc6
SL
1079 /// Indicates that the landing pad is finished and unwinding should
1080 /// continue. Emitted by build::scope::diverge_cleanup.
1081 Resume,
e9174d1e 1082
ff7c6d11
XL
1083 /// Indicates that the landing pad is finished and that the process
1084 /// should abort. Used to prevent unwinding for foreign items.
1085 Abort,
1086
1087 /// Indicates a normal return. The return place should have
1088 /// been filled in by now. This should occur at most once.
e9174d1e
SL
1089 Return,
1090
3157f602
XL
1091 /// Indicates a terminator that can never be reached.
1092 Unreachable,
1093
ff7c6d11 1094 /// Drop the Place
416331ca 1095 Drop { location: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> },
7453a54e 1096
ff7c6d11 1097 /// Drop the Place and assign the new value over it. This ensures
2c00a5a8 1098 /// that the assignment to `P` occurs *even if* the destructor for
b7449926 1099 /// place unwinds. Its semantics are best explained by the
abe05a73
XL
1100 /// elaboration:
1101 ///
1102 /// ```
1103 /// BB0 {
2c00a5a8 1104 /// DropAndReplace(P <- V, goto BB1, unwind BB2)
abe05a73
XL
1105 /// }
1106 /// ```
1107 ///
1108 /// becomes
1109 ///
1110 /// ```
1111 /// BB0 {
2c00a5a8 1112 /// Drop(P, goto BB1, unwind BB2)
abe05a73
XL
1113 /// }
1114 /// BB1 {
b7449926 1115 /// // P is now uninitialized
2c00a5a8 1116 /// P <- V
abe05a73
XL
1117 /// }
1118 /// BB2 {
b7449926 1119 /// // P is now uninitialized -- its dtor panicked
2c00a5a8 1120 /// P <- V
abe05a73
XL
1121 /// }
1122 /// ```
3157f602 1123 DropAndReplace {
ff7c6d11 1124 location: Place<'tcx>,
3157f602
XL
1125 value: Operand<'tcx>,
1126 target: BasicBlock,
1127 unwind: Option<BasicBlock>,
1128 },
1129
9cc50fc6 1130 /// Block ends with a call of a converging function
b039eaaf 1131 Call {
9cc50fc6
SL
1132 /// The function that’s being called
1133 func: Operand<'tcx>,
abe05a73
XL
1134 /// Arguments the function is called with.
1135 /// These are owned by the callee, which is free to modify them.
1136 /// This allows the memory occupied by "by-value" arguments to be
1137 /// reused across function calls without duplicating the contents.
9cc50fc6 1138 args: Vec<Operand<'tcx>>,
7453a54e 1139 /// Destination for the return value. If some, the call is converging.
ff7c6d11 1140 destination: Option<(Place<'tcx>, BasicBlock)>,
7453a54e 1141 /// Cleanups to be done if the call unwinds.
94b46f34 1142 cleanup: Option<BasicBlock>,
0bf4aa26
XL
1143 /// Whether this is from a call in HIR, rather than from an overloaded
1144 /// operator. True for overloaded function call.
1145 from_hir_call: bool,
b039eaaf 1146 },
3157f602
XL
1147
1148 /// Jump to the target if the condition has the expected value,
1149 /// otherwise panic with a message and a cleanup target.
1150 Assert {
1151 cond: Operand<'tcx>,
1152 expected: bool,
1153 msg: AssertMessage<'tcx>,
1154 target: BasicBlock,
94b46f34 1155 cleanup: Option<BasicBlock>,
ea8adc8c
XL
1156 },
1157
1158 /// A suspend point
1159 Yield {
1160 /// The value to return
1161 value: Operand<'tcx>,
1162 /// Where to resume to
1163 resume: BasicBlock,
1164 /// Cleanup to be done if the generator is dropped at this suspend point
1165 drop: Option<BasicBlock>,
1166 },
1167
1168 /// Indicates the end of the dropping of a generator
1169 GeneratorDrop,
abe05a73 1170
2c00a5a8
XL
1171 /// A block where control flow only ever takes one real path, but borrowck
1172 /// needs to be more conservative.
abe05a73 1173 FalseEdges {
2c00a5a8 1174 /// The target normal control flow will take
abe05a73 1175 real_target: BasicBlock,
dc9dc135
XL
1176 /// A block control flow could conceptually jump to, but won't in
1177 /// practice
1178 imaginary_target: BasicBlock,
2c00a5a8
XL
1179 },
1180 /// A terminator for blocks that only take one path in reality, but where we
1181 /// reserve the right to unwind in borrowck, even if it won't happen in practice.
1182 /// This can arise in infinite loops with no function calls for example.
1183 FalseUnwind {
1184 /// The target normal control flow will take
1185 real_target: BasicBlock,
1186 /// The imaginary cleanup block link. This particular path will never be taken
1187 /// in practice, but in order to avoid fragility we want to always
1188 /// consider it in borrowck. We don't want to accept programs which
1189 /// pass borrowck only when panic=abort or some assertions are disabled
1190 /// due to release vs. debug mode builds. This needs to be an Option because
1191 /// of the remove_noop_landing_pads and no_landing_pads passes
1192 unwind: Option<BasicBlock>,
abe05a73 1193 },
e9174d1e
SL
1194}
1195
83c7162d
XL
1196pub type Successors<'a> =
1197 iter::Chain<option::IntoIter<&'a BasicBlock>, slice::Iter<'a, BasicBlock>>;
1198pub type SuccessorsMut<'a> =
1199 iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
1200
b039eaaf 1201impl<'tcx> Terminator<'tcx> {
0bf4aa26 1202 pub fn successors(&self) -> Successors<'_> {
54a0048b
SL
1203 self.kind.successors()
1204 }
1205
0bf4aa26 1206 pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
54a0048b
SL
1207 self.kind.successors_mut()
1208 }
ff7c6d11 1209
8faf50e0
XL
1210 pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
1211 self.kind.unwind()
1212 }
1213
ff7c6d11
XL
1214 pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
1215 self.kind.unwind_mut()
1216 }
54a0048b
SL
1217}
1218
1219impl<'tcx> TerminatorKind<'tcx> {
dc9dc135
XL
1220 pub fn if_(
1221 tcx: TyCtxt<'tcx>,
94b46f34
XL
1222 cond: Operand<'tcx>,
1223 t: BasicBlock,
1224 f: BasicBlock,
1225 ) -> TerminatorKind<'tcx> {
0531ce1d 1226 static BOOL_SWITCH_FALSE: &'static [u128] = &[0];
8bb4bdeb
XL
1227 TerminatorKind::SwitchInt {
1228 discr: cond,
1229 switch_ty: tcx.types.bool,
1230 values: From::from(BOOL_SWITCH_FALSE),
1231 targets: vec![f, t],
1232 }
1233 }
1234
0bf4aa26 1235 pub fn successors(&self) -> Successors<'_> {
54a0048b 1236 use self::TerminatorKind::*;
e9174d1e 1237 match *self {
94b46f34
XL
1238 Resume
1239 | Abort
1240 | GeneratorDrop
1241 | Return
1242 | Unreachable
416331ca 1243 | Call { destination: None, cleanup: None, .. } => None.into_iter().chain(&[]),
94b46f34 1244 Goto { target: ref t }
416331ca
XL
1245 | Call { destination: None, cleanup: Some(ref t), .. }
1246 | Call { destination: Some((_, ref t)), cleanup: None, .. }
1247 | Yield { resume: ref t, drop: None, .. }
1248 | DropAndReplace { target: ref t, unwind: None, .. }
1249 | Drop { target: ref t, unwind: None, .. }
1250 | Assert { target: ref t, cleanup: None, .. }
1251 | FalseUnwind { real_target: ref t, unwind: None } => Some(t).into_iter().chain(&[]),
1252 Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. }
1253 | Yield { resume: ref t, drop: Some(ref u), .. }
1254 | DropAndReplace { target: ref t, unwind: Some(ref u), .. }
1255 | Drop { target: ref t, unwind: Some(ref u), .. }
1256 | Assert { target: ref t, cleanup: Some(ref u), .. }
1257 | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => {
1258 Some(t).into_iter().chain(slice::from_ref(u))
abe05a73 1259 }
94b46f34 1260 SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]),
416331ca
XL
1261 FalseEdges { ref real_target, ref imaginary_target } => {
1262 Some(real_target).into_iter().chain(slice::from_ref(imaginary_target))
1263 }
e9174d1e
SL
1264 }
1265 }
92a42be0 1266
0bf4aa26 1267 pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
54a0048b 1268 use self::TerminatorKind::*;
92a42be0 1269 match *self {
94b46f34
XL
1270 Resume
1271 | Abort
1272 | GeneratorDrop
1273 | Return
1274 | Unreachable
416331ca 1275 | Call { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []),
94b46f34 1276 Goto { target: ref mut t }
416331ca
XL
1277 | Call { destination: None, cleanup: Some(ref mut t), .. }
1278 | Call { destination: Some((_, ref mut t)), cleanup: None, .. }
1279 | Yield { resume: ref mut t, drop: None, .. }
1280 | DropAndReplace { target: ref mut t, unwind: None, .. }
1281 | Drop { target: ref mut t, unwind: None, .. }
1282 | Assert { target: ref mut t, cleanup: None, .. }
1283 | FalseUnwind { real_target: ref mut t, unwind: None } => {
1284 Some(t).into_iter().chain(&mut [])
abe05a73 1285 }
416331ca
XL
1286 Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. }
1287 | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
1288 | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. }
1289 | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
1290 | Assert { target: ref mut t, cleanup: Some(ref mut u), .. }
1291 | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => {
1292 Some(t).into_iter().chain(slice::from_mut(u))
94b46f34 1293 }
416331ca
XL
1294 SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]),
1295 FalseEdges { ref mut real_target, ref mut imaginary_target } => {
1296 Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
94b46f34 1297 }
92a42be0
SL
1298 }
1299 }
ff7c6d11 1300
8faf50e0
XL
1301 pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
1302 match *self {
1303 TerminatorKind::Goto { .. }
1304 | TerminatorKind::Resume
1305 | TerminatorKind::Abort
1306 | TerminatorKind::Return
1307 | TerminatorKind::Unreachable
1308 | TerminatorKind::GeneratorDrop
1309 | TerminatorKind::Yield { .. }
1310 | TerminatorKind::SwitchInt { .. }
1311 | TerminatorKind::FalseEdges { .. } => None,
416331ca
XL
1312 TerminatorKind::Call { cleanup: ref unwind, .. }
1313 | TerminatorKind::Assert { cleanup: ref unwind, .. }
8faf50e0
XL
1314 | TerminatorKind::DropAndReplace { ref unwind, .. }
1315 | TerminatorKind::Drop { ref unwind, .. }
1316 | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
1317 }
1318 }
1319
ff7c6d11
XL
1320 pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
1321 match *self {
94b46f34
XL
1322 TerminatorKind::Goto { .. }
1323 | TerminatorKind::Resume
1324 | TerminatorKind::Abort
1325 | TerminatorKind::Return
1326 | TerminatorKind::Unreachable
1327 | TerminatorKind::GeneratorDrop
1328 | TerminatorKind::Yield { .. }
1329 | TerminatorKind::SwitchInt { .. }
1330 | TerminatorKind::FalseEdges { .. } => None,
416331ca
XL
1331 TerminatorKind::Call { cleanup: ref mut unwind, .. }
1332 | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
94b46f34
XL
1333 | TerminatorKind::DropAndReplace { ref mut unwind, .. }
1334 | TerminatorKind::Drop { ref mut unwind, .. }
1335 | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind),
ff7c6d11
XL
1336 }
1337 }
e9174d1e
SL
1338}
1339
b039eaaf 1340impl<'tcx> BasicBlockData<'tcx> {
9cc50fc6 1341 pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
416331ca 1342 BasicBlockData { statements: vec![], terminator, is_cleanup: false }
e9174d1e 1343 }
9cc50fc6
SL
1344
1345 /// Accessor for terminator.
1346 ///
1347 /// Terminator may not be None after construction of the basic block is complete. This accessor
1348 /// provides a convenience way to reach the terminator.
1349 pub fn terminator(&self) -> &Terminator<'tcx> {
1350 self.terminator.as_ref().expect("invalid terminator state")
1351 }
1352
1353 pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
1354 self.terminator.as_mut().expect("invalid terminator state")
1355 }
ea8adc8c 1356
94b46f34
XL
1357 pub fn retain_statements<F>(&mut self, mut f: F)
1358 where
0bf4aa26 1359 F: FnMut(&mut Statement<'_>) -> bool,
94b46f34 1360 {
ea8adc8c
XL
1361 for s in &mut self.statements {
1362 if !f(s) {
0531ce1d 1363 s.make_nop();
ea8adc8c
XL
1364 }
1365 }
1366 }
ff7c6d11 1367
0531ce1d 1368 pub fn expand_statements<F, I>(&mut self, mut f: F)
94b46f34
XL
1369 where
1370 F: FnMut(&mut Statement<'tcx>) -> Option<I>,
1371 I: iter::TrustedLen<Item = Statement<'tcx>>,
0531ce1d
XL
1372 {
1373 // Gather all the iterators we'll need to splice in, and their positions.
1374 let mut splices: Vec<(usize, I)> = vec![];
1375 let mut extra_stmts = 0;
1376 for (i, s) in self.statements.iter_mut().enumerate() {
1377 if let Some(mut new_stmts) = f(s) {
1378 if let Some(first) = new_stmts.next() {
1379 // We can already store the first new statement.
1380 *s = first;
1381
1382 // Save the other statements for optimized splicing.
1383 let remaining = new_stmts.size_hint().0;
1384 if remaining > 0 {
1385 splices.push((i + 1 + extra_stmts, new_stmts));
1386 extra_stmts += remaining;
1387 }
1388 } else {
1389 s.make_nop();
1390 }
1391 }
1392 }
1393
1394 // Splice in the new statements, from the end of the block.
1395 // FIXME(eddyb) This could be more efficient with a "gap buffer"
1396 // where a range of elements ("gap") is left uninitialized, with
1397 // splicing adding new elements to the end of that gap and moving
1398 // existing elements from before the gap to the end of the gap.
1399 // For now, this is safe code, emulating a gap but initializing it.
94b46f34
XL
1400 let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
1401 self.statements.resize(
1402 gap.end,
1403 Statement {
416331ca 1404 source_info: SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE },
94b46f34 1405 kind: StatementKind::Nop,
0531ce1d 1406 },
94b46f34 1407 );
0531ce1d
XL
1408 for (splice_start, new_stmts) in splices.into_iter().rev() {
1409 let splice_end = splice_start + new_stmts.size_hint().0;
1410 while gap.end > splice_end {
1411 gap.start -= 1;
1412 gap.end -= 1;
1413 self.statements.swap(gap.start, gap.end);
1414 }
1415 self.statements.splice(splice_start..splice_end, new_stmts);
1416 gap.end = splice_start;
1417 }
1418 }
1419
ff7c6d11
XL
1420 pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
1421 if index < self.statements.len() {
1422 &self.statements[index]
1423 } else {
1424 &self.terminator
1425 }
1426 }
e9174d1e
SL
1427}
1428
54a0048b 1429impl<'tcx> Debug for TerminatorKind<'tcx> {
0bf4aa26 1430 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
54a0048b 1431 self.fmt_head(fmt)?;
83c7162d 1432 let successor_count = self.successors().count();
9cc50fc6 1433 let labels = self.fmt_successor_labels();
83c7162d 1434 assert_eq!(successor_count, labels.len());
9cc50fc6 1435
83c7162d 1436 match successor_count {
9cc50fc6
SL
1437 0 => Ok(()),
1438
83c7162d 1439 1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()),
9cc50fc6
SL
1440
1441 _ => {
54a0048b 1442 write!(fmt, " -> [")?;
83c7162d 1443 for (i, target) in self.successors().enumerate() {
9cc50fc6 1444 if i > 0 {
54a0048b 1445 write!(fmt, ", ")?;
9cc50fc6 1446 }
54a0048b 1447 write!(fmt, "{}: {:?}", labels[i], target)?;
9cc50fc6
SL
1448 }
1449 write!(fmt, "]")
1450 }
9cc50fc6
SL
1451 }
1452 }
1453}
1454
54a0048b 1455impl<'tcx> TerminatorKind<'tcx> {
9cc50fc6 1456 /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
3b2f2976 1457 /// successor basic block, if any. The only information not included is the list of possible
9cc50fc6
SL
1458 /// successors, which may be rendered differently between the text and the graphviz format.
1459 pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
54a0048b 1460 use self::TerminatorKind::*;
e9174d1e 1461 match *self {
9cc50fc6 1462 Goto { .. } => write!(fmt, "goto"),
416331ca 1463 SwitchInt { discr: ref place, .. } => write!(fmt, "switchInt({:?})", place),
9cc50fc6 1464 Return => write!(fmt, "return"),
ea8adc8c 1465 GeneratorDrop => write!(fmt, "generator_drop"),
9cc50fc6 1466 Resume => write!(fmt, "resume"),
ff7c6d11 1467 Abort => write!(fmt, "abort"),
ea8adc8c 1468 Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value),
3157f602
XL
1469 Unreachable => write!(fmt, "unreachable"),
1470 Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
416331ca
XL
1471 DropAndReplace { ref location, ref value, .. } => {
1472 write!(fmt, "replace({:?} <- {:?})", location, value)
1473 }
1474 Call { ref func, ref args, ref destination, .. } => {
7453a54e 1475 if let Some((ref destination, _)) = *destination {
54a0048b 1476 write!(fmt, "{:?} = ", destination)?;
9cc50fc6 1477 }
54a0048b 1478 write!(fmt, "{:?}(", func)?;
9cc50fc6 1479 for (index, arg) in args.iter().enumerate() {
b039eaaf 1480 if index > 0 {
54a0048b 1481 write!(fmt, ", ")?;
b039eaaf 1482 }
54a0048b 1483 write!(fmt, "{:?}", arg)?;
e9174d1e 1484 }
9cc50fc6 1485 write!(fmt, ")")
e9174d1e 1486 }
416331ca 1487 Assert { ref cond, expected, ref msg, .. } => {
3157f602
XL
1488 write!(fmt, "assert(")?;
1489 if !expected {
1490 write!(fmt, "!")?;
1491 }
83c7162d 1492 write!(fmt, "{:?}, \"{:?}\")", cond, msg)
94b46f34 1493 }
2c00a5a8
XL
1494 FalseEdges { .. } => write!(fmt, "falseEdges"),
1495 FalseUnwind { .. } => write!(fmt, "falseUnwind"),
e9174d1e
SL
1496 }
1497 }
9cc50fc6 1498
9fa01778 1499 /// Returns the list of labels for the edges to the successor basic blocks.
9cc50fc6 1500 pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
54a0048b 1501 use self::TerminatorKind::*;
9cc50fc6 1502 match *self {
ff7c6d11 1503 Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
7453a54e 1504 Goto { .. } => vec!["".into()],
416331ca
XL
1505 SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| {
1506 let param_env = ty::ParamEnv::empty();
1507 let switch_ty = tcx.lift_to_global(&switch_ty).unwrap();
1508 let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
1509 values
1510 .iter()
1511 .map(|&u| {
1512 tcx.mk_const(ty::Const {
1513 val: ConstValue::Scalar(Scalar::from_uint(u, size).into()),
1514 ty: switch_ty,
1515 })
1516 .to_string()
1517 .into()
1518 })
1519 .chain(iter::once("otherwise".into()))
1520 .collect()
1521 }),
1522 Call { destination: Some(_), cleanup: Some(_), .. } => {
1523 vec!["return".into(), "unwind".into()]
9cc50fc6 1524 }
416331ca
XL
1525 Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
1526 Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
1527 Call { destination: None, cleanup: None, .. } => vec![],
0bf4aa26
XL
1528 Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
1529 Yield { drop: None, .. } => vec!["resume".into()],
94b46f34 1530 DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
0bf4aa26 1531 vec!["return".into()]
94b46f34 1532 }
416331ca
XL
1533 DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => {
1534 vec!["return".into(), "unwind".into()]
3157f602
XL
1535 }
1536 Assert { cleanup: None, .. } => vec!["".into()],
0bf4aa26 1537 Assert { .. } => vec!["success".into(), "unwind".into()],
416331ca
XL
1538 FalseEdges { .. } => vec!["real".into(), "imaginary".into()],
1539 FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
2c00a5a8 1540 FalseUnwind { unwind: None, .. } => vec!["real".into()],
9cc50fc6
SL
1541 }
1542 }
e9174d1e
SL
1543}
1544
e9174d1e
SL
1545///////////////////////////////////////////////////////////////////////////
1546// Statements
1547
532ac7d7 1548#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
b039eaaf 1549pub struct Statement<'tcx> {
3157f602 1550 pub source_info: SourceInfo,
b039eaaf 1551 pub kind: StatementKind<'tcx>,
e9174d1e
SL
1552}
1553
a1dfa0c6
XL
1554// `Statement` is used a lot. Make sure it doesn't unintentionally get bigger.
1555#[cfg(target_arch = "x86_64")]
48663c56 1556static_assert_size!(Statement<'_>, 56);
a1dfa0c6 1557
9e0c209e
SL
1558impl<'tcx> Statement<'tcx> {
1559 /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
1560 /// invalidating statement indices in `Location`s.
1561 pub fn make_nop(&mut self) {
1562 self.kind = StatementKind::Nop
1563 }
0531ce1d
XL
1564
1565 /// Changes a statement to a nop and returns the original statement.
1566 pub fn replace_nop(&mut self) -> Self {
1567 Statement {
1568 source_info: self.source_info,
94b46f34 1569 kind: mem::replace(&mut self.kind, StatementKind::Nop),
0531ce1d
XL
1570 }
1571 }
9e0c209e
SL
1572}
1573
532ac7d7 1574#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
b039eaaf 1575pub enum StatementKind<'tcx> {
ff7c6d11 1576 /// Write the RHS Rvalue to the LHS Place.
0bf4aa26 1577 Assign(Place<'tcx>, Box<Rvalue<'tcx>>),
5bcae85e 1578
94b46f34 1579 /// This represents all the reading that a pattern match may do
0731742a 1580 /// (e.g., inspecting constants and discriminant values), and the
0bf4aa26
XL
1581 /// kind of pattern it comes from. This is in order to adapt potential
1582 /// error messages to these specific patterns.
0731742a
XL
1583 ///
1584 /// Note that this also is emitted for regular `let` bindings to ensure that locals that are
9fa01778 1585 /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
0bf4aa26 1586 FakeRead(FakeReadCause, Place<'tcx>),
94b46f34 1587
ff7c6d11 1588 /// Write the discriminant for a variant to the enum Place.
416331ca 1589 SetDiscriminant { place: Place<'tcx>, variant_index: VariantIdx },
5bcae85e
SL
1590
1591 /// Start a live range for the storage of the local.
ea8adc8c 1592 StorageLive(Local),
5bcae85e
SL
1593
1594 /// End the current live range for the storage of the local.
ea8adc8c 1595 StorageDead(Local),
9e0c209e 1596
532ac7d7
XL
1597 /// Executes a piece of inline Assembly. Stored in a Box to keep the size
1598 /// of `StatementKind` low.
1599 InlineAsm(Box<InlineAsm<'tcx>>),
8bb4bdeb 1600
9fa01778 1601 /// Retag references in the given place, ensuring they got fresh tags. This is
a1dfa0c6
XL
1602 /// part of the Stacked Borrows model. These statements are currently only interpreted
1603 /// by miri and only generated when "-Z mir-emit-retag" is passed.
1604 /// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
1605 /// for more details.
0731742a 1606 Retag(RetagKind, Place<'tcx>),
041b39d2 1607
b7449926
XL
1608 /// Encodes a user's type ascription. These need to be preserved
1609 /// intact so that NLL can respect them. For example:
0531ce1d 1610 ///
b7449926 1611 /// let a: T = y;
0531ce1d 1612 ///
b7449926
XL
1613 /// The effect of this annotation is to relate the type `T_y` of the place `y`
1614 /// to the user-given type `T`. The effect depends on the specified variance:
0531ce1d 1615 ///
b7449926
XL
1616 /// - `Covariant` -- requires that `T_y <: T`
1617 /// - `Contravariant` -- requires that `T_y :> T`
1618 /// - `Invariant` -- requires that `T_y == T`
1619 /// - `Bivariant` -- no effect
532ac7d7 1620 AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection>),
0531ce1d 1621
9e0c209e
SL
1622 /// No-op. Useful for deleting instructions without affecting statement indices.
1623 Nop,
e9174d1e
SL
1624}
1625
0731742a 1626/// `RetagKind` describes what kind of retag is to be performed.
532ac7d7 1627#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, HashStable)]
0731742a
XL
1628pub enum RetagKind {
1629 /// The initial retag when entering a function
1630 FnEntry,
1631 /// Retag preparing for a two-phase borrow
1632 TwoPhase,
1633 /// Retagging raw pointers
1634 Raw,
1635 /// A "normal" retag
1636 Default,
1637}
1638
0bf4aa26 1639/// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists.
532ac7d7 1640#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
0bf4aa26 1641pub enum FakeReadCause {
9fa01778
XL
1642 /// Inject a fake read of the borrowed input at the end of each guards
1643 /// code.
0bf4aa26 1644 ///
9fa01778
XL
1645 /// This should ensure that you cannot change the variant for an enum while
1646 /// you are in the midst of matching on it.
0bf4aa26
XL
1647 ForMatchGuard,
1648
1649 /// `let x: !; match x {}` doesn't generate any read of x so we need to
1650 /// generate a read of x to check that it is initialized and safe.
1651 ForMatchedPlace,
1652
9fa01778
XL
1653 /// A fake read of the RefWithinGuard version of a bind-by-value variable
1654 /// in a match guard to ensure that it's value hasn't change by the time
1655 /// we create the OutsideGuard version.
1656 ForGuardBinding,
1657
0bf4aa26
XL
1658 /// Officially, the semantics of
1659 ///
1660 /// `let pattern = <expr>;`
1661 ///
1662 /// is that `<expr>` is evaluated into a temporary and then this temporary is
1663 /// into the pattern.
1664 ///
1665 /// However, if we see the simple pattern `let var = <expr>`, we optimize this to
1666 /// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable,
1667 /// but in some cases it can affect the borrow checker, as in #53695.
1668 /// Therefore, we insert a "fake read" here to ensure that we get
1669 /// appropriate errors.
1670 ForLet,
1671}
1672
532ac7d7
XL
1673#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
1674pub struct InlineAsm<'tcx> {
1675 pub asm: HirInlineAsm,
1676 pub outputs: Box<[Place<'tcx>]>,
1677 pub inputs: Box<[(Span, Operand<'tcx>)]>,
1678}
1679
b039eaaf 1680impl<'tcx> Debug for Statement<'tcx> {
0bf4aa26 1681 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
e9174d1e
SL
1682 use self::StatementKind::*;
1683 match self.kind {
ff7c6d11 1684 Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
0bf4aa26 1685 FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
416331ca
XL
1686 Retag(ref kind, ref place) => write!(
1687 fmt,
1688 "Retag({}{:?})",
1689 match kind {
1690 RetagKind::FnEntry => "[fn entry] ",
1691 RetagKind::TwoPhase => "[2phase] ",
1692 RetagKind::Raw => "[raw] ",
1693 RetagKind::Default => "",
1694 },
1695 place,
1696 ),
ff7c6d11
XL
1697 StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
1698 StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
416331ca
XL
1699 SetDiscriminant { ref place, variant_index } => {
1700 write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
1701 }
1702 InlineAsm(ref asm) => {
1703 write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs)
1704 }
b7449926
XL
1705 AscribeUserType(ref place, ref variance, ref c_ty) => {
1706 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
94b46f34 1707 }
9e0c209e 1708 Nop => write!(fmt, "nop"),
e9174d1e
SL
1709 }
1710 }
1711}
54a0048b 1712
e9174d1e 1713///////////////////////////////////////////////////////////////////////////
ff7c6d11 1714// Places
e9174d1e
SL
1715
1716/// A path to a value; something that can be evaluated without
1717/// changing or disturbing program state.
416331ca
XL
1718#[derive(
1719 Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
1720)]
1721pub struct Place<'tcx> {
1722 pub base: PlaceBase<'tcx>,
532ac7d7
XL
1723
1724 /// projection out of a place (access a field, deref a pointer, etc)
416331ca 1725 pub projection: Option<Box<Projection<'tcx>>>,
532ac7d7
XL
1726}
1727
416331ca
XL
1728#[derive(
1729 Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
1730)]
532ac7d7 1731pub enum PlaceBase<'tcx> {
c30ab7b3
SL
1732 /// local variable
1733 Local(Local),
e9174d1e
SL
1734
1735 /// static or static mut variable
8bb4bdeb 1736 Static(Box<Static<'tcx>>),
e9174d1e
SL
1737}
1738
532ac7d7 1739/// We store the normalized type to avoid requiring normalization when reading MIR
0bf4aa26 1740#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
8bb4bdeb 1741pub struct Static<'tcx> {
8bb4bdeb 1742 pub ty: Ty<'tcx>,
532ac7d7
XL
1743 pub kind: StaticKind,
1744}
1745
416331ca
XL
1746#[derive(
1747 Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable,
1748)]
532ac7d7
XL
1749pub enum StaticKind {
1750 Promoted(Promoted),
1751 Static(DefId),
8bb4bdeb
XL
1752}
1753
cc61c64b 1754impl_stable_hash_for!(struct Static<'tcx> {
532ac7d7
XL
1755 ty,
1756 kind
cc61c64b
XL
1757});
1758
dc9dc135 1759/// The `Projection` data structure defines things of the form `base.x`, `*b` or `b[index]`.
416331ca
XL
1760#[derive(
1761 Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
1762)]
dc9dc135 1763pub struct Projection<'tcx> {
416331ca 1764 pub base: Option<Box<Projection<'tcx>>>,
dc9dc135 1765 pub elem: PlaceElem<'tcx>,
416331ca 1766}
e9174d1e 1767
416331ca
XL
1768#[derive(
1769 Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
1770)]
532ac7d7 1771pub enum ProjectionElem<V, T> {
e9174d1e 1772 Deref,
3b2f2976 1773 Field(Field, T),
e9174d1e
SL
1774 Index(V),
1775
7453a54e
SL
1776 /// These indices are generated by slice patterns. Easiest to explain
1777 /// by example:
1778 ///
1779 /// ```
1780 /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
1781 /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
1782 /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
1783 /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true },
1784 /// ```
e9174d1e 1785 ConstantIndex {
7453a54e
SL
1786 /// index or -index (in Python terms), depending on from_end
1787 offset: u32,
1788 /// thing being indexed must be at least this long
1789 min_length: u32,
1790 /// counting backwards from end?
1791 from_end: bool,
e9174d1e
SL
1792 },
1793
3157f602
XL
1794 /// These indices are generated by slice patterns.
1795 ///
1796 /// slice[from:-to] in Python terms.
1797 Subslice {
1798 from: u32,
1799 to: u32,
1800 },
1801
7453a54e
SL
1802 /// "Downcast" to a variant of an ADT. Currently, we only introduce
1803 /// this for ADTs with more than one variant. It may be better to
1804 /// just introduce it always, or always for enums.
532ac7d7
XL
1805 ///
1806 /// The included Symbol is the name of the variant, used for printing MIR.
1807 Downcast(Option<Symbol>, VariantIdx),
e9174d1e
SL
1808}
1809
ff7c6d11 1810/// Alias for projections as they appear in places, where the base is a place
ea8adc8c 1811/// and the index is a local.
532ac7d7 1812pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
e9174d1e 1813
48663c56
XL
1814// At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
1815#[cfg(target_arch = "x86_64")]
1816static_assert_size!(PlaceElem<'_>, 16);
a1dfa0c6 1817
0bf4aa26
XL
1818/// Alias for projections as they appear in `UserTypeProjection`, where we
1819/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
532ac7d7 1820pub type ProjectionKind = ProjectionElem<(), ()>;
0bf4aa26 1821
b7449926
XL
1822newtype_index! {
1823 pub struct Field {
532ac7d7 1824 derive [HashStable]
b7449926
XL
1825 DEBUG_FORMAT = "field[{}]"
1826 }
1827}
e9174d1e 1828
416331ca
XL
1829#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1830pub struct PlaceRef<'a, 'tcx> {
1831 pub base: &'a PlaceBase<'tcx>,
1832 pub projection: &'a Option<Box<Projection<'tcx>>>,
1833}
1834
ff7c6d11 1835impl<'tcx> Place<'tcx> {
416331ca
XL
1836 pub const RETURN_PLACE: Place<'tcx> = Place {
1837 base: PlaceBase::Local(RETURN_PLACE),
1838 projection: None,
1839 };
532ac7d7 1840
ff7c6d11 1841 pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
7453a54e 1842 self.elem(ProjectionElem::Field(f, ty))
e9174d1e
SL
1843 }
1844
ff7c6d11 1845 pub fn deref(self) -> Place<'tcx> {
e9174d1e
SL
1846 self.elem(ProjectionElem::Deref)
1847 }
1848
a1dfa0c6 1849 pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
532ac7d7
XL
1850 self.elem(ProjectionElem::Downcast(
1851 Some(adt_def.variants[variant_index].ident.name),
416331ca
XL
1852 variant_index,
1853 ))
32a655c1
SL
1854 }
1855
48663c56
XL
1856 pub fn downcast_unnamed(self, variant_index: VariantIdx) -> Place<'tcx> {
1857 self.elem(ProjectionElem::Downcast(None, variant_index))
1858 }
1859
ff7c6d11 1860 pub fn index(self, index: Local) -> Place<'tcx> {
e9174d1e
SL
1861 self.elem(ProjectionElem::Index(index))
1862 }
1863
ff7c6d11 1864 pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
416331ca
XL
1865 Place {
1866 base: self.base,
1867 projection: Some(Box::new(Projection { base: self.projection, elem })),
1868 }
e9174d1e 1869 }
0bf4aa26 1870
9fa01778 1871 /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
0bf4aa26 1872 /// a single deref of a local.
9fa01778
XL
1873 //
1874 // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
dc9dc135 1875 pub fn local_or_deref_local(&self) -> Option<Local> {
0bf4aa26 1876 match self {
416331ca
XL
1877 Place {
1878 base: PlaceBase::Local(local),
1879 projection: None,
1880 } |
1881 Place {
1882 base: PlaceBase::Local(local),
1883 projection: Some(box Projection {
1884 base: None,
1885 elem: ProjectionElem::Deref,
1886 }),
1887 } => Some(*local),
0bf4aa26
XL
1888 _ => None,
1889 }
1890 }
1891
48663c56 1892 /// Recursively "iterates" over place components, generating a `PlaceBase` and
dc9dc135 1893 /// `Projections` list and invoking `op` with a `ProjectionsIter`.
48663c56
XL
1894 pub fn iterate<R>(
1895 &self,
dc9dc135 1896 op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
48663c56 1897 ) -> R {
416331ca 1898 Place::iterate_over(&self.base, &self.projection, op)
48663c56
XL
1899 }
1900
416331ca
XL
1901 pub fn iterate_over<R>(
1902 place_base: &PlaceBase<'tcx>,
1903 place_projection: &Option<Box<Projection<'tcx>>>,
dc9dc135 1904 op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
48663c56 1905 ) -> R {
416331ca
XL
1906 fn iterate_over2<'tcx, R>(
1907 place_base: &PlaceBase<'tcx>,
1908 place_projection: &Option<Box<Projection<'tcx>>>,
1909 next: &Projections<'_, 'tcx>,
1910 op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
1911 ) -> R {
1912 match place_projection {
1913 None => {
1914 op(place_base, next.iter())
1915 }
1916
1917 Some(interior) => {
1918 iterate_over2(
1919 place_base,
1920 &interior.base,
1921 &Projections::List {
1922 projection: interior,
1923 next,
1924 },
1925 op,
1926 )
1927 }
1928 }
1929 }
48663c56 1930
416331ca
XL
1931 iterate_over2(place_base, place_projection, &Projections::Empty, op)
1932 }
1933
1934 pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
1935 PlaceRef {
1936 base: &self.base,
1937 projection: &self.projection,
0bf4aa26
XL
1938 }
1939 }
e9174d1e
SL
1940}
1941
dc9dc135
XL
1942impl From<Local> for Place<'_> {
1943 fn from(local: Local) -> Self {
416331ca
XL
1944 Place {
1945 base: local.into(),
1946 projection: None,
1947 }
dc9dc135
XL
1948 }
1949}
1950
1951impl From<Local> for PlaceBase<'_> {
1952 fn from(local: Local) -> Self {
1953 PlaceBase::Local(local)
1954 }
1955}
1956
416331ca
XL
1957impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
1958 pub fn iterate<R>(
1959 &self,
1960 op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
1961 ) -> R {
1962 Place::iterate_over(self.base, self.projection, op)
1963 }
1964
1965 /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
1966 /// a single deref of a local.
1967 //
1968 // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
1969 pub fn local_or_deref_local(&self) -> Option<Local> {
1970 match self {
1971 PlaceRef {
1972 base: PlaceBase::Local(local),
1973 projection: None,
1974 } |
1975 PlaceRef {
1976 base: PlaceBase::Local(local),
1977 projection: Some(box Projection {
1978 base: None,
1979 elem: ProjectionElem::Deref,
1980 }),
1981 } => Some(*local),
1982 _ => None,
1983 }
1984 }
1985}
1986
48663c56
XL
1987/// A linked list of projections running up the stack; begins with the
1988/// innermost projection and extends to the outermost (e.g., `a.b.c`
1989/// would have the place `b` with a "next" pointer to `b.c`).
1990/// Created by `Place::iterate`.
1991///
1992/// N.B., this particular impl strategy is not the most obvious. It was
1993/// chosen because it makes a measurable difference to NLL
1994/// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot.
dc9dc135 1995pub enum Projections<'p, 'tcx> {
48663c56
XL
1996 Empty,
1997
416331ca 1998 List { projection: &'p Projection<'tcx>, next: &'p Projections<'p, 'tcx> },
48663c56
XL
1999}
2000
dc9dc135
XL
2001impl<'p, 'tcx> Projections<'p, 'tcx> {
2002 fn iter(&self) -> ProjectionsIter<'_, 'tcx> {
2003 ProjectionsIter { value: self }
48663c56
XL
2004 }
2005}
2006
dc9dc135
XL
2007impl<'p, 'tcx> IntoIterator for &'p Projections<'p, 'tcx> {
2008 type Item = &'p Projection<'tcx>;
2009 type IntoIter = ProjectionsIter<'p, 'tcx>;
48663c56 2010
dc9dc135 2011 /// Converts a list of `Projection` components into an iterator;
48663c56
XL
2012 /// this iterator yields up a never-ending stream of `Option<&Place>`.
2013 /// These begin with the "innermost" projection and then with each
2014 /// projection therefrom. So given a place like `a.b.c` it would
2015 /// yield up:
2016 ///
2017 /// ```notrust
2018 /// Some(`a`), Some(`a.b`), Some(`a.b.c`), None, None, ...
2019 /// ```
2020 fn into_iter(self) -> Self::IntoIter {
2021 self.iter()
2022 }
2023}
2024
dc9dc135 2025/// Iterator over components; see `Projections::iter` for more
48663c56
XL
2026/// information.
2027///
2028/// N.B., this is not a *true* Rust iterator -- the code above just
2029/// manually invokes `next`. This is because we (sometimes) want to
2030/// keep executing even after `None` has been returned.
dc9dc135
XL
2031pub struct ProjectionsIter<'p, 'tcx> {
2032 pub value: &'p Projections<'p, 'tcx>,
48663c56
XL
2033}
2034
dc9dc135
XL
2035impl<'p, 'tcx> Iterator for ProjectionsIter<'p, 'tcx> {
2036 type Item = &'p Projection<'tcx>;
48663c56
XL
2037
2038 fn next(&mut self) -> Option<Self::Item> {
dc9dc135 2039 if let &Projections::List { projection, next } = self.value {
48663c56
XL
2040 self.value = next;
2041 Some(projection)
2042 } else {
2043 None
2044 }
2045 }
2046}
2047
dc9dc135 2048impl<'p, 'tcx> FusedIterator for ProjectionsIter<'p, 'tcx> {}
48663c56 2049
ff7c6d11 2050impl<'tcx> Debug for Place<'tcx> {
0bf4aa26 2051 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
48663c56
XL
2052 self.iterate(|_place_base, place_projections| {
2053 // FIXME: remove this collect once we have migrated to slices
2054 let projs_vec: Vec<_> = place_projections.collect();
2055 for projection in projs_vec.iter().rev() {
2056 match projection.elem {
416331ca 2057 ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
48663c56
XL
2058 write!(fmt, "(").unwrap();
2059 }
2060 ProjectionElem::Deref => {
2061 write!(fmt, "(*").unwrap();
2062 }
416331ca
XL
2063 ProjectionElem::Index(_)
2064 | ProjectionElem::ConstantIndex { .. }
2065 | ProjectionElem::Subslice { .. } => {}
94b46f34 2066 }
48663c56
XL
2067 }
2068 });
2069
2070 self.iterate(|place_base, place_projections| {
dc9dc135 2071 write!(fmt, "{:?}", place_base)?;
48663c56
XL
2072
2073 for projection in place_projections {
2074 match projection.elem {
2075 ProjectionElem::Downcast(Some(name), _index) => {
2076 write!(fmt, " as {})", name)?;
2077 }
2078 ProjectionElem::Downcast(None, index) => {
2079 write!(fmt, " as variant#{:?})", index)?;
2080 }
2081 ProjectionElem::Deref => {
2082 write!(fmt, ")")?;
2083 }
2084 ProjectionElem::Field(field, ty) => {
2085 write!(fmt, ".{:?}: {:?})", field.index(), ty)?;
2086 }
2087 ProjectionElem::Index(ref index) => {
2088 write!(fmt, "[{:?}]", index)?;
2089 }
416331ca 2090 ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => {
48663c56
XL
2091 write!(fmt, "[{:?} of {:?}]", offset, min_length)?;
2092 }
416331ca 2093 ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
48663c56
XL
2094 write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
2095 }
2096 ProjectionElem::Subslice { from, to } if to == 0 => {
2097 write!(fmt, "[{:?}:]", from)?;
2098 }
2099 ProjectionElem::Subslice { from, to } if from == 0 => {
2100 write!(fmt, "[:-{:?}]", to)?;
2101 }
2102 ProjectionElem::Subslice { from, to } => {
2103 write!(fmt, "[{:?}:-{:?}]", from, to)?;
2104 }
94b46f34 2105 }
48663c56
XL
2106 }
2107
2108 Ok(())
2109 })
e9174d1e
SL
2110 }
2111}
2112
dc9dc135
XL
2113impl Debug for PlaceBase<'_> {
2114 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
2115 match *self {
2116 PlaceBase::Local(id) => write!(fmt, "{:?}", id),
2117 PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) }) => {
416331ca
XL
2118 write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.def_path_str(def_id)), ty)
2119 }
dc9dc135 2120 PlaceBase::Static(box self::Static { ty, kind: StaticKind::Promoted(promoted) }) => {
416331ca
XL
2121 write!(fmt, "({:?}: {:?})", promoted, ty)
2122 }
dc9dc135
XL
2123 }
2124 }
2125}
2126
54a0048b
SL
2127///////////////////////////////////////////////////////////////////////////
2128// Scopes
2129
b7449926
XL
2130newtype_index! {
2131 pub struct SourceScope {
532ac7d7 2132 derive [HashStable]
abe05a73 2133 DEBUG_FORMAT = "scope[{}]",
94b46f34 2134 const OUTERMOST_SOURCE_SCOPE = 0,
b7449926
XL
2135 }
2136}
54a0048b 2137
532ac7d7 2138#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
94b46f34 2139pub struct SourceScopeData {
a7813a04 2140 pub span: Span,
94b46f34
XL
2141 pub parent_scope: Option<SourceScope>,
2142}
2143
532ac7d7 2144#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
94b46f34 2145pub struct SourceScopeLocalData {
532ac7d7
XL
2146 /// A HirId with lint levels equivalent to this scope's lint levels.
2147 pub lint_root: hir::HirId,
94b46f34
XL
2148 /// The unsafe block that contains this node.
2149 pub safety: Safety,
54a0048b
SL
2150}
2151
e9174d1e
SL
2152///////////////////////////////////////////////////////////////////////////
2153// Operands
54a0048b 2154
0bf4aa26
XL
2155/// These are values that can appear inside an rvalue. They are intentionally
2156/// limited to prevent rvalues from being nested in one another.
532ac7d7 2157#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
b039eaaf 2158pub enum Operand<'tcx> {
ff7c6d11
XL
2159 /// Copy: The value must be available for use afterwards.
2160 ///
2161 /// This implies that the type of the place must be `Copy`; this is true
2162 /// by construction during build, but also checked by the MIR type checker.
2163 Copy(Place<'tcx>),
b7449926 2164
ff7c6d11
XL
2165 /// Move: The value (including old borrows of it) will not be used again.
2166 ///
2167 /// Safe for values of all types (modulo future developments towards `?Move`).
2168 /// Correct usage patterns are enforced by the borrow checker for safe code.
2169 /// `Copy` may be converted to `Move` to enable "last-use" optimizations.
2170 Move(Place<'tcx>),
b7449926
XL
2171
2172 /// Synthesizes a constant value.
cc61c64b 2173 Constant(Box<Constant<'tcx>>),
e9174d1e
SL
2174}
2175
b039eaaf 2176impl<'tcx> Debug for Operand<'tcx> {
0bf4aa26 2177 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
e9174d1e
SL
2178 use self::Operand::*;
2179 match *self {
2180 Constant(ref a) => write!(fmt, "{:?}", a),
ff7c6d11
XL
2181 Copy(ref place) => write!(fmt, "{:?}", place),
2182 Move(ref place) => write!(fmt, "move {:?}", place),
e9174d1e
SL
2183 }
2184 }
2185}
2186
cc61c64b 2187impl<'tcx> Operand<'tcx> {
b7449926 2188 /// Convenience helper to make a constant that refers to the fn
9fa01778 2189 /// with given `DefId` and substs. Since this is used to synthesize
b7449926 2190 /// MIR, assumes `user_ty` is None.
dc9dc135
XL
2191 pub fn function_handle(
2192 tcx: TyCtxt<'tcx>,
cc61c64b 2193 def_id: DefId,
532ac7d7 2194 substs: SubstsRef<'tcx>,
cc61c64b
XL
2195 span: Span,
2196 ) -> Self {
ea8adc8c 2197 let ty = tcx.type_of(def_id).subst(tcx, substs);
cc61c64b 2198 Operand::Constant(box Constant {
041b39d2 2199 span,
ea8adc8c 2200 ty,
b7449926 2201 user_ty: None,
dc9dc135 2202 literal: ty::Const::zero_sized(tcx, ty),
cc61c64b
XL
2203 })
2204 }
2205
ff7c6d11
XL
2206 pub fn to_copy(&self) -> Self {
2207 match *self {
2208 Operand::Copy(_) | Operand::Constant(_) => self.clone(),
94b46f34 2209 Operand::Move(ref place) => Operand::Copy(place.clone()),
ff7c6d11
XL
2210 }
2211 }
cc61c64b
XL
2212}
2213
e9174d1e 2214///////////////////////////////////////////////////////////////////////////
7453a54e 2215/// Rvalues
e9174d1e 2216
532ac7d7 2217#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
b039eaaf 2218pub enum Rvalue<'tcx> {
7453a54e 2219 /// x (either a move or copy, depending on type of x)
b039eaaf 2220 Use(Operand<'tcx>),
e9174d1e 2221
7453a54e 2222 /// [x; 32]
0531ce1d 2223 Repeat(Operand<'tcx>, u64),
e9174d1e 2224
7453a54e 2225 /// &x or &mut x
ff7c6d11 2226 Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
e9174d1e 2227
7453a54e 2228 /// length of a [X] or [X;n] value
ff7c6d11 2229 Len(Place<'tcx>),
e9174d1e 2230
b039eaaf 2231 Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
e9174d1e 2232
b039eaaf 2233 BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
3157f602 2234 CheckedBinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
e9174d1e 2235
7cac9316 2236 NullaryOp(NullOp, Ty<'tcx>),
b039eaaf 2237 UnaryOp(UnOp, Operand<'tcx>),
e9174d1e 2238
8bb4bdeb
XL
2239 /// Read the discriminant of an ADT.
2240 ///
0731742a 2241 /// Undefined (i.e., no effort is made to make it defined, but there’s no reason why it cannot
8bb4bdeb 2242 /// be defined to return, say, a 0) if ADT is not an enum.
ff7c6d11 2243 Discriminant(Place<'tcx>),
8bb4bdeb 2244
9fa01778 2245 /// Creates an aggregate value, like a tuple or struct. This is
7453a54e
SL
2246 /// only needed because we want to distinguish `dest = Foo { x:
2247 /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
2248 /// that `Foo` has a destructor. These rvalues can be optimized
2249 /// away after type-checking and before lowering.
cc61c64b 2250 Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
e9174d1e
SL
2251}
2252
532ac7d7 2253#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
e9174d1e
SL
2254pub enum CastKind {
2255 Misc,
48663c56 2256 Pointer(PointerCast),
e9174d1e
SL
2257}
2258
532ac7d7 2259#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
b039eaaf 2260pub enum AggregateKind<'tcx> {
8bb4bdeb
XL
2261 /// The type is of the element
2262 Array(Ty<'tcx>),
e9174d1e 2263 Tuple,
ff7c6d11 2264
2c00a5a8
XL
2265 /// The second field is the variant index. It's equal to 0 for struct
2266 /// and union expressions. The fourth field is
ff7c6d11 2267 /// active field number and is present only for union expressions
0731742a 2268 /// -- e.g., for a union expression `SomeUnion { c: .. }`, the
ff7c6d11 2269 /// active field index would identity the field `c`
416331ca 2270 Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
ff7c6d11 2271
a7813a04 2272 Closure(DefId, ClosureSubsts<'tcx>),
94b46f34 2273 Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
e9174d1e
SL
2274}
2275
532ac7d7 2276#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
e9174d1e
SL
2277pub enum BinOp {
2278 /// The `+` operator (addition)
2279 Add,
2280 /// The `-` operator (subtraction)
2281 Sub,
2282 /// The `*` operator (multiplication)
2283 Mul,
2284 /// The `/` operator (division)
2285 Div,
2286 /// The `%` operator (modulus)
2287 Rem,
2288 /// The `^` operator (bitwise xor)
2289 BitXor,
2290 /// The `&` operator (bitwise and)
2291 BitAnd,
2292 /// The `|` operator (bitwise or)
2293 BitOr,
2294 /// The `<<` operator (shift left)
2295 Shl,
2296 /// The `>>` operator (shift right)
2297 Shr,
2298 /// The `==` operator (equality)
2299 Eq,
2300 /// The `<` operator (less than)
2301 Lt,
2302 /// The `<=` operator (less than or equal to)
2303 Le,
2304 /// The `!=` operator (not equal to)
2305 Ne,
2306 /// The `>=` operator (greater than or equal to)
2307 Ge,
2308 /// The `>` operator (greater than)
2309 Gt,
7cac9316
XL
2310 /// The `ptr.offset` operator
2311 Offset,
e9174d1e
SL
2312}
2313
3157f602
XL
2314impl BinOp {
2315 pub fn is_checkable(self) -> bool {
2316 use self::BinOp::*;
2317 match self {
2318 Add | Sub | Mul | Shl | Shr => true,
94b46f34 2319 _ => false,
3157f602
XL
2320 }
2321 }
2322}
2323
532ac7d7 2324#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
7cac9316 2325pub enum NullOp {
9fa01778 2326 /// Returns the size of a value of that type
7cac9316 2327 SizeOf,
9fa01778 2328 /// Creates a new uninitialized box for a value of that type
7cac9316
XL
2329 Box,
2330}
2331
532ac7d7 2332#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
e9174d1e
SL
2333pub enum UnOp {
2334 /// The `!` operator for logical inversion
2335 Not,
2336 /// The `-` operator for negation
b039eaaf 2337 Neg,
e9174d1e
SL
2338}
2339
b039eaaf 2340impl<'tcx> Debug for Rvalue<'tcx> {
0bf4aa26 2341 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
e9174d1e
SL
2342 use self::Rvalue::*;
2343
2344 match *self {
ff7c6d11 2345 Use(ref place) => write!(fmt, "{:?}", place),
e9174d1e 2346 Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b),
9cc50fc6 2347 Len(ref a) => write!(fmt, "Len({:?})", a),
ff7c6d11
XL
2348 Cast(ref kind, ref place, ref ty) => {
2349 write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind)
2350 }
9cc50fc6 2351 BinaryOp(ref op, ref a, ref b) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
3157f602
XL
2352 CheckedBinaryOp(ref op, ref a, ref b) => {
2353 write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
2354 }
e9174d1e 2355 UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
ff7c6d11 2356 Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
7cac9316 2357 NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
ff7c6d11 2358 Ref(region, borrow_kind, ref place) => {
9cc50fc6
SL
2359 let kind_str = match borrow_kind {
2360 BorrowKind::Shared => "",
0bf4aa26 2361 BorrowKind::Shallow => "shallow ",
2c00a5a8 2362 BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
9cc50fc6 2363 };
041b39d2 2364
3b2f2976 2365 // When printing regions, add trailing space if necessary.
532ac7d7
XL
2366 let print_region = ty::tls::with(|tcx| {
2367 tcx.sess.verbose() || tcx.sess.opts.debugging_opts.identify_regions
2368 });
2369 let region = if print_region {
8faf50e0 2370 let mut region = region.to_string();
94b46f34
XL
2371 if region.len() > 0 {
2372 region.push(' ');
2373 }
041b39d2
XL
2374 region
2375 } else {
3b2f2976 2376 // Do not even print 'static
b7449926 2377 String::new()
041b39d2 2378 };
ff7c6d11 2379 write!(fmt, "&{}{}{:?}", region, kind_str, place)
9cc50fc6
SL
2380 }
2381
ff7c6d11 2382 Aggregate(ref kind, ref places) => {
0bf4aa26 2383 fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result {
54a0048b 2384 let mut tuple_fmt = fmt.debug_tuple("");
ff7c6d11
XL
2385 for place in places {
2386 tuple_fmt.field(place);
9cc50fc6
SL
2387 }
2388 tuple_fmt.finish()
2389 }
2390
cc61c64b 2391 match **kind {
ff7c6d11 2392 AggregateKind::Array(_) => write!(fmt, "{:?}", places),
9cc50fc6 2393
94b46f34
XL
2394 AggregateKind::Tuple => match places.len() {
2395 0 => write!(fmt, "()"),
2396 1 => write!(fmt, "({:?},)", places[0]),
2397 _ => fmt_tuple(fmt, places),
2398 },
9cc50fc6 2399
b7449926 2400 AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => {
9cc50fc6 2401 let variant_def = &adt_def.variants[variant];
54a0048b 2402
532ac7d7
XL
2403 let f = &mut *fmt;
2404 ty::tls::with(|tcx| {
2405 let substs = tcx.lift(&substs).expect("could not lift for printing");
2406 FmtPrinter::new(tcx, f, Namespace::ValueNS)
2407 .print_def_path(variant_def.def_id, substs)?;
2408 Ok(())
2409 })?;
9cc50fc6 2410
c30ab7b3
SL
2411 match variant_def.ctor_kind {
2412 CtorKind::Const => Ok(()),
ff7c6d11 2413 CtorKind::Fn => fmt_tuple(fmt, places),
c30ab7b3 2414 CtorKind::Fictive => {
54a0048b 2415 let mut struct_fmt = fmt.debug_struct("");
ff7c6d11 2416 for (field, place) in variant_def.fields.iter().zip(places) {
94b46f34 2417 struct_fmt.field(&field.ident.as_str(), place);
9cc50fc6
SL
2418 }
2419 struct_fmt.finish()
2420 }
2421 }
2422 }
2423
c30ab7b3 2424 AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| {
532ac7d7 2425 if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
041b39d2 2426 let name = if tcx.sess.opts.debugging_opts.span_free_formats {
532ac7d7 2427 format!("[closure@{:?}]", hir_id)
041b39d2 2428 } else {
dc9dc135 2429 format!("[closure@{:?}]", tcx.hir().span(hir_id))
041b39d2 2430 };
9cc50fc6
SL
2431 let mut struct_fmt = fmt.debug_struct(&name);
2432
48663c56 2433 if let Some(upvars) = tcx.upvars(def_id) {
dc9dc135
XL
2434 for (&var_id, place) in upvars.keys().zip(places) {
2435 let var_name = tcx.hir().name(var_id);
ff7c6d11 2436 struct_fmt.field(&var_name.as_str(), place);
9cc50fc6 2437 }
48663c56 2438 }
9cc50fc6
SL
2439
2440 struct_fmt.finish()
2441 } else {
2442 write!(fmt, "[closure]")
2443 }
2444 }),
ea8adc8c
XL
2445
2446 AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
532ac7d7 2447 if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
416331ca 2448 let name = format!("[generator@{:?}]", tcx.hir().span(hir_id));
ea8adc8c
XL
2449 let mut struct_fmt = fmt.debug_struct(&name);
2450
48663c56 2451 if let Some(upvars) = tcx.upvars(def_id) {
dc9dc135
XL
2452 for (&var_id, place) in upvars.keys().zip(places) {
2453 let var_name = tcx.hir().name(var_id);
ff7c6d11 2454 struct_fmt.field(&var_name.as_str(), place);
ea8adc8c 2455 }
48663c56 2456 }
ea8adc8c
XL
2457
2458 struct_fmt.finish()
2459 } else {
2460 write!(fmt, "[generator]")
2461 }
2462 }),
9cc50fc6
SL
2463 }
2464 }
e9174d1e
SL
2465 }
2466 }
2467}
2468
2469///////////////////////////////////////////////////////////////////////////
7453a54e
SL
2470/// Constants
2471///
2472/// Two constants are equal if they are the same constant. Note that
2473/// this does not necessarily mean that they are "==" in Rust -- in
2474/// particular one must be wary of `NaN`!
e9174d1e 2475
532ac7d7 2476#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
b039eaaf
SL
2477pub struct Constant<'tcx> {
2478 pub span: Span,
2479 pub ty: Ty<'tcx>,
b7449926
XL
2480
2481 /// Optional user-given type: for something like
2482 /// `collect::<Vec<_>>`, this would be present and would
2483 /// indicate that `Vec<_>` was explicitly specified.
2484 ///
2485 /// Needed for NLL to impose user-given type constraints.
0731742a 2486 pub user_ty: Option<UserTypeAnnotationIndex>,
b7449926 2487
532ac7d7 2488 pub literal: &'tcx ty::Const<'tcx>,
0bf4aa26
XL
2489}
2490
2491/// A collection of projections into user types.
2492///
2493/// They are projections because a binding can occur a part of a
2494/// parent pattern that has been ascribed a type.
2495///
2496/// Its a collection because there can be multiple type ascriptions on
2497/// the path from the root of the pattern down to the binding itself.
2498///
2499/// An example:
2500///
2501/// ```rust
2502/// struct S<'a>((i32, &'a str), String);
2503/// let S((_, w): (i32, &'static str), _): S = ...;
2504/// // ------ ^^^^^^^^^^^^^^^^^^^ (1)
2505/// // --------------------------------- ^ (2)
2506/// ```
2507///
2508/// The highlights labelled `(1)` show the subpattern `(_, w)` being
2509/// ascribed the type `(i32, &'static str)`.
2510///
2511/// The highlights labelled `(2)` show the whole pattern being
2512/// ascribed the type `S`.
2513///
2514/// In this example, when we descend to `w`, we will have built up the
2515/// following two projected types:
2516///
2517/// * base: `S`, projection: `(base.0).1`
2518/// * base: `(i32, &'static str)`, projection: `base.1`
2519///
2520/// The first will lead to the constraint `w: &'1 str` (for some
2521/// inferred region `'1`). The second will lead to the constraint `w:
2522/// &'static str`.
532ac7d7
XL
2523#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
2524pub struct UserTypeProjections {
2525 pub(crate) contents: Vec<(UserTypeProjection, Span)>,
0bf4aa26
XL
2526}
2527
2528BraceStructTypeFoldableImpl! {
532ac7d7 2529 impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections {
0bf4aa26
XL
2530 contents
2531 }
2532}
2533
532ac7d7 2534impl<'tcx> UserTypeProjections {
0bf4aa26
XL
2535 pub fn none() -> Self {
2536 UserTypeProjections { contents: vec![] }
2537 }
2538
416331ca 2539 pub fn from_projections(projs: impl Iterator<Item = (UserTypeProjection, Span)>) -> Self {
0bf4aa26
XL
2540 UserTypeProjections { contents: projs.collect() }
2541 }
2542
416331ca 2543 pub fn projections_and_spans(&self) -> impl Iterator<Item = &(UserTypeProjection, Span)> {
0bf4aa26
XL
2544 self.contents.iter()
2545 }
2546
416331ca 2547 pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> {
0bf4aa26
XL
2548 self.contents.iter().map(|&(ref user_type, _span)| user_type)
2549 }
0731742a 2550
416331ca 2551 pub fn push_projection(mut self, user_ty: &UserTypeProjection, span: Span) -> Self {
0731742a
XL
2552 self.contents.push((user_ty.clone(), span));
2553 self
2554 }
2555
2556 fn map_projections(
2557 mut self,
416331ca 2558 mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
0731742a
XL
2559 ) -> Self {
2560 self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
2561 self
2562 }
2563
2564 pub fn index(self) -> Self {
2565 self.map_projections(|pat_ty_proj| pat_ty_proj.index())
2566 }
2567
2568 pub fn subslice(self, from: u32, to: u32) -> Self {
2569 self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
2570 }
2571
2572 pub fn deref(self) -> Self {
2573 self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
2574 }
2575
2576 pub fn leaf(self, field: Field) -> Self {
2577 self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
2578 }
2579
416331ca 2580 pub fn variant(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx, field: Field) -> Self {
0731742a
XL
2581 self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
2582 }
0bf4aa26
XL
2583}
2584
2585/// Encodes the effect of a user-supplied type annotation on the
2586/// subcomponents of a pattern. The effect is determined by applying the
2587/// given list of proejctions to some underlying base type. Often,
2588/// the projection element list `projs` is empty, in which case this
2589/// directly encodes a type in `base`. But in the case of complex patterns with
2590/// subpatterns and bindings, we want to apply only a *part* of the type to a variable,
2591/// in which case the `projs` vector is used.
2592///
2593/// Examples:
2594///
2595/// * `let x: T = ...` -- here, the `projs` vector is empty.
2596///
2597/// * `let (x, _): T = ...` -- here, the `projs` vector would contain
2598/// `field[0]` (aka `.0`), indicating that the type of `s` is
2599/// determined by finding the type of the `.0` field from `T`.
532ac7d7
XL
2600#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
2601pub struct UserTypeProjection {
0731742a 2602 pub base: UserTypeAnnotationIndex,
dc9dc135 2603 pub projs: Vec<ProjectionKind>,
0bf4aa26
XL
2604}
2605
416331ca 2606impl Copy for ProjectionKind {}
0bf4aa26 2607
532ac7d7 2608impl UserTypeProjection {
0731742a
XL
2609 pub(crate) fn index(mut self) -> Self {
2610 self.projs.push(ProjectionElem::Index(()));
2611 self
2612 }
2613
2614 pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
2615 self.projs.push(ProjectionElem::Subslice { from, to });
2616 self
2617 }
2618
2619 pub(crate) fn deref(mut self) -> Self {
2620 self.projs.push(ProjectionElem::Deref);
2621 self
2622 }
2623
2624 pub(crate) fn leaf(mut self, field: Field) -> Self {
2625 self.projs.push(ProjectionElem::Field(field, ()));
2626 self
2627 }
2628
2629 pub(crate) fn variant(
2630 mut self,
2631 adt_def: &'tcx AdtDef,
2632 variant_index: VariantIdx,
2633 field: Field,
2634 ) -> Self {
532ac7d7
XL
2635 self.projs.push(ProjectionElem::Downcast(
2636 Some(adt_def.variants[variant_index].ident.name),
416331ca
XL
2637 variant_index,
2638 ));
0731742a
XL
2639 self.projs.push(ProjectionElem::Field(field, ()));
2640 self
2641 }
2642}
2643
532ac7d7 2644CloneTypeFoldableAndLiftImpls! { ProjectionKind, }
0bf4aa26 2645
532ac7d7 2646impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
dc9dc135 2647 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
9fa01778 2648 use crate::mir::ProjectionElem::*;
0bf4aa26
XL
2649
2650 let base = self.base.fold_with(folder);
416331ca
XL
2651 let projs: Vec<_> = self
2652 .projs
0bf4aa26 2653 .iter()
416331ca
XL
2654 .map(|elem| match elem {
2655 Deref => Deref,
2656 Field(f, ()) => Field(f.clone(), ()),
2657 Index(()) => Index(()),
2658 elem => elem.clone(),
2659 })
0bf4aa26
XL
2660 .collect();
2661
2662 UserTypeProjection { base, projs }
2663 }
2664
2665 fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
2666 self.base.visit_with(visitor)
2667 // Note: there's nothing in `self.proj` to visit.
2668 }
2669}
2670
b7449926
XL
2671newtype_index! {
2672 pub struct Promoted {
532ac7d7 2673 derive [HashStable]
b7449926
XL
2674 DEBUG_FORMAT = "promoted[{}]"
2675 }
2676}
abe05a73 2677
9cc50fc6 2678impl<'tcx> Debug for Constant<'tcx> {
0bf4aa26 2679 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
dc9dc135 2680 write!(fmt, "{}", self)
9cc50fc6
SL
2681 }
2682}
2683
dc9dc135
XL
2684impl<'tcx> Display for Constant<'tcx> {
2685 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
2686 write!(fmt, "const ")?;
2687 write!(fmt, "{}", self.literal)
2688 }
9cc50fc6 2689}
3157f602 2690
dc9dc135 2691impl<'tcx> graph::DirectedGraph for Body<'tcx> {
3157f602 2692 type Node = BasicBlock;
8faf50e0 2693}
3157f602 2694
dc9dc135 2695impl<'tcx> graph::WithNumNodes for Body<'tcx> {
94b46f34
XL
2696 fn num_nodes(&self) -> usize {
2697 self.basic_blocks.len()
2698 }
8faf50e0 2699}
3157f602 2700
dc9dc135 2701impl<'tcx> graph::WithStartNode for Body<'tcx> {
94b46f34
XL
2702 fn start_node(&self) -> Self::Node {
2703 START_BLOCK
2704 }
8faf50e0 2705}
3157f602 2706
dc9dc135 2707impl<'tcx> graph::WithPredecessors for Body<'tcx> {
416331ca
XL
2708 fn predecessors(
2709 &self,
94b46f34 2710 node: Self::Node,
416331ca 2711 ) -> <Self as GraphPredecessors<'_>>::Iter {
3157f602
XL
2712 self.predecessors_for(node).clone().into_iter()
2713 }
8faf50e0
XL
2714}
2715
dc9dc135 2716impl<'tcx> graph::WithSuccessors for Body<'tcx> {
416331ca
XL
2717 fn successors(
2718 &self,
94b46f34 2719 node: Self::Node,
416331ca 2720 ) -> <Self as GraphSuccessors<'_>>::Iter {
83c7162d 2721 self.basic_blocks[node].terminator().successors().cloned()
3157f602
XL
2722 }
2723}
2724
dc9dc135 2725impl<'a, 'b> graph::GraphPredecessors<'b> for Body<'a> {
3157f602
XL
2726 type Item = BasicBlock;
2727 type Iter = IntoIter<BasicBlock>;
2728}
2729
dc9dc135 2730impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
3157f602 2731 type Item = BasicBlock;
83c7162d 2732 type Iter = iter::Cloned<Successors<'b>>;
3157f602 2733}
9e0c209e 2734
532ac7d7 2735#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
9e0c209e
SL
2736pub struct Location {
2737 /// the location is within this block
2738 pub block: BasicBlock,
2739
2c00a5a8 2740 /// the location is the start of the statement; or, if `statement_index`
9e0c209e
SL
2741 /// == num-statements, then the start of the terminator.
2742 pub statement_index: usize,
2743}
2744
2745impl fmt::Debug for Location {
0bf4aa26 2746 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
9e0c209e
SL
2747 write!(fmt, "{:?}[{}]", self.block, self.statement_index)
2748 }
2749}
2750
2751impl Location {
416331ca 2752 pub const START: Location = Location { block: START_BLOCK, statement_index: 0 };
83c7162d 2753
abe05a73
XL
2754 /// Returns the location immediately after this one within the enclosing block.
2755 ///
2756 /// Note that if this location represents a terminator, then the
2757 /// resulting location would be out of bounds and invalid.
2758 pub fn successor_within_block(&self) -> Location {
416331ca 2759 Location { block: self.block, statement_index: self.statement_index + 1 }
abe05a73
XL
2760 }
2761
a1dfa0c6 2762 /// Returns `true` if `other` is earlier in the control flow graph than `self`.
dc9dc135 2763 pub fn is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool {
a1dfa0c6
XL
2764 // If we are in the same block as the other location and are an earlier statement
2765 // then we are a predecessor of `other`.
2766 if self.block == other.block && self.statement_index < other.statement_index {
2767 return true;
2768 }
2769
2770 // If we're in another block, then we want to check that block is a predecessor of `other`.
dc9dc135 2771 let mut queue: Vec<BasicBlock> = body.predecessors_for(other.block).clone();
a1dfa0c6
XL
2772 let mut visited = FxHashSet::default();
2773
2774 while let Some(block) = queue.pop() {
2775 // If we haven't visited this block before, then make sure we visit it's predecessors.
2776 if visited.insert(block) {
dc9dc135 2777 queue.append(&mut body.predecessors_for(block).clone());
a1dfa0c6
XL
2778 } else {
2779 continue;
2780 }
2781
2782 // If we found the block that `self` is in, then we are a predecessor of `other` (since
2783 // we found that block by looking at the predecessors of `other`).
2784 if self.block == block {
2785 return true;
2786 }
2787 }
2788
2789 false
2790 }
2791
83c7162d 2792 pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
9e0c209e
SL
2793 if self.block == other.block {
2794 self.statement_index <= other.statement_index
2795 } else {
2796 dominators.is_dominated_by(other.block, self.block)
2797 }
2798 }
2799}
8bb4bdeb 2800
532ac7d7 2801#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
ff7c6d11
XL
2802pub enum UnsafetyViolationKind {
2803 General,
9fa01778 2804 /// Permitted in const fn and regular fns.
0731742a 2805 GeneralAndConstFn,
532ac7d7
XL
2806 ExternStatic(hir::HirId),
2807 BorrowPacked(hir::HirId),
ff7c6d11
XL
2808}
2809
532ac7d7 2810#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
ea8adc8c
XL
2811pub struct UnsafetyViolation {
2812 pub source_info: SourceInfo,
ff7c6d11 2813 pub description: InternedString,
8faf50e0 2814 pub details: InternedString,
ff7c6d11 2815 pub kind: UnsafetyViolationKind,
ea8adc8c
XL
2816}
2817
532ac7d7 2818#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
ea8adc8c
XL
2819pub struct UnsafetyCheckResult {
2820 /// Violations that are propagated *upwards* from this function
0531ce1d 2821 pub violations: Lrc<[UnsafetyViolation]>,
ea8adc8c
XL
2822 /// unsafe blocks in this function, along with whether they are used. This is
2823 /// used for the "unused_unsafe" lint.
532ac7d7 2824 pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
ea8adc8c
XL
2825}
2826
48663c56
XL
2827newtype_index! {
2828 pub struct GeneratorSavedLocal {
2829 derive [HashStable]
2830 DEBUG_FORMAT = "_{}",
2831 }
2832}
2833
ea8adc8c 2834/// The layout of generator state
532ac7d7 2835#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
ea8adc8c 2836pub struct GeneratorLayout<'tcx> {
48663c56
XL
2837 /// The type of every local stored inside the generator.
2838 pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
2839
2840 /// Which of the above fields are in each variant. Note that one field may
2841 /// be stored in multiple variants.
2842 pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
2843
dc9dc135
XL
2844 /// Which saved locals are storage-live at the same time. Locals that do not
2845 /// have conflicts with each other are allowed to overlap in the computed
2846 /// layout.
2847 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
2848
48663c56
XL
2849 /// Names and scopes of all the stored generator locals.
2850 /// NOTE(tmandry) This is *strictly* a temporary hack for codegen
2851 /// debuginfo generation, and will be removed at some point.
2852 /// Do **NOT** use it for anything else, local information should not be
2853 /// in the MIR, please rely on local crate HIR or other side-channels.
2854 pub __local_debuginfo_codegen_only_do_not_use: IndexVec<GeneratorSavedLocal, LocalDecl<'tcx>>,
ea8adc8c 2855}
8bb4bdeb 2856
532ac7d7 2857#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
dc9dc135
XL
2858pub struct BorrowCheckResult<'tcx> {
2859 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
83c7162d
XL
2860 pub used_mut_upvars: SmallVec<[Field; 8]>,
2861}
2862
ff7c6d11
XL
2863/// After we borrow check a closure, we are left with various
2864/// requirements that we have inferred between the free regions that
9fa01778 2865/// appear in the closure's signature or on its field types. These
ff7c6d11
XL
2866/// requirements are then verified and proved by the closure's
2867/// creating function. This struct encodes those requirements.
2868///
2869/// The requirements are listed as being between various
2870/// `RegionVid`. The 0th region refers to `'static`; subsequent region
2871/// vids refer to the free regions that appear in the closure (or
2872/// generator's) type, in order of appearance. (This numbering is
2873/// actually defined by the `UniversalRegions` struct in the NLL
2874/// region checker. See for example
2875/// `UniversalRegions::closure_mapping`.) Note that we treat the free
2876/// regions in the closure's type "as if" they were erased, so their
2877/// precise identity is not important, only their position.
2878///
2879/// Example: If type check produces a closure with the closure substs:
2880///
2881/// ```text
2882/// ClosureSubsts = [
2883/// i8, // the "closure kind"
2884/// for<'x> fn(&'a &'x u32) -> &'x u32, // the "closure signature"
2885/// &'a String, // some upvar
2886/// ]
2887/// ```
2888///
2889/// here, there is one unique free region (`'a`) but it appears
0531ce1d 2890/// twice. We would "renumber" each occurrence to a unique vid, as follows:
ff7c6d11
XL
2891///
2892/// ```text
2893/// ClosureSubsts = [
2894/// i8, // the "closure kind"
2895/// for<'x> fn(&'1 &'x u32) -> &'x u32, // the "closure signature"
2896/// &'2 String, // some upvar
2897/// ]
2898/// ```
2899///
2900/// Now the code might impose a requirement like `'1: '2`. When an
2901/// instance of the closure is created, the corresponding free regions
2902/// can be extracted from its type and constrained to have the given
2903/// outlives relationship.
2904///
2905/// In some cases, we have to record outlives requirements between
2906/// types and regions as well. In that case, if those types include
2907/// any regions, those regions are recorded as `ReClosureBound`
2908/// instances assigned one of these same indices. Those regions will
2909/// be substituted away by the creator. We use `ReClosureBound` in
2910/// that case because the regions must be allocated in the global
2911/// TyCtxt, and hence we cannot use `ReVar` (which is what we use
2912/// internally within the rest of the NLL code).
532ac7d7 2913#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
dc9dc135 2914pub struct ClosureRegionRequirements<'tcx> {
9fa01778 2915 /// The number of external regions defined on the closure. In our
ff7c6d11
XL
2916 /// example above, it would be 3 -- one for `'static`, then `'1`
2917 /// and `'2`. This is just used for a sanity check later on, to
2918 /// make sure that the number of regions we see at the callsite
2919 /// matches.
2920 pub num_external_vids: usize,
2921
2922 /// Requirements between the various free regions defined in
2923 /// indices.
dc9dc135 2924 pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
ff7c6d11
XL
2925}
2926
2927/// Indicates an outlives constraint between a type or between two
2928/// free-regions declared on the closure.
532ac7d7 2929#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
ff7c6d11
XL
2930pub struct ClosureOutlivesRequirement<'tcx> {
2931 // This region or type ...
2932 pub subject: ClosureOutlivesSubject<'tcx>,
2933
0bf4aa26 2934 // ... must outlive this one.
ff7c6d11
XL
2935 pub outlived_free_region: ty::RegionVid,
2936
0bf4aa26 2937 // If not, report an error here ...
ff7c6d11 2938 pub blame_span: Span,
0bf4aa26
XL
2939
2940 // ... due to this reason.
2941 pub category: ConstraintCategory,
2942}
2943
2944/// Outlives constraints can be categorized to determine whether and why they
2945/// are interesting (for error reporting). Order of variants indicates sort
2946/// order of the category, thereby influencing diagnostic output.
2947///
2948/// See also [rustc_mir::borrow_check::nll::constraints]
416331ca
XL
2949#[derive(
2950 Copy,
2951 Clone,
2952 Debug,
2953 Eq,
2954 PartialEq,
2955 PartialOrd,
2956 Ord,
2957 Hash,
2958 RustcEncodable,
2959 RustcDecodable,
2960 HashStable,
2961)]
0bf4aa26
XL
2962pub enum ConstraintCategory {
2963 Return,
0731742a 2964 Yield,
0bf4aa26
XL
2965 UseAsConst,
2966 UseAsStatic,
2967 TypeAnnotation,
2968 Cast,
2969
2970 /// A constraint that came from checking the body of a closure.
2971 ///
2972 /// We try to get the category that the closure used when reporting this.
2973 ClosureBounds,
2974 CallArgument,
2975 CopyBound,
2976 SizedBound,
2977 Assignment,
2978 OpaqueType,
2979
2980 /// A "boring" constraint (caused by the given location) is one that
2981 /// the user probably doesn't want to see described in diagnostics,
2982 /// because it is kind of an artifact of the type system setup.
2983 /// Example: `x = Foo { field: y }` technically creates
2984 /// intermediate regions representing the "type of `Foo { field: y
2985 /// }`", and data flows from `y` into those variables, but they
2986 /// are not very interesting. The assignment into `x` on the other
2987 /// hand might be.
2988 Boring,
2989 // Boring and applicable everywhere.
2990 BoringNoLocation,
2991
2992 /// A constraint that doesn't correspond to anything the user sees.
2993 Internal,
ff7c6d11
XL
2994}
2995
2996/// The subject of a ClosureOutlivesRequirement -- that is, the thing
2997/// that must outlive some region.
532ac7d7 2998#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
ff7c6d11
XL
2999pub enum ClosureOutlivesSubject<'tcx> {
3000 /// Subject is a type, typically a type parameter, but could also
3001 /// be a projection. Indicates a requirement like `T: 'a` being
3002 /// passed to the caller, where the type here is `T`.
3003 ///
3004 /// The type here is guaranteed not to contain any free regions at
3005 /// present.
3006 Ty(Ty<'tcx>),
3007
3008 /// Subject is a free region from the closure. Indicates a requirement
3009 /// like `'a: 'b` being passed to the caller; the region here is `'a`.
3010 Region(ty::RegionVid),
3011}
3012
8bb4bdeb
XL
3013/*
3014 * TypeFoldable implementations for MIR types
dc9dc135 3015*/
8bb4bdeb 3016
0531ce1d 3017CloneTypeFoldableAndLiftImpls! {
0bf4aa26 3018 BlockTailInfo,
a1dfa0c6 3019 MirPhase,
0531ce1d
XL
3020 Mutability,
3021 SourceInfo,
48663c56 3022 UpvarDebuginfo,
0bf4aa26 3023 FakeReadCause,
0731742a 3024 RetagKind,
94b46f34
XL
3025 SourceScope,
3026 SourceScopeData,
3027 SourceScopeLocalData,
0731742a 3028 UserTypeAnnotationIndex,
8bb4bdeb
XL
3029}
3030
0531ce1d 3031BraceStructTypeFoldableImpl! {
dc9dc135 3032 impl<'tcx> TypeFoldable<'tcx> for Body<'tcx> {
a1dfa0c6 3033 phase,
0531ce1d 3034 basic_blocks,
94b46f34
XL
3035 source_scopes,
3036 source_scope_local_data,
0531ce1d
XL
3037 promoted,
3038 yield_ty,
3039 generator_drop,
3040 generator_layout,
3041 local_decls,
0731742a 3042 user_type_annotations,
0531ce1d 3043 arg_count,
48663c56 3044 __upvar_debuginfo_codegen_only_do_not_use,
0531ce1d 3045 spread_arg,
0731742a 3046 control_flow_destroyed,
0531ce1d
XL
3047 span,
3048 cache,
ea8adc8c
XL
3049 }
3050}
3051
0531ce1d
XL
3052BraceStructTypeFoldableImpl! {
3053 impl<'tcx> TypeFoldable<'tcx> for GeneratorLayout<'tcx> {
48663c56
XL
3054 field_tys,
3055 variant_fields,
dc9dc135 3056 storage_conflicts,
48663c56 3057 __local_debuginfo_codegen_only_do_not_use,
8bb4bdeb
XL
3058 }
3059}
3060
0531ce1d
XL
3061BraceStructTypeFoldableImpl! {
3062 impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> {
3063 mutability,
3064 is_user_variable,
3065 internal,
3066 ty,
b7449926 3067 user_ty,
0531ce1d
XL
3068 name,
3069 source_info,
0bf4aa26 3070 is_block_tail,
94b46f34 3071 visibility_scope,
8bb4bdeb 3072 }
0531ce1d 3073}
8bb4bdeb 3074
0531ce1d
XL
3075BraceStructTypeFoldableImpl! {
3076 impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> {
3077 statements,
3078 terminator,
3079 is_cleanup,
8bb4bdeb
XL
3080 }
3081}
3082
0531ce1d
XL
3083BraceStructTypeFoldableImpl! {
3084 impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
3085 source_info, kind
3b2f2976
XL
3086 }
3087}
3088
0531ce1d
XL
3089EnumTypeFoldableImpl! {
3090 impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> {
3091 (StatementKind::Assign)(a, b),
0bf4aa26 3092 (StatementKind::FakeRead)(cause, place),
0531ce1d
XL
3093 (StatementKind::SetDiscriminant) { place, variant_index },
3094 (StatementKind::StorageLive)(a),
3095 (StatementKind::StorageDead)(a),
532ac7d7 3096 (StatementKind::InlineAsm)(a),
0731742a 3097 (StatementKind::Retag)(kind, place),
b7449926 3098 (StatementKind::AscribeUserType)(a, v, b),
0531ce1d 3099 (StatementKind::Nop),
8bb4bdeb 3100 }
0531ce1d 3101}
8bb4bdeb 3102
532ac7d7
XL
3103BraceStructTypeFoldableImpl! {
3104 impl<'tcx> TypeFoldable<'tcx> for InlineAsm<'tcx> {
3105 asm,
3106 outputs,
3107 inputs,
3108 }
3109}
3110
0531ce1d
XL
3111EnumTypeFoldableImpl! {
3112 impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate<T> {
3113 (ClearCrossCrate::Clear),
3114 (ClearCrossCrate::Set)(a),
3115 } where T: TypeFoldable<'tcx>
8bb4bdeb
XL
3116}
3117
3118impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
dc9dc135 3119 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
9fa01778 3120 use crate::mir::TerminatorKind::*;
8bb4bdeb
XL
3121
3122 let kind = match self.kind {
a1dfa0c6 3123 Goto { target } => Goto { target },
416331ca 3124 SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
8bb4bdeb
XL
3125 discr: discr.fold_with(folder),
3126 switch_ty: switch_ty.fold_with(folder),
3127 values: values.clone(),
94b46f34 3128 targets: targets.clone(),
8bb4bdeb 3129 },
416331ca
XL
3130 Drop { ref location, target, unwind } => {
3131 Drop { location: location.fold_with(folder), target, unwind }
3132 }
3133 DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace {
8bb4bdeb
XL
3134 location: location.fold_with(folder),
3135 value: value.fold_with(folder),
041b39d2
XL
3136 target,
3137 unwind,
8bb4bdeb 3138 },
416331ca
XL
3139 Yield { ref value, resume, drop } => {
3140 Yield { value: value.fold_with(folder), resume: resume, drop: drop }
3141 }
3142 Call { ref func, ref args, ref destination, cleanup, from_hir_call } => {
3143 let dest =
3144 destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
8bb4bdeb
XL
3145
3146 Call {
3147 func: func.fold_with(folder),
3148 args: args.fold_with(folder),
3149 destination: dest,
041b39d2 3150 cleanup,
0bf4aa26 3151 from_hir_call,
8bb4bdeb 3152 }
94b46f34 3153 }
416331ca
XL
3154 Assert { ref cond, expected, ref msg, target, cleanup } => {
3155 use PanicInfo::*;
3156 let msg = match msg {
3157 BoundsCheck { ref len, ref index } =>
3158 BoundsCheck {
3159 len: len.fold_with(folder),
3160 index: index.fold_with(folder),
3161 },
3162 Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
3163 GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
3164 msg.clone(),
8bb4bdeb 3165 };
416331ca 3166 Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
94b46f34 3167 }
ea8adc8c 3168 GeneratorDrop => GeneratorDrop,
8bb4bdeb 3169 Resume => Resume,
ff7c6d11 3170 Abort => Abort,
8bb4bdeb
XL
3171 Return => Return,
3172 Unreachable => Unreachable,
416331ca
XL
3173 FalseEdges { real_target, imaginary_target } => {
3174 FalseEdges { real_target, imaginary_target }
3175 }
3176 FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
8bb4bdeb 3177 };
416331ca 3178 Terminator { source_info: self.source_info, kind }
8bb4bdeb
XL
3179 }
3180
3181 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
9fa01778 3182 use crate::mir::TerminatorKind::*;
8bb4bdeb
XL
3183
3184 match self.kind {
416331ca
XL
3185 SwitchInt { ref discr, switch_ty, .. } => {
3186 discr.visit_with(visitor) || switch_ty.visit_with(visitor)
3187 }
94b46f34 3188 Drop { ref location, .. } => location.visit_with(visitor),
416331ca
XL
3189 DropAndReplace { ref location, ref value, .. } => {
3190 location.visit_with(visitor) || value.visit_with(visitor)
3191 }
94b46f34 3192 Yield { ref value, .. } => value.visit_with(visitor),
416331ca 3193 Call { ref func, ref args, ref destination, .. } => {
8bb4bdeb
XL
3194 let dest = if let Some((ref loc, _)) = *destination {
3195 loc.visit_with(visitor)
94b46f34
XL
3196 } else {
3197 false
3198 };
8bb4bdeb 3199 dest || func.visit_with(visitor) || args.visit_with(visitor)
94b46f34 3200 }
416331ca 3201 Assert { ref cond, ref msg, .. } => {
8bb4bdeb 3202 if cond.visit_with(visitor) {
416331ca
XL
3203 use PanicInfo::*;
3204 match msg {
3205 BoundsCheck { ref len, ref index } =>
3206 len.visit_with(visitor) || index.visit_with(visitor),
3207 Panic { .. } | Overflow(_) | OverflowNeg |
3208 DivisionByZero | RemainderByZero |
3209 GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
3210 false
8bb4bdeb
XL
3211 }
3212 } else {
3213 false
3214 }
94b46f34
XL
3215 }
3216 Goto { .. }
3217 | Resume
3218 | Abort
3219 | Return
3220 | GeneratorDrop
3221 | Unreachable
3222 | FalseEdges { .. }
3223 | FalseUnwind { .. } => false,
8bb4bdeb
XL
3224 }
3225 }
3226}
3227
ff7c6d11 3228impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
dc9dc135 3229 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
416331ca
XL
3230 Place {
3231 base: self.base.clone(),
3232 projection: self.projection.fold_with(folder),
8bb4bdeb
XL
3233 }
3234 }
3235
3236 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
416331ca 3237 self.projection.visit_with(visitor)
8bb4bdeb
XL
3238 }
3239}
3240
3241impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
dc9dc135 3242 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
9fa01778 3243 use crate::mir::Rvalue::*;
8bb4bdeb
XL
3244 match *self {
3245 Use(ref op) => Use(op.fold_with(folder)),
3246 Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
94b46f34
XL
3247 Ref(region, bk, ref place) => {
3248 Ref(region.fold_with(folder), bk, place.fold_with(folder))
3249 }
ff7c6d11 3250 Len(ref place) => Len(place.fold_with(folder)),
8bb4bdeb 3251 Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
94b46f34
XL
3252 BinaryOp(op, ref rhs, ref lhs) => {
3253 BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
3254 }
3255 CheckedBinaryOp(op, ref rhs, ref lhs) => {
3256 CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
3257 }
8bb4bdeb 3258 UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
ff7c6d11 3259 Discriminant(ref place) => Discriminant(place.fold_with(folder)),
7cac9316 3260 NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
8bb4bdeb 3261 Aggregate(ref kind, ref fields) => {
cc61c64b 3262 let kind = box match **kind {
8bb4bdeb
XL
3263 AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
3264 AggregateKind::Tuple => AggregateKind::Tuple,
b7449926
XL
3265 AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
3266 def,
3267 v,
3268 substs.fold_with(folder),
3269 user_ty.fold_with(folder),
3270 n,
3271 ),
94b46f34
XL
3272 AggregateKind::Closure(id, substs) => {
3273 AggregateKind::Closure(id, substs.fold_with(folder))
3274 }
3275 AggregateKind::Generator(id, substs, movablity) => {
3276 AggregateKind::Generator(id, substs.fold_with(folder), movablity)
3277 }
8bb4bdeb
XL
3278 };
3279 Aggregate(kind, fields.fold_with(folder))
3280 }
3281 }
3282 }
3283
3284 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
9fa01778 3285 use crate::mir::Rvalue::*;
8bb4bdeb
XL
3286 match *self {
3287 Use(ref op) => op.visit_with(visitor),
3288 Repeat(ref op, _) => op.visit_with(visitor),
ff7c6d11
XL
3289 Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
3290 Len(ref place) => place.visit_with(visitor),
8bb4bdeb 3291 Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
94b46f34
XL
3292 BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
3293 rhs.visit_with(visitor) || lhs.visit_with(visitor)
3294 }
8bb4bdeb 3295 UnaryOp(_, ref val) => val.visit_with(visitor),
ff7c6d11 3296 Discriminant(ref place) => place.visit_with(visitor),
7cac9316 3297 NullaryOp(_, ty) => ty.visit_with(visitor),
8bb4bdeb 3298 Aggregate(ref kind, ref fields) => {
cc61c64b 3299 (match **kind {
8bb4bdeb
XL
3300 AggregateKind::Array(ty) => ty.visit_with(visitor),
3301 AggregateKind::Tuple => false,
b7449926
XL
3302 AggregateKind::Adt(_, _, substs, user_ty, _) => {
3303 substs.visit_with(visitor) || user_ty.visit_with(visitor)
3304 }
ea8adc8c 3305 AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
94b46f34 3306 AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
8bb4bdeb
XL
3307 }) || fields.visit_with(visitor)
3308 }
3309 }
3310 }
3311}
3312
3313impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
dc9dc135 3314 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
8bb4bdeb 3315 match *self {
ff7c6d11
XL
3316 Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
3317 Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
8bb4bdeb
XL
3318 Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
3319 }
3320 }
3321
3322 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
3323 match *self {
94b46f34
XL
3324 Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
3325 Operand::Constant(ref c) => c.visit_with(visitor),
8bb4bdeb
XL
3326 }
3327 }
3328}
3329
dc9dc135
XL
3330impl<'tcx> TypeFoldable<'tcx> for Projection<'tcx> {
3331 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
9fa01778 3332 use crate::mir::ProjectionElem::*;
8bb4bdeb
XL
3333
3334 let base = self.base.fold_with(folder);
3335 let elem = match self.elem {
3336 Deref => Deref,
3b2f2976 3337 Field(f, ref ty) => Field(f, ty.fold_with(folder)),
8bb4bdeb 3338 Index(ref v) => Index(v.fold_with(folder)),
94b46f34 3339 ref elem => elem.clone(),
8bb4bdeb
XL
3340 };
3341
94b46f34 3342 Projection { base, elem }
8bb4bdeb
XL
3343 }
3344
3345 fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
9fa01778 3346 use crate::mir::ProjectionElem::*;
8bb4bdeb 3347
416331ca
XL
3348 self.base.visit_with(visitor)
3349 || match self.elem {
3350 Field(_, ref ty) => ty.visit_with(visitor),
3351 Index(ref v) => v.visit_with(visitor),
3352 _ => false,
3353 }
8bb4bdeb
XL
3354 }
3355}
3356
0531ce1d 3357impl<'tcx> TypeFoldable<'tcx> for Field {
dc9dc135 3358 fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
0531ce1d
XL
3359 *self
3360 }
3361 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
3362 false
3363 }
3364}
3365
48663c56 3366impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
dc9dc135 3367 fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
48663c56
XL
3368 *self
3369 }
3370 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
3371 false
3372 }
3373}
3374
dc9dc135
XL
3375impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
3376 fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
3377 self.clone()
3378 }
3379 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
3380 false
3381 }
3382}
3383
8bb4bdeb 3384impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
dc9dc135 3385 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
8bb4bdeb
XL
3386 Constant {
3387 span: self.span.clone(),
3388 ty: self.ty.fold_with(folder),
b7449926 3389 user_ty: self.user_ty.fold_with(folder),
94b46f34 3390 literal: self.literal.fold_with(folder),
8bb4bdeb
XL
3391 }
3392 }
3393 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
3394 self.ty.visit_with(visitor) || self.literal.visit_with(visitor)
3395 }
3396}