| 1 | //! This defines the syntax of MIR, i.e., the set of available MIR operations, and other definitions |
| 2 | //! closely related to MIR semantics. |
| 3 | //! This is in a dedicated file so that changes to this file can be reviewed more carefully. |
| 4 | //! The intention is that this file only contains datatype declarations, no code. |
| 5 | |
| 6 | use rustc_abi::{FieldIdx, VariantIdx}; |
| 7 | use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece, Mutability}; |
| 8 | use rustc_data_structures::packed::Pu128; |
| 9 | use rustc_hir::CoroutineKind; |
| 10 | use rustc_hir::def_id::DefId; |
| 11 | use rustc_index::IndexVec; |
| 12 | use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; |
| 13 | use rustc_span::def_id::LocalDefId; |
| 14 | use rustc_span::source_map::Spanned; |
| 15 | use rustc_span::{Span, Symbol}; |
| 16 | use rustc_target::asm::InlineAsmRegOrRegClass; |
| 17 | use smallvec::SmallVec; |
| 18 | |
| 19 | use super::{BasicBlock, Const, Local, UserTypeProjection}; |
| 20 | use crate::mir::coverage::CoverageKind; |
| 21 | use crate::ty::adjustment::PointerCoercion; |
| 22 | use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex}; |
| 23 | |
| 24 | /// Represents the "flavors" of MIR. |
| 25 | /// |
| 26 | /// The MIR pipeline is structured into a few major dialects, with one or more phases within each |
| 27 | /// dialect. A MIR flavor is identified by a dialect-phase pair. A single `MirPhase` value |
| 28 | /// specifies such a pair. All flavors of MIR use the same data structure to represent the program. |
| 29 | /// |
| 30 | /// Different MIR dialects have different semantics. (The differences between dialects are small, |
| 31 | /// but they do exist.) The progression from one MIR dialect to the next is technically a lowering |
| 32 | /// from one IR to another. In other words, a single well-formed [`Body`](crate::mir::Body) might |
| 33 | /// have different semantic meaning and different behavior at runtime in the different dialects. |
| 34 | /// The specific differences between dialects are described on the variants below. |
| 35 | /// |
| 36 | /// Phases exist only to place restrictions on what language constructs are permitted in |
| 37 | /// well-formed MIR, and subsequent phases mostly increase those restrictions. I.e. to convert MIR |
| 38 | /// from one phase to the next might require removing/replacing certain MIR constructs. |
| 39 | /// |
| 40 | /// When adding dialects or phases, remember to update [`MirPhase::index`]. |
| 41 | #[derive (Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] |
| 42 | #[derive (HashStable)] |
| 43 | pub enum MirPhase { |
| 44 | /// The "built MIR" dialect, as generated by MIR building. |
| 45 | /// |
| 46 | /// The only things that operate on this dialect are unsafeck, the various MIR lints, and const |
| 47 | /// qualifs. |
| 48 | /// |
| 49 | /// This dialect has just the one (implicit) phase, which places few restrictions on what MIR |
| 50 | /// constructs are allowed. |
| 51 | Built, |
| 52 | |
| 53 | /// The "analysis MIR" dialect, used for borrowck and friends. |
| 54 | /// |
| 55 | /// The only semantic difference between built MIR and analysis MIR relates to constant |
| 56 | /// promotion. In built MIR, sequences of statements that would generally be subject to |
| 57 | /// constant promotion are semantically constants, while in analysis MIR all constants are |
| 58 | /// explicit. |
| 59 | /// |
| 60 | /// The result of const promotion is available from the `mir_promoted` and `promoted_mir` |
| 61 | /// queries. |
| 62 | /// |
| 63 | /// The phases of this dialect are described in `AnalysisPhase`. |
| 64 | Analysis(AnalysisPhase), |
| 65 | |
| 66 | /// The "runtime MIR" dialect, used for CTFE, optimizations, and codegen. |
| 67 | /// |
| 68 | /// The semantic differences between analysis MIR and runtime MIR are as follows. |
| 69 | /// |
| 70 | /// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly |
| 71 | /// speaking, if dataflow analysis determines that the place being dropped is uninitialized, |
| 72 | /// the drop will not be executed. The exact semantics of this aren't written down anywhere, |
| 73 | /// which means they are essentially "what drop elaboration does." In runtime MIR, the drops |
| 74 | /// are unconditional; when a `Drop` terminator is reached, if the type has drop glue that |
| 75 | /// drop glue is always executed. This may be UB if the underlying place is not initialized. |
| 76 | /// - Packed drops: Places might in general be misaligned - in most cases this is UB, the |
| 77 | /// exception is fields of packed structs. In analysis MIR, `Drop(P)` for a `P` that might be |
| 78 | /// misaligned for this reason implicitly moves `P` to a temporary before dropping. Runtime |
| 79 | /// MIR has no such rules, and dropping a misaligned place is simply UB. |
| 80 | /// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In |
| 81 | /// runtime MIR, this is UB. |
| 82 | /// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same |
| 83 | /// way that Rust itself has them. Where exactly these are is generally subject to change, |
| 84 | /// and so we don't document this here. Runtime MIR has most retags explicit (though implicit |
| 85 | /// retags can still occur at `Rvalue::{Ref,AddrOf}`). |
| 86 | /// - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code |
| 87 | /// has access to. This occurs in coroutine bodies. Such locals do not behave like other |
| 88 | /// locals, because they e.g. may be aliased in surprising ways. Runtime MIR has no such |
| 89 | /// special locals. All coroutine bodies are lowered and so all places that look like locals |
| 90 | /// really are locals. |
| 91 | /// |
| 92 | /// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part |
| 93 | /// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that |
| 94 | /// transformations that can suppress such errors should not run on analysis MIR. |
| 95 | /// |
| 96 | /// The phases of this dialect are described in `RuntimePhase`. |
| 97 | Runtime(RuntimePhase), |
| 98 | } |
| 99 | |
| 100 | /// See [`MirPhase::Analysis`]. |
| 101 | #[derive (Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] |
| 102 | #[derive (HashStable)] |
| 103 | pub enum AnalysisPhase { |
| 104 | Initial = 0, |
| 105 | /// Beginning in this phase, the following variants are disallowed: |
| 106 | /// * [`TerminatorKind::FalseUnwind`] |
| 107 | /// * [`TerminatorKind::FalseEdge`] |
| 108 | /// * [`StatementKind::FakeRead`] |
| 109 | /// * [`StatementKind::AscribeUserType`] |
| 110 | /// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or |
| 111 | /// [`CoverageKind::SpanMarker`] |
| 112 | /// * [`Rvalue::Ref`] with `BorrowKind::Fake` |
| 113 | /// * [`CastKind::PointerCoercion`] with any of the following: |
| 114 | /// * [`PointerCoercion::ArrayToPointer`] |
| 115 | /// * [`PointerCoercion::MutToConstPointer`] |
| 116 | /// |
| 117 | /// Furthermore, `Deref` projections must be the first projection within any place (if they |
| 118 | /// appear at all) |
| 119 | PostCleanup = 1, |
| 120 | } |
| 121 | |
| 122 | /// See [`MirPhase::Runtime`]. |
| 123 | #[derive (Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] |
| 124 | #[derive (HashStable)] |
| 125 | pub enum RuntimePhase { |
| 126 | /// In addition to the semantic changes, beginning with this phase, the following variants are |
| 127 | /// disallowed: |
| 128 | /// * [`TerminatorKind::Yield`] |
| 129 | /// * [`TerminatorKind::CoroutineDrop`] |
| 130 | /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` |
| 131 | /// * [`PlaceElem::OpaqueCast`] |
| 132 | /// |
| 133 | /// And the following variants are allowed: |
| 134 | /// * [`StatementKind::Retag`] |
| 135 | /// * [`StatementKind::SetDiscriminant`] |
| 136 | /// * [`StatementKind::Deinit`] |
| 137 | /// |
| 138 | /// Furthermore, `Copy` operands are allowed for non-`Copy` types. |
| 139 | Initial = 0, |
| 140 | /// Beginning with this phase, the following variant is disallowed: |
| 141 | /// * [`ProjectionElem::Deref`] of `Box` |
| 142 | PostCleanup = 1, |
| 143 | Optimized = 2, |
| 144 | } |
| 145 | |
| 146 | /////////////////////////////////////////////////////////////////////////// |
| 147 | // Borrow kinds |
| 148 | |
| 149 | #[derive (Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)] |
| 150 | #[derive (Hash, HashStable)] |
| 151 | pub enum BorrowKind { |
| 152 | /// Data must be immutable and is aliasable. |
| 153 | Shared, |
| 154 | |
| 155 | /// An immutable, aliasable borrow that is discarded after borrow-checking. Can behave either |
| 156 | /// like a normal shared borrow or like a special shallow borrow (see [`FakeBorrowKind`]). |
| 157 | /// |
| 158 | /// This is used when lowering index expressions and matches. This is used to prevent code like |
| 159 | /// the following from compiling: |
| 160 | /// ```compile_fail,E0510 |
| 161 | /// let mut x: &[_] = &[[0, 1]]; |
| 162 | /// let y: &[_] = &[]; |
| 163 | /// let _ = x[0][{x = y; 1}]; |
| 164 | /// ``` |
| 165 | /// ```compile_fail,E0510 |
| 166 | /// let mut x = &Some(0); |
| 167 | /// match *x { |
| 168 | /// None => (), |
| 169 | /// Some(_) if { x = &None; false } => (), |
| 170 | /// Some(_) => (), |
| 171 | /// } |
| 172 | /// ``` |
| 173 | /// We can also report errors with this kind of borrow differently. |
| 174 | Fake(FakeBorrowKind), |
| 175 | |
| 176 | /// Data is mutable and not aliasable. |
| 177 | Mut { kind: MutBorrowKind }, |
| 178 | } |
| 179 | |
| 180 | #[derive (Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)] |
| 181 | #[derive (Hash, HashStable)] |
| 182 | pub enum RawPtrKind { |
| 183 | Mut, |
| 184 | Const, |
| 185 | /// Creates a raw pointer to a place that will only be used to access its metadata, |
| 186 | /// not the data behind the pointer. Note that this limitation is *not* enforced |
| 187 | /// by the validator. |
| 188 | /// |
| 189 | /// The borrow checker allows overlap of these raw pointers with references to the |
| 190 | /// data. This is sound even if the pointer is "misused" since any such use is anyway |
| 191 | /// unsafe. In terms of the operational semantics (i.e., Miri), this is equivalent |
| 192 | /// to `RawPtrKind::Mut`, but will never incur a retag. |
| 193 | FakeForPtrMetadata, |
| 194 | } |
| 195 | |
| 196 | #[derive (Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)] |
| 197 | #[derive (Hash, HashStable)] |
| 198 | pub enum MutBorrowKind { |
| 199 | Default, |
| 200 | /// This borrow arose from method-call auto-ref. (i.e., `adjustment::Adjust::Borrow`) |
| 201 | TwoPhaseBorrow, |
| 202 | /// Data must be immutable but not aliasable. This kind of borrow |
| 203 | /// cannot currently be expressed by the user and is used only in |
| 204 | /// implicit closure bindings. It is needed when the closure is |
| 205 | /// borrowing or mutating a mutable referent, e.g.: |
| 206 | /// ``` |
| 207 | /// let mut z = 3; |
| 208 | /// let x: &mut isize = &mut z; |
| 209 | /// let y = || *x += 5; |
| 210 | /// ``` |
| 211 | /// If we were to try to translate this closure into a more explicit |
| 212 | /// form, we'd encounter an error with the code as written: |
| 213 | /// ```compile_fail,E0594 |
| 214 | /// struct Env<'a> { x: &'a &'a mut isize } |
| 215 | /// let mut z = 3; |
| 216 | /// let x: &mut isize = &mut z; |
| 217 | /// let y = (&mut Env { x: &x }, fn_ptr); // Closure is pair of env and fn |
| 218 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } |
| 219 | /// ``` |
| 220 | /// This is then illegal because you cannot mutate an `&mut` found |
| 221 | /// in an aliasable location. To solve, you'd have to translate with |
| 222 | /// an `&mut` borrow: |
| 223 | /// ```compile_fail,E0596 |
| 224 | /// struct Env<'a> { x: &'a mut &'a mut isize } |
| 225 | /// let mut z = 3; |
| 226 | /// let x: &mut isize = &mut z; |
| 227 | /// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x |
| 228 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } |
| 229 | /// ``` |
| 230 | /// Now the assignment to `**env.x` is legal, but creating a |
| 231 | /// mutable pointer to `x` is not because `x` is not mutable. We |
| 232 | /// could fix this by declaring `x` as `let mut x`. This is ok in |
| 233 | /// user code, if awkward, but extra weird for closures, since the |
| 234 | /// borrow is hidden. |
| 235 | /// |
| 236 | /// So we introduce a `ClosureCapture` borrow -- user will not have to mark the variable |
| 237 | /// containing the mutable reference as `mut`, as they didn't ever |
| 238 | /// intend to mutate the mutable reference itself. We still mutable capture it in order to |
| 239 | /// mutate the pointed value through it (but not mutating the reference itself). |
| 240 | /// |
| 241 | /// This solves the problem. For simplicity, we don't give users the way to express this |
| 242 | /// borrow, it's just used when translating closures. |
| 243 | ClosureCapture, |
| 244 | } |
| 245 | |
| 246 | #[derive (Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)] |
| 247 | #[derive (Hash, HashStable)] |
| 248 | pub enum FakeBorrowKind { |
| 249 | /// A shared shallow borrow. The immediately borrowed place must be immutable, but projections |
| 250 | /// from it don't need to be. For example, a shallow borrow of `a.b` doesn't conflict with a |
| 251 | /// mutable borrow of `a.b.c`. |
| 252 | /// |
| 253 | /// This is used when lowering matches: when matching on a place we want to ensure that place |
| 254 | /// have the same value from the start of the match until an arm is selected. This prevents this |
| 255 | /// code from compiling: |
| 256 | /// ```compile_fail,E0510 |
| 257 | /// let mut x = &Some(0); |
| 258 | /// match *x { |
| 259 | /// None => (), |
| 260 | /// Some(_) if { x = &None; false } => (), |
| 261 | /// Some(_) => (), |
| 262 | /// } |
| 263 | /// ``` |
| 264 | /// This can't be a shared borrow because mutably borrowing `(*x as Some).0` should not checking |
| 265 | /// the discriminant or accessing other variants, because the mutating `(*x as Some).0` can't |
| 266 | /// affect the discriminant of `x`. E.g. the following is allowed: |
| 267 | /// ```rust |
| 268 | /// let mut x = Some(0); |
| 269 | /// match x { |
| 270 | /// Some(_) |
| 271 | /// if { |
| 272 | /// if let Some(ref mut y) = x { |
| 273 | /// *y += 1; |
| 274 | /// }; |
| 275 | /// true |
| 276 | /// } => {} |
| 277 | /// _ => {} |
| 278 | /// } |
| 279 | /// ``` |
| 280 | Shallow, |
| 281 | /// A shared (deep) borrow. Data must be immutable and is aliasable. |
| 282 | /// |
| 283 | /// This is used when lowering deref patterns, where shallow borrows wouldn't prevent something |
| 284 | /// like: |
| 285 | // ```compile_fail |
| 286 | // let mut b = Box::new(false); |
| 287 | // match b { |
| 288 | // deref!(true) => {} // not reached because `*b == false` |
| 289 | // _ if { *b = true; false } => {} // not reached because the guard is `false` |
| 290 | // deref!(false) => {} // not reached because the guard changed it |
| 291 | // // UB because we reached the unreachable. |
| 292 | // } |
| 293 | // ``` |
| 294 | Deep, |
| 295 | } |
| 296 | |
| 297 | /////////////////////////////////////////////////////////////////////////// |
| 298 | // Statements |
| 299 | |
| 300 | /// The various kinds of statements that can appear in MIR. |
| 301 | /// |
| 302 | /// Not all of these are allowed at every [`MirPhase`]. Check the documentation there to see which |
| 303 | /// ones you do not have to worry about. The MIR validator will generally enforce such restrictions, |
| 304 | /// causing an ICE if they are violated. |
| 305 | #[derive (Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 306 | #[derive (TypeFoldable, TypeVisitable)] |
| 307 | pub enum StatementKind<'tcx> { |
| 308 | /// Assign statements roughly correspond to an assignment in Rust proper (`x = ...`) except |
| 309 | /// without the possibility of dropping the previous value (that must be done separately, if at |
| 310 | /// all). The *exact* way this works is undecided. It probably does something like evaluating |
| 311 | /// the LHS to a place and the RHS to a value, and then storing the value to the place. Various |
| 312 | /// parts of this may do type specific things that are more complicated than simply copying |
| 313 | /// bytes. |
| 314 | /// |
| 315 | /// **Needs clarification**: The implication of the above idea would be that assignment implies |
| 316 | /// that the resulting value is initialized. I believe we could commit to this separately from |
| 317 | /// committing to whatever part of the memory model we would need to decide on to make the above |
| 318 | /// paragraph precise. Do we want to? |
| 319 | /// |
| 320 | /// Assignments in which the types of the place and rvalue differ are not well-formed. |
| 321 | /// |
| 322 | /// **Needs clarification**: Do we ever want to worry about non-free (in the body) lifetimes for |
| 323 | /// the typing requirement in post drop-elaboration MIR? I think probably not - I'm not sure we |
| 324 | /// could meaningfully require this anyway. How about free lifetimes? Is ignoring this |
| 325 | /// interesting for optimizations? Do we want to allow such optimizations? |
| 326 | /// |
| 327 | /// **Needs clarification**: We currently require that the LHS place not overlap with any place |
| 328 | /// read as part of computation of the RHS for some rvalues (generally those not producing |
| 329 | /// primitives). This requirement is under discussion in [#68364]. As a part of this discussion, |
| 330 | /// it is also unclear in what order the components are evaluated. |
| 331 | /// |
| 332 | /// [#68364]: https://github.com/rust-lang/rust/issues/68364 |
| 333 | /// |
| 334 | /// See [`Rvalue`] documentation for details on each of those. |
| 335 | Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>), |
| 336 | |
| 337 | /// This represents all the reading that a pattern match may do (e.g., inspecting constants and |
| 338 | /// discriminant values), and the kind of pattern it comes from. This is in order to adapt |
| 339 | /// potential error messages to these specific patterns. |
| 340 | /// |
| 341 | /// Note that this also is emitted for regular `let` bindings to ensure that locals that are |
| 342 | /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;` |
| 343 | /// |
| 344 | /// When executed at runtime this is a nop. |
| 345 | /// |
| 346 | /// Disallowed after drop elaboration. |
| 347 | FakeRead(Box<(FakeReadCause, Place<'tcx>)>), |
| 348 | |
| 349 | /// Write the discriminant for a variant to the enum Place. |
| 350 | /// |
| 351 | /// This is permitted for both coroutines and ADTs. This does not necessarily write to the |
| 352 | /// entire place; instead, it writes to the minimum set of bytes as required by the layout for |
| 353 | /// the type. |
| 354 | SetDiscriminant { place: Box<Place<'tcx>>, variant_index: VariantIdx }, |
| 355 | |
| 356 | /// Deinitializes the place. |
| 357 | /// |
| 358 | /// This writes `uninit` bytes to the entire place. |
| 359 | Deinit(Box<Place<'tcx>>), |
| 360 | |
| 361 | /// `StorageLive` and `StorageDead` statements mark the live range of a local. |
| 362 | /// |
| 363 | /// At any point during the execution of a function, each local is either allocated or |
| 364 | /// unallocated. Except as noted below, all locals except function parameters are initially |
| 365 | /// unallocated. `StorageLive` statements cause memory to be allocated for the local while |
| 366 | /// `StorageDead` statements cause the memory to be freed. In other words, |
| 367 | /// `StorageLive`/`StorageDead` act like the heap operations `allocate`/`deallocate`, but for |
| 368 | /// stack-allocated local variables. Using a local in any way (not only reading/writing from it) |
| 369 | /// while it is unallocated is UB. |
| 370 | /// |
| 371 | /// Some locals have no `StorageLive` or `StorageDead` statements within the entire MIR body. |
| 372 | /// These locals are implicitly allocated for the full duration of the function. There is a |
| 373 | /// convenience method at `rustc_mir_dataflow::storage::always_storage_live_locals` for |
| 374 | /// computing these locals. |
| 375 | /// |
| 376 | /// If the local is already allocated, calling `StorageLive` again will implicitly free the |
| 377 | /// local and then allocate fresh uninitilized memory. If a local is already deallocated, |
| 378 | /// calling `StorageDead` again is a NOP. |
| 379 | StorageLive(Local), |
| 380 | |
| 381 | /// See `StorageLive` above. |
| 382 | StorageDead(Local), |
| 383 | |
| 384 | /// Retag references in the given place, ensuring they got fresh tags. |
| 385 | /// |
| 386 | /// This is part of the Stacked Borrows model. These statements are currently only interpreted |
| 387 | /// by miri and only generated when `-Z mir-emit-retag` is passed. See |
| 388 | /// <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/> for |
| 389 | /// more details. |
| 390 | /// |
| 391 | /// For code that is not specific to stacked borrows, you should consider retags to read and |
| 392 | /// modify the place in an opaque way. |
| 393 | /// |
| 394 | /// Only `RetagKind::Default` and `RetagKind::FnEntry` are permitted. |
| 395 | Retag(RetagKind, Box<Place<'tcx>>), |
| 396 | |
| 397 | /// This statement exists to preserve a trace of a scrutinee matched against a wildcard binding. |
| 398 | /// This is especially useful for `let _ = PLACE;` bindings that desugar to a single |
| 399 | /// `PlaceMention(PLACE)`. |
| 400 | /// |
| 401 | /// When executed at runtime, this computes the given place, but then discards |
| 402 | /// it without doing a load. `let _ = *ptr;` is fine even if the pointer is dangling. |
| 403 | PlaceMention(Box<Place<'tcx>>), |
| 404 | |
| 405 | /// Encodes a user's type ascription. These need to be preserved |
| 406 | /// intact so that NLL can respect them. For example: |
| 407 | /// ```ignore (illustrative) |
| 408 | /// let a: T = y; |
| 409 | /// ``` |
| 410 | /// The effect of this annotation is to relate the type `T_y` of the place `y` |
| 411 | /// to the user-given type `T`. The effect depends on the specified variance: |
| 412 | /// |
| 413 | /// - `Covariant` -- requires that `T_y <: T` |
| 414 | /// - `Contravariant` -- requires that `T_y :> T` |
| 415 | /// - `Invariant` -- requires that `T_y == T` |
| 416 | /// - `Bivariant` -- no effect |
| 417 | /// |
| 418 | /// When executed at runtime this is a nop. |
| 419 | /// |
| 420 | /// Disallowed after drop elaboration. |
| 421 | AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), |
| 422 | |
| 423 | /// Carries control-flow-sensitive information injected by `-Cinstrument-coverage`, |
| 424 | /// such as where to generate physical coverage-counter-increments during codegen. |
| 425 | /// |
| 426 | /// Coverage statements are used in conjunction with the coverage mappings and other |
| 427 | /// information stored in the function's |
| 428 | /// [`mir::Body::function_coverage_info`](crate::mir::Body::function_coverage_info). |
| 429 | /// (For inlined MIR, take care to look up the *original function's* coverage info.) |
| 430 | /// |
| 431 | /// Interpreters and codegen backends that don't support coverage instrumentation |
| 432 | /// can usually treat this as a no-op. |
| 433 | Coverage( |
| 434 | // Coverage statements are unlikely to ever contain type information in |
| 435 | // the foreseeable future, so excluding them from TypeFoldable/TypeVisitable |
| 436 | // avoids some unhelpful derive boilerplate. |
| 437 | #[type_foldable(identity)] |
| 438 | #[type_visitable(ignore)] |
| 439 | CoverageKind, |
| 440 | ), |
| 441 | |
| 442 | /// Denotes a call to an intrinsic that does not require an unwind path and always returns. |
| 443 | /// This avoids adding a new block and a terminator for simple intrinsics. |
| 444 | Intrinsic(Box<NonDivergingIntrinsic<'tcx>>), |
| 445 | |
| 446 | /// Instructs the const eval interpreter to increment a counter; this counter is used to track |
| 447 | /// how many steps the interpreter has taken. It is used to prevent the user from writing const |
| 448 | /// code that runs for too long or infinitely. Other than in the const eval interpreter, this |
| 449 | /// is a no-op. |
| 450 | ConstEvalCounter, |
| 451 | |
| 452 | /// No-op. Useful for deleting instructions without affecting statement indices. |
| 453 | Nop, |
| 454 | |
| 455 | /// Marker statement indicating where `place` would be dropped. |
| 456 | /// This is semantically equivalent to `Nop`, so codegen and MIRI should interpret this |
| 457 | /// statement as such. |
| 458 | /// The only use case of this statement is for linting in MIR to detect temporary lifetime |
| 459 | /// changes. |
| 460 | BackwardIncompatibleDropHint { |
| 461 | /// Place to drop |
| 462 | place: Box<Place<'tcx>>, |
| 463 | /// Reason for backward incompatibility |
| 464 | reason: BackwardIncompatibleDropReason, |
| 465 | }, |
| 466 | } |
| 467 | |
| 468 | #[derive ( |
| 469 | Clone, |
| 470 | TyEncodable, |
| 471 | TyDecodable, |
| 472 | Debug, |
| 473 | PartialEq, |
| 474 | Hash, |
| 475 | HashStable, |
| 476 | TypeFoldable, |
| 477 | TypeVisitable |
| 478 | )] |
| 479 | pub enum NonDivergingIntrinsic<'tcx> { |
| 480 | /// Denotes a call to the intrinsic function `assume`. |
| 481 | /// |
| 482 | /// The operand must be a boolean. Optimizers may use the value of the boolean to backtrack its |
| 483 | /// computation to infer information about other variables. So if the boolean came from a |
| 484 | /// `x < y` operation, subsequent operations on `x` and `y` could elide various bound checks. |
| 485 | /// If the argument is `false`, this operation is equivalent to `TerminatorKind::Unreachable`. |
| 486 | Assume(Operand<'tcx>), |
| 487 | |
| 488 | /// Denotes a call to the intrinsic function `copy_nonoverlapping`. |
| 489 | /// |
| 490 | /// First, all three operands are evaluated. `src` and `dest` must each be a reference, pointer, |
| 491 | /// or `Box` pointing to the same type `T`. `count` must evaluate to a `usize`. Then, `src` and |
| 492 | /// `dest` are dereferenced, and `count * size_of::<T>()` bytes beginning with the first byte of |
| 493 | /// the `src` place are copied to the contiguous range of bytes beginning with the first byte |
| 494 | /// of `dest`. |
| 495 | /// |
| 496 | /// **Needs clarification**: In what order are operands computed and dereferenced? It should |
| 497 | /// probably match the order for assignment, but that is also undecided. |
| 498 | /// |
| 499 | /// **Needs clarification**: Is this typed or not, ie is there a typed load and store involved? |
| 500 | /// I vaguely remember Ralf saying somewhere that he thought it should not be. |
| 501 | CopyNonOverlapping(CopyNonOverlapping<'tcx>), |
| 502 | } |
| 503 | |
| 504 | /// Describes what kind of retag is to be performed. |
| 505 | #[derive (Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)] |
| 506 | #[rustc_pass_by_value ] |
| 507 | pub enum RetagKind { |
| 508 | /// The initial retag of arguments when entering a function. |
| 509 | FnEntry, |
| 510 | /// Retag preparing for a two-phase borrow. |
| 511 | TwoPhase, |
| 512 | /// Retagging raw pointers. |
| 513 | Raw, |
| 514 | /// A "normal" retag. |
| 515 | Default, |
| 516 | } |
| 517 | |
| 518 | /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. |
| 519 | #[derive (Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)] |
| 520 | pub enum FakeReadCause { |
| 521 | /// Inject a fake read of the borrowed input at the end of each guards |
| 522 | /// code. |
| 523 | /// |
| 524 | /// This should ensure that you cannot change the variant for an enum while |
| 525 | /// you are in the midst of matching on it. |
| 526 | ForMatchGuard, |
| 527 | |
| 528 | /// `let x: !; match x {}` doesn't generate any read of x so we need to |
| 529 | /// generate a read of x to check that it is initialized and safe. |
| 530 | /// |
| 531 | /// If a closure pattern matches a Place starting with an Upvar, then we introduce a |
| 532 | /// FakeRead for that Place outside the closure, in such a case this option would be |
| 533 | /// Some(closure_def_id). |
| 534 | /// Otherwise, the value of the optional LocalDefId will be None. |
| 535 | // |
| 536 | // We can use LocalDefId here since fake read statements are removed |
| 537 | // before codegen in the `CleanupNonCodegenStatements` pass. |
| 538 | ForMatchedPlace(Option<LocalDefId>), |
| 539 | |
| 540 | /// A fake read of the RefWithinGuard version of a bind-by-value variable |
| 541 | /// in a match guard to ensure that its value hasn't change by the time |
| 542 | /// we create the OutsideGuard version. |
| 543 | ForGuardBinding, |
| 544 | |
| 545 | /// Officially, the semantics of |
| 546 | /// |
| 547 | /// `let pattern = <expr>;` |
| 548 | /// |
| 549 | /// is that `<expr>` is evaluated into a temporary and then this temporary is |
| 550 | /// into the pattern. |
| 551 | /// |
| 552 | /// However, if we see the simple pattern `let var = <expr>`, we optimize this to |
| 553 | /// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable, |
| 554 | /// but in some cases it can affect the borrow checker, as in #53695. |
| 555 | /// Therefore, we insert a "fake read" here to ensure that we get |
| 556 | /// appropriate errors. |
| 557 | /// |
| 558 | /// If a closure pattern matches a Place starting with an Upvar, then we introduce a |
| 559 | /// FakeRead for that Place outside the closure, in such a case this option would be |
| 560 | /// Some(closure_def_id). |
| 561 | /// Otherwise, the value of the optional DefId will be None. |
| 562 | ForLet(Option<LocalDefId>), |
| 563 | |
| 564 | /// If we have an index expression like |
| 565 | /// |
| 566 | /// (*x)[1][{ x = y; 4}] |
| 567 | /// |
| 568 | /// then the first bounds check is invalidated when we evaluate the second |
| 569 | /// index expression. Thus we create a fake borrow of `x` across the second |
| 570 | /// indexer, which will cause a borrow check error. |
| 571 | ForIndex, |
| 572 | } |
| 573 | |
| 574 | #[derive (Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 575 | #[derive (TypeFoldable, TypeVisitable)] |
| 576 | pub struct CopyNonOverlapping<'tcx> { |
| 577 | pub src: Operand<'tcx>, |
| 578 | pub dst: Operand<'tcx>, |
| 579 | /// Number of elements to copy from src to dest, not bytes. |
| 580 | pub count: Operand<'tcx>, |
| 581 | } |
| 582 | |
| 583 | /// Represents how a [`TerminatorKind::Call`] was constructed. |
| 584 | /// Used only for diagnostics. |
| 585 | #[derive (Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, HashStable)] |
| 586 | #[derive (TypeFoldable, TypeVisitable)] |
| 587 | pub enum CallSource { |
| 588 | /// This came from something such as `a > b` or `a + b`. In THIR, if `from_hir_call` |
| 589 | /// is false then this is the desugaring. |
| 590 | OverloadedOperator, |
| 591 | /// This was from comparison generated by a match, used by const-eval for better errors |
| 592 | /// when the comparison cannot be done in compile time. |
| 593 | /// |
| 594 | /// (see <https://github.com/rust-lang/rust/issues/90237>) |
| 595 | MatchCmp, |
| 596 | /// Other types of desugaring that did not come from the HIR, but we don't care about |
| 597 | /// for diagnostics (yet). |
| 598 | Misc, |
| 599 | /// Normal function call, no special source |
| 600 | Normal, |
| 601 | } |
| 602 | |
| 603 | #[derive (Clone, Copy, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] |
| 604 | #[derive (TypeFoldable, TypeVisitable)] |
| 605 | /// The macro that an inline assembly block was created by |
| 606 | pub enum InlineAsmMacro { |
| 607 | /// The `asm!` macro |
| 608 | Asm, |
| 609 | /// The `naked_asm!` macro |
| 610 | NakedAsm, |
| 611 | } |
| 612 | |
| 613 | /////////////////////////////////////////////////////////////////////////// |
| 614 | // Terminators |
| 615 | |
| 616 | /// The various kinds of terminators, representing ways of exiting from a basic block. |
| 617 | /// |
| 618 | /// A note on unwinding: Panics may occur during the execution of some terminators. Depending on the |
| 619 | /// `-C panic` flag, this may either cause the program to abort or the call stack to unwind. Such |
| 620 | /// terminators have a `unwind: UnwindAction` field on them. If stack unwinding occurs, then |
| 621 | /// once the current function is reached, an action will be taken based on the `unwind` field. |
| 622 | /// If the action is `Cleanup`, then the execution continues at the given basic block. If the |
| 623 | /// action is `Continue` then no cleanup is performed, and the stack continues unwinding. |
| 624 | /// |
| 625 | /// The basic block pointed to by a `Cleanup` unwind action must have its `cleanup` flag set. |
| 626 | /// `cleanup` basic blocks have a couple restrictions: |
| 627 | /// 1. All `unwind` fields in them must be `UnwindAction::Terminate` or `UnwindAction::Unreachable`. |
| 628 | /// 2. `Return` terminators are not allowed in them. `Terminate` and `Resume` terminators are. |
| 629 | /// 3. All other basic blocks (in the current body) that are reachable from `cleanup` basic blocks |
| 630 | /// must also be `cleanup`. This is a part of the type system and checked statically, so it is |
| 631 | /// still an error to have such an edge in the CFG even if it's known that it won't be taken at |
| 632 | /// runtime. |
| 633 | /// 4. The control flow between cleanup blocks must look like an upside down tree. Roughly |
| 634 | /// speaking, this means that control flow that looks like a V is allowed, while control flow |
| 635 | /// that looks like a W is not. This is necessary to ensure that landing pad information can be |
| 636 | /// correctly codegened on MSVC. More precisely: |
| 637 | /// |
| 638 | /// Begin with the standard control flow graph `G`. Modify `G` as follows: for any two cleanup |
| 639 | /// vertices `u` and `v` such that `u` dominates `v`, contract `u` and `v` into a single vertex, |
| 640 | /// deleting self edges and duplicate edges in the process. Now remove all vertices from `G` |
| 641 | /// that are not cleanup vertices or are not reachable. The resulting graph must be an inverted |
| 642 | /// tree, that is each vertex may have at most one successor and there may be no cycles. |
| 643 | #[derive (Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] |
| 644 | pub enum TerminatorKind<'tcx> { |
| 645 | /// Block has one successor; we continue execution there. |
| 646 | Goto { target: BasicBlock }, |
| 647 | |
| 648 | /// Switches based on the computed value. |
| 649 | /// |
| 650 | /// First, evaluates the `discr` operand. The type of the operand must be a signed or unsigned |
| 651 | /// integer, char, or bool, and must match the given type. Then, if the list of switch targets |
| 652 | /// contains the computed value, continues execution at the associated basic block. Otherwise, |
| 653 | /// continues execution at the "otherwise" basic block. |
| 654 | /// |
| 655 | /// Target values may not appear more than once. |
| 656 | SwitchInt { |
| 657 | /// The discriminant value being tested. |
| 658 | discr: Operand<'tcx>, |
| 659 | targets: SwitchTargets, |
| 660 | }, |
| 661 | |
| 662 | /// Indicates that the landing pad is finished and that the process should continue unwinding. |
| 663 | /// |
| 664 | /// Like a return, this marks the end of this invocation of the function. |
| 665 | /// |
| 666 | /// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after |
| 667 | /// deaggregation runs. |
| 668 | UnwindResume, |
| 669 | |
| 670 | /// Indicates that the landing pad is finished and that the process should terminate. |
| 671 | /// |
| 672 | /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in |
| 673 | /// cleanup blocks. |
| 674 | UnwindTerminate(UnwindTerminateReason), |
| 675 | |
| 676 | /// Returns from the function. |
| 677 | /// |
| 678 | /// Like function calls, the exact semantics of returns in Rust are unclear. Returning very |
| 679 | /// likely at least assigns the value currently in the return place (`_0`) to the place |
| 680 | /// specified in the associated `Call` terminator in the calling function, as if assigned via |
| 681 | /// `dest = move _0`. It might additionally do other things, like have side-effects in the |
| 682 | /// aliasing model. |
| 683 | /// |
| 684 | /// If the body is a coroutine body, this has slightly different semantics; it instead causes a |
| 685 | /// `CoroutineState::Returned(_0)` to be created (as if by an `Aggregate` rvalue) and assigned |
| 686 | /// to the return place. |
| 687 | Return, |
| 688 | |
| 689 | /// Indicates a terminator that can never be reached. |
| 690 | /// |
| 691 | /// Executing this terminator is UB. |
| 692 | Unreachable, |
| 693 | |
| 694 | /// The behavior of this statement differs significantly before and after drop elaboration. |
| 695 | /// |
| 696 | /// After drop elaboration: `Drop` terminators are a complete nop for types that have no drop |
| 697 | /// glue. For other types, `Drop` terminators behave exactly like a call to |
| 698 | /// `core::mem::drop_in_place` with a pointer to the given place. |
| 699 | /// |
| 700 | /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically, |
| 701 | /// the `Drop` will be executed if... |
| 702 | /// |
| 703 | /// **Needs clarification**: End of that sentence. This in effect should document the exact |
| 704 | /// behavior of drop elaboration. The following sounds vaguely right, but I'm not quite sure: |
| 705 | /// |
| 706 | /// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to |
| 707 | /// > the place or one of its "parents" occurred more recently than a move out of it. This does not |
| 708 | /// > consider indirect assignments. |
| 709 | /// |
| 710 | /// The `replace` flag indicates whether this terminator was created as part of an assignment. |
| 711 | /// This should only be used for diagnostic purposes, and does not have any operational |
| 712 | /// meaning. |
| 713 | Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction, replace: bool }, |
| 714 | |
| 715 | /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of |
| 716 | /// the referred to function. The operand types must match the argument types of the function. |
| 717 | /// The return place type must match the return type. The type of the `func` operand must be |
| 718 | /// callable, meaning either a function pointer, a function type, or a closure type. |
| 719 | /// |
| 720 | /// **Needs clarification**: The exact semantics of this. Current backends rely on `move` |
| 721 | /// operands not aliasing the return place. It is unclear how this is justified in MIR, see |
| 722 | /// [#71117]. |
| 723 | /// |
| 724 | /// [#71117]: https://github.com/rust-lang/rust/issues/71117 |
| 725 | Call { |
| 726 | /// The function that’s being called. |
| 727 | func: Operand<'tcx>, |
| 728 | /// Arguments the function is called with. |
| 729 | /// These are owned by the callee, which is free to modify them. |
| 730 | /// This allows the memory occupied by "by-value" arguments to be |
| 731 | /// reused across function calls without duplicating the contents. |
| 732 | /// The span for each arg is also included |
| 733 | /// (e.g. `a` and `b` in `x.foo(a, b)`). |
| 734 | args: Box<[Spanned<Operand<'tcx>>]>, |
| 735 | /// Where the returned value will be written |
| 736 | destination: Place<'tcx>, |
| 737 | /// Where to go after this call returns. If none, the call necessarily diverges. |
| 738 | target: Option<BasicBlock>, |
| 739 | /// Action to be taken if the call unwinds. |
| 740 | unwind: UnwindAction, |
| 741 | /// Where this call came from in HIR/THIR. |
| 742 | call_source: CallSource, |
| 743 | /// This `Span` is the span of the function, without the dot and receiver |
| 744 | /// e.g. `foo(a, b)` in `x.foo(a, b)` |
| 745 | fn_span: Span, |
| 746 | }, |
| 747 | |
| 748 | /// Tail call. |
| 749 | /// |
| 750 | /// Roughly speaking this is a chimera of [`Call`] and [`Return`], with some caveats. |
| 751 | /// Semantically tail calls consists of two actions: |
| 752 | /// - pop of the current stack frame |
| 753 | /// - a call to the `func`, with the return address of the **current** caller |
| 754 | /// - so that a `return` inside `func` returns to the caller of the caller |
| 755 | /// of the function that is currently being executed |
| 756 | /// |
| 757 | /// Note that in difference with [`Call`] this is missing |
| 758 | /// - `destination` (because it's always the return place) |
| 759 | /// - `target` (because it's always taken from the current stack frame) |
| 760 | /// - `unwind` (because it's always taken from the current stack frame) |
| 761 | /// |
| 762 | /// [`Call`]: TerminatorKind::Call |
| 763 | /// [`Return`]: TerminatorKind::Return |
| 764 | TailCall { |
| 765 | /// The function that’s being called. |
| 766 | func: Operand<'tcx>, |
| 767 | /// Arguments the function is called with. |
| 768 | /// These are owned by the callee, which is free to modify them. |
| 769 | /// This allows the memory occupied by "by-value" arguments to be |
| 770 | /// reused across function calls without duplicating the contents. |
| 771 | args: Box<[Spanned<Operand<'tcx>>]>, |
| 772 | // FIXME(explicit_tail_calls): should we have the span for `become`? is this span accurate? do we need it? |
| 773 | /// This `Span` is the span of the function, without the dot and receiver |
| 774 | /// (e.g. `foo(a, b)` in `x.foo(a, b)` |
| 775 | fn_span: Span, |
| 776 | }, |
| 777 | |
| 778 | /// Evaluates the operand, which must have type `bool`. If it is not equal to `expected`, |
| 779 | /// initiates a panic. Initiating a panic corresponds to a `Call` terminator with some |
| 780 | /// unspecified constant as the function to call, all the operands stored in the `AssertMessage` |
| 781 | /// as parameters, and `None` for the destination. Keep in mind that the `cleanup` path is not |
| 782 | /// necessarily executed even in the case of a panic, for example in `-C panic=abort`. If the |
| 783 | /// assertion does not fail, execution continues at the specified basic block. |
| 784 | /// |
| 785 | /// When overflow checking is disabled and this is run-time MIR (as opposed to compile-time MIR |
| 786 | /// that is used for CTFE), the following variants of this terminator behave as `goto target`: |
| 787 | /// - `OverflowNeg(..)`, |
| 788 | /// - `Overflow(op, ..)` if op is add, sub, mul, shl, shr, but NOT div or rem. |
| 789 | Assert { |
| 790 | cond: Operand<'tcx>, |
| 791 | expected: bool, |
| 792 | msg: Box<AssertMessage<'tcx>>, |
| 793 | target: BasicBlock, |
| 794 | unwind: UnwindAction, |
| 795 | }, |
| 796 | |
| 797 | /// Marks a suspend point. |
| 798 | /// |
| 799 | /// Like `Return` terminators in coroutine bodies, this computes `value` and then a |
| 800 | /// `CoroutineState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to |
| 801 | /// the return place of the function calling this one, and execution continues in the calling |
| 802 | /// function. When next invoked with the same first argument, execution of this function |
| 803 | /// continues at the `resume` basic block, with the second argument written to the `resume_arg` |
| 804 | /// place. If the coroutine is dropped before then, the `drop` basic block is invoked. |
| 805 | /// |
| 806 | /// Note that coroutines can be (unstably) cloned under certain conditions, which means that |
| 807 | /// this terminator can **return multiple times**! MIR optimizations that reorder code into |
| 808 | /// different basic blocks needs to be aware of that. |
| 809 | /// See <https://github.com/rust-lang/rust/issues/95360>. |
| 810 | /// |
| 811 | /// Not permitted in bodies that are not coroutine bodies, or after coroutine lowering. |
| 812 | /// |
| 813 | /// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`? |
| 814 | Yield { |
| 815 | /// The value to return. |
| 816 | value: Operand<'tcx>, |
| 817 | /// Where to resume to. |
| 818 | resume: BasicBlock, |
| 819 | /// The place to store the resume argument in. |
| 820 | resume_arg: Place<'tcx>, |
| 821 | /// Cleanup to be done if the coroutine is dropped at this suspend point. |
| 822 | drop: Option<BasicBlock>, |
| 823 | }, |
| 824 | |
| 825 | /// Indicates the end of dropping a coroutine. |
| 826 | /// |
| 827 | /// Semantically just a `return` (from the coroutines drop glue). Only permitted in the same situations |
| 828 | /// as `yield`. |
| 829 | /// |
| 830 | /// **Needs clarification**: Is that even correct? The coroutine drop code is always confusing |
| 831 | /// to me, because it's not even really in the current body. |
| 832 | /// |
| 833 | /// **Needs clarification**: Are there type system constraints on these terminators? Should |
| 834 | /// there be a "block type" like `cleanup` blocks for them? |
| 835 | CoroutineDrop, |
| 836 | |
| 837 | /// A block where control flow only ever takes one real path, but borrowck needs to be more |
| 838 | /// conservative. |
| 839 | /// |
| 840 | /// At runtime this is semantically just a goto. |
| 841 | /// |
| 842 | /// Disallowed after drop elaboration. |
| 843 | FalseEdge { |
| 844 | /// The target normal control flow will take. |
| 845 | real_target: BasicBlock, |
| 846 | /// A block control flow could conceptually jump to, but won't in |
| 847 | /// practice. |
| 848 | imaginary_target: BasicBlock, |
| 849 | }, |
| 850 | |
| 851 | /// A terminator for blocks that only take one path in reality, but where we reserve the right |
| 852 | /// to unwind in borrowck, even if it won't happen in practice. This can arise in infinite loops |
| 853 | /// with no function calls for example. |
| 854 | /// |
| 855 | /// At runtime this is semantically just a goto. |
| 856 | /// |
| 857 | /// Disallowed after drop elaboration. |
| 858 | FalseUnwind { |
| 859 | /// The target normal control flow will take. |
| 860 | real_target: BasicBlock, |
| 861 | /// The imaginary cleanup block link. This particular path will never be taken |
| 862 | /// in practice, but in order to avoid fragility we want to always |
| 863 | /// consider it in borrowck. We don't want to accept programs which |
| 864 | /// pass borrowck only when `panic=abort` or some assertions are disabled |
| 865 | /// due to release vs. debug mode builds. |
| 866 | unwind: UnwindAction, |
| 867 | }, |
| 868 | |
| 869 | /// Block ends with an inline assembly block. This is a terminator since |
| 870 | /// inline assembly is allowed to diverge. |
| 871 | InlineAsm { |
| 872 | /// Macro used to create this inline asm: one of `asm!` or `naked_asm!` |
| 873 | asm_macro: InlineAsmMacro, |
| 874 | |
| 875 | /// The template for the inline assembly, with placeholders. |
| 876 | template: &'tcx [InlineAsmTemplatePiece], |
| 877 | |
| 878 | /// The operands for the inline assembly, as `Operand`s or `Place`s. |
| 879 | operands: Box<[InlineAsmOperand<'tcx>]>, |
| 880 | |
| 881 | /// Miscellaneous options for the inline assembly. |
| 882 | options: InlineAsmOptions, |
| 883 | |
| 884 | /// Source spans for each line of the inline assembly code. These are |
| 885 | /// used to map assembler errors back to the line in the source code. |
| 886 | line_spans: &'tcx [Span], |
| 887 | |
| 888 | /// Valid targets for the inline assembly. |
| 889 | /// The first element is the fallthrough destination, unless |
| 890 | /// asm_macro == InlineAsmMacro::NakedAsm or InlineAsmOptions::NORETURN is set. |
| 891 | targets: Box<[BasicBlock]>, |
| 892 | |
| 893 | /// Action to be taken if the inline assembly unwinds. This is present |
| 894 | /// if and only if InlineAsmOptions::MAY_UNWIND is set. |
| 895 | unwind: UnwindAction, |
| 896 | }, |
| 897 | } |
| 898 | |
| 899 | #[derive ( |
| 900 | Clone, |
| 901 | Debug, |
| 902 | TyEncodable, |
| 903 | TyDecodable, |
| 904 | Hash, |
| 905 | HashStable, |
| 906 | PartialEq, |
| 907 | TypeFoldable, |
| 908 | TypeVisitable |
| 909 | )] |
| 910 | pub enum BackwardIncompatibleDropReason { |
| 911 | Edition2024, |
| 912 | } |
| 913 | |
| 914 | #[derive (Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] |
| 915 | pub struct SwitchTargets { |
| 916 | /// Possible values. For each value, the location to branch to is found in |
| 917 | /// the corresponding element in the `targets` vector. |
| 918 | pub(super) values: SmallVec<[Pu128; 1]>, |
| 919 | |
| 920 | /// Possible branch targets. The last element of this vector is used for |
| 921 | /// the "otherwise" branch, so `targets.len() == values.len() + 1` always |
| 922 | /// holds. |
| 923 | // |
| 924 | // Note: This invariant is non-obvious and easy to violate. This would be a |
| 925 | // more rigorous representation: |
| 926 | // |
| 927 | // normal: SmallVec<[(Pu128, BasicBlock); 1]>, |
| 928 | // otherwise: BasicBlock, |
| 929 | // |
| 930 | // But it's important to have the targets in a sliceable type, because |
| 931 | // target slices show up elsewhere. E.g. `TerminatorKind::InlineAsm` has a |
| 932 | // boxed slice, and `TerminatorKind::FalseEdge` has a single target that |
| 933 | // can be converted to a slice with `slice::from_ref`. |
| 934 | // |
| 935 | // Why does this matter? In functions like `TerminatorKind::successors` we |
| 936 | // return `impl Iterator` and a non-slice-of-targets representation here |
| 937 | // causes problems because multiple different concrete iterator types would |
| 938 | // be involved and we would need a boxed trait object, which requires an |
| 939 | // allocation, which is expensive if done frequently. |
| 940 | pub(super) targets: SmallVec<[BasicBlock; 2]>, |
| 941 | } |
| 942 | |
| 943 | /// Action to be taken when a stack unwind happens. |
| 944 | #[derive (Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 945 | #[derive (TypeFoldable, TypeVisitable)] |
| 946 | pub enum UnwindAction { |
| 947 | /// No action is to be taken. Continue unwinding. |
| 948 | /// |
| 949 | /// This is similar to `Cleanup(bb)` where `bb` does nothing but `Resume`, but they are not |
| 950 | /// equivalent, as presence of `Cleanup(_)` will make a frame non-POF. |
| 951 | Continue, |
| 952 | /// Triggers undefined behavior if unwind happens. |
| 953 | Unreachable, |
| 954 | /// Terminates the execution if unwind happens. |
| 955 | /// |
| 956 | /// Depending on the platform and situation this may cause a non-unwindable panic or abort. |
| 957 | Terminate(UnwindTerminateReason), |
| 958 | /// Cleanups to be done. |
| 959 | Cleanup(BasicBlock), |
| 960 | } |
| 961 | |
| 962 | /// The reason we are terminating the process during unwinding. |
| 963 | #[derive (Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 964 | #[derive (TypeFoldable, TypeVisitable)] |
| 965 | pub enum UnwindTerminateReason { |
| 966 | /// Unwinding is just not possible given the ABI of this function. |
| 967 | Abi, |
| 968 | /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was |
| 969 | /// triggered by the drop glue. |
| 970 | InCleanup, |
| 971 | } |
| 972 | |
| 973 | /// Information about an assertion failure. |
| 974 | #[derive (Clone, Hash, HashStable, PartialEq, Debug)] |
| 975 | #[derive (TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] |
| 976 | pub enum AssertKind<O> { |
| 977 | BoundsCheck { len: O, index: O }, |
| 978 | Overflow(BinOp, O, O), |
| 979 | OverflowNeg(O), |
| 980 | DivisionByZero(O), |
| 981 | RemainderByZero(O), |
| 982 | ResumedAfterReturn(CoroutineKind), |
| 983 | ResumedAfterPanic(CoroutineKind), |
| 984 | MisalignedPointerDereference { required: O, found: O }, |
| 985 | NullPointerDereference, |
| 986 | } |
| 987 | |
| 988 | #[derive (Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 989 | #[derive (TypeFoldable, TypeVisitable)] |
| 990 | pub enum InlineAsmOperand<'tcx> { |
| 991 | In { |
| 992 | reg: InlineAsmRegOrRegClass, |
| 993 | value: Operand<'tcx>, |
| 994 | }, |
| 995 | Out { |
| 996 | reg: InlineAsmRegOrRegClass, |
| 997 | late: bool, |
| 998 | place: Option<Place<'tcx>>, |
| 999 | }, |
| 1000 | InOut { |
| 1001 | reg: InlineAsmRegOrRegClass, |
| 1002 | late: bool, |
| 1003 | in_value: Operand<'tcx>, |
| 1004 | out_place: Option<Place<'tcx>>, |
| 1005 | }, |
| 1006 | Const { |
| 1007 | value: Box<ConstOperand<'tcx>>, |
| 1008 | }, |
| 1009 | SymFn { |
| 1010 | value: Box<ConstOperand<'tcx>>, |
| 1011 | }, |
| 1012 | SymStatic { |
| 1013 | def_id: DefId, |
| 1014 | }, |
| 1015 | Label { |
| 1016 | /// This represents the index into the `targets` array in `TerminatorKind::InlineAsm`. |
| 1017 | target_index: usize, |
| 1018 | }, |
| 1019 | } |
| 1020 | |
| 1021 | /// Type for MIR `Assert` terminator error messages. |
| 1022 | pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>; |
| 1023 | |
| 1024 | /////////////////////////////////////////////////////////////////////////// |
| 1025 | // Places |
| 1026 | |
| 1027 | /// Places roughly correspond to a "location in memory." Places in MIR are the same mathematical |
| 1028 | /// object as places in Rust. This of course means that what exactly they are is undecided and part |
| 1029 | /// of the Rust memory model. However, they will likely contain at least the following pieces of |
| 1030 | /// information in some form: |
| 1031 | /// |
| 1032 | /// 1. The address in memory that the place refers to. |
| 1033 | /// 2. The provenance with which the place is being accessed. |
| 1034 | /// 3. The type of the place and an optional variant index. See [`PlaceTy`][super::PlaceTy]. |
| 1035 | /// 4. Optionally, some metadata. This exists if and only if the type of the place is not `Sized`. |
| 1036 | /// |
| 1037 | /// We'll give a description below of how all pieces of the place except for the provenance are |
| 1038 | /// calculated. We cannot give a description of the provenance, because that is part of the |
| 1039 | /// undecided aliasing model - we only include it here at all to acknowledge its existence. |
| 1040 | /// |
| 1041 | /// Each local naturally corresponds to the place `Place { local, projection: [] }`. This place has |
| 1042 | /// the address of the local's allocation and the type of the local. |
| 1043 | /// |
| 1044 | /// **Needs clarification:** Unsized locals seem to present a bit of an issue. Their allocation |
| 1045 | /// can't actually be created on `StorageLive`, because it's unclear how big to make the allocation. |
| 1046 | /// Furthermore, MIR produces assignments to unsized locals, although that is not permitted under |
| 1047 | /// `#![feature(unsized_locals)]` in Rust. Besides just putting "unsized locals are special and |
| 1048 | /// different" in a bunch of places, I (JakobDegen) don't know how to incorporate this behavior into |
| 1049 | /// the current MIR semantics in a clean way - possibly this needs some design work first. |
| 1050 | /// |
| 1051 | /// For places that are not locals, ie they have a non-empty list of projections, we define the |
| 1052 | /// values as a function of the parent place, that is the place with its last [`ProjectionElem`] |
| 1053 | /// stripped. The way this is computed of course depends on the kind of that last projection |
| 1054 | /// element: |
| 1055 | /// |
| 1056 | /// - [`Downcast`](ProjectionElem::Downcast): This projection sets the place's variant index to the |
| 1057 | /// given one, and makes no other changes. A `Downcast` projection must always be followed |
| 1058 | /// immediately by a `Field` projection. |
| 1059 | /// - [`Field`](ProjectionElem::Field): `Field` projections take their parent place and create a |
| 1060 | /// place referring to one of the fields of the type. The resulting address is the parent |
| 1061 | /// address, plus the offset of the field. The type becomes the type of the field. If the parent |
| 1062 | /// was unsized and so had metadata associated with it, then the metadata is retained if the |
| 1063 | /// field is unsized and thrown out if it is sized. |
| 1064 | /// |
| 1065 | /// These projections are only legal for tuples, ADTs, closures, and coroutines. If the ADT or |
| 1066 | /// coroutine has more than one variant, the parent place's variant index must be set, indicating |
| 1067 | /// which variant is being used. If it has just one variant, the variant index may or may not be |
| 1068 | /// included - the single possible variant is inferred if it is not included. |
| 1069 | /// - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the |
| 1070 | /// given one, and makes no other changes. A `OpaqueCast` projection on any type other than an |
| 1071 | /// opaque type from the current crate is not well-formed. |
| 1072 | /// - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the |
| 1073 | /// place as described in the documentation for the `ProjectionElem`. The resulting address is |
| 1074 | /// the parent's address plus that offset, and the type is `T`. This is only legal if the parent |
| 1075 | /// place has type `[T; N]` or `[T]` (*not* `&[T]`). Since such a `T` is always sized, any |
| 1076 | /// resulting metadata is thrown out. |
| 1077 | /// - [`Subslice`](ProjectionElem::Subslice): This projection calculates an offset and a new |
| 1078 | /// address in a similar manner as `ConstantIndex`. It is also only legal on `[T; N]` and `[T]`. |
| 1079 | /// However, this yields a `Place` of type `[T]`, and additionally sets the metadata to be the |
| 1080 | /// length of the subslice. |
| 1081 | /// - [`Index`](ProjectionElem::Index): Like `ConstantIndex`, only legal on `[T; N]` or `[T]`. |
| 1082 | /// However, `Index` additionally takes a local from which the value of the index is computed at |
| 1083 | /// runtime. Computing the value of the index involves interpreting the `Local` as a |
| 1084 | /// `Place { local, projection: [] }`, and then computing its value as if done via |
| 1085 | /// [`Operand::Copy`]. The array/slice is then indexed with the resulting value. The local must |
| 1086 | /// have type `usize`. |
| 1087 | /// - [`Deref`](ProjectionElem::Deref): Derefs are the last type of projection, and the most |
| 1088 | /// complicated. They are only legal on parent places that are references, pointers, or `Box`. A |
| 1089 | /// `Deref` projection begins by loading a value from the parent place, as if by |
| 1090 | /// [`Operand::Copy`]. It then dereferences the resulting pointer, creating a place of the |
| 1091 | /// pointee's type. The resulting address is the address that was stored in the pointer. If the |
| 1092 | /// pointee type is unsized, the pointer additionally stored the value of the metadata. |
| 1093 | /// |
| 1094 | /// The "validity invariant" of places is the same as that of raw pointers, meaning that e.g. |
| 1095 | /// `*ptr` on a dangling or unaligned pointer is never UB. (Later doing a load/store on that place |
| 1096 | /// or turning it into a reference can be UB though!) The only ways for a place computation can |
| 1097 | /// cause UB are: |
| 1098 | /// - On a `Deref` projection, we do an actual load of the inner place, with all the usual |
| 1099 | /// consequences (the inner place must be based on an aligned pointer, it must point to allocated |
| 1100 | /// memory, the aliasig model must allow reads, this must not be a data race). |
| 1101 | /// - For the projections that perform pointer arithmetic, the offset must in-bounds of an |
| 1102 | /// allocation (i.e., the preconditions of `ptr::offset` must be met). |
| 1103 | #[derive (Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable, TypeFoldable, TypeVisitable)] |
| 1104 | pub struct Place<'tcx> { |
| 1105 | pub local: Local, |
| 1106 | |
| 1107 | /// projection out of a place (access a field, deref a pointer, etc) |
| 1108 | pub projection: &'tcx List<PlaceElem<'tcx>>, |
| 1109 | } |
| 1110 | |
| 1111 | #[derive (Copy, Clone, Debug, PartialEq, Eq, Hash)] |
| 1112 | #[derive (TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] |
| 1113 | pub enum ProjectionElem<V, T> { |
| 1114 | Deref, |
| 1115 | |
| 1116 | /// A field (e.g., `f` in `_1.f`) is one variant of [`ProjectionElem`]. Conceptually, |
| 1117 | /// rustc can identify that a field projection refers to either two different regions of memory |
| 1118 | /// or the same one between the base and the 'projection element'. |
| 1119 | /// Read more about projections in the [rustc-dev-guide][mir-datatypes] |
| 1120 | /// |
| 1121 | /// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types |
| 1122 | Field(FieldIdx, T), |
| 1123 | |
| 1124 | /// Index into a slice/array. |
| 1125 | /// |
| 1126 | /// Note that this does not also dereference, and so it does not exactly correspond to slice |
| 1127 | /// indexing in Rust. In other words, in the below Rust code: |
| 1128 | /// |
| 1129 | /// ```rust |
| 1130 | /// let x = &[1, 2, 3, 4]; |
| 1131 | /// let i = 2; |
| 1132 | /// x[i]; |
| 1133 | /// ``` |
| 1134 | /// |
| 1135 | /// The `x[i]` is turned into a `Deref` followed by an `Index`, not just an `Index`. The same |
| 1136 | /// thing is true of the `ConstantIndex` and `Subslice` projections below. |
| 1137 | Index(V), |
| 1138 | |
| 1139 | /// These indices are generated by slice patterns. Easiest to explain |
| 1140 | /// by example: |
| 1141 | /// |
| 1142 | /// ```ignore (illustrative) |
| 1143 | /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false }, |
| 1144 | /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false }, |
| 1145 | /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true }, |
| 1146 | /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true }, |
| 1147 | /// ``` |
| 1148 | ConstantIndex { |
| 1149 | /// index or -index (in Python terms), depending on from_end |
| 1150 | offset: u64, |
| 1151 | /// The thing being indexed must be at least this long -- otherwise, the |
| 1152 | /// projection is UB. |
| 1153 | /// |
| 1154 | /// For arrays this is always the exact length. |
| 1155 | min_length: u64, |
| 1156 | /// Counting backwards from end? This is always false when indexing an |
| 1157 | /// array. |
| 1158 | from_end: bool, |
| 1159 | }, |
| 1160 | |
| 1161 | /// These indices are generated by slice patterns. |
| 1162 | /// |
| 1163 | /// If `from_end` is true `slice[from..slice.len() - to]`. |
| 1164 | /// Otherwise `array[from..to]`. |
| 1165 | Subslice { |
| 1166 | from: u64, |
| 1167 | to: u64, |
| 1168 | /// Whether `to` counts from the start or end of the array/slice. |
| 1169 | /// For `PlaceElem`s this is `true` if and only if the base is a slice. |
| 1170 | /// For `ProjectionKind`, this can also be `true` for arrays. |
| 1171 | from_end: bool, |
| 1172 | }, |
| 1173 | |
| 1174 | /// "Downcast" to a variant of an enum or a coroutine. |
| 1175 | /// |
| 1176 | /// The included Symbol is the name of the variant, used for printing MIR. |
| 1177 | /// |
| 1178 | /// This operation itself is never UB, all it does is change the type of the place. |
| 1179 | Downcast(Option<Symbol>, VariantIdx), |
| 1180 | |
| 1181 | /// Like an explicit cast from an opaque type to a concrete type, but without |
| 1182 | /// requiring an intermediate variable. |
| 1183 | OpaqueCast(T), |
| 1184 | |
| 1185 | /// A transmute from an unsafe binder to the type that it wraps. This is a projection |
| 1186 | /// of a place, so it doesn't necessarily constitute a move out of the binder. |
| 1187 | UnwrapUnsafeBinder(T), |
| 1188 | |
| 1189 | /// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where |
| 1190 | /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping |
| 1191 | /// explicit during optimizations and codegen. |
| 1192 | /// |
| 1193 | /// This projection doesn't impact the runtime behavior of the program except for potentially changing |
| 1194 | /// some type metadata of the interpreter or codegen backend. |
| 1195 | /// |
| 1196 | /// This goal is achieved with mir_transform pass `Subtyper`, which runs right after |
| 1197 | /// borrowchecker, as we only care about subtyping that can affect trait selection and |
| 1198 | /// `TypeId`. |
| 1199 | Subtype(T), |
| 1200 | } |
| 1201 | |
| 1202 | /// Alias for projections as they appear in places, where the base is a place |
| 1203 | /// and the index is a local. |
| 1204 | pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>; |
| 1205 | |
| 1206 | /////////////////////////////////////////////////////////////////////////// |
| 1207 | // Operands |
| 1208 | |
| 1209 | /// An operand in MIR represents a "value" in Rust, the definition of which is undecided and part of |
| 1210 | /// the memory model. One proposal for a definition of values can be found [on UCG][value-def]. |
| 1211 | /// |
| 1212 | /// [value-def]: https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/value-domain.md |
| 1213 | /// |
| 1214 | /// The most common way to create values is via loading a place. Loading a place is an operation |
| 1215 | /// which reads the memory of the place and converts it to a value. This is a fundamentally *typed* |
| 1216 | /// operation. The nature of the value produced depends on the type of the conversion. Furthermore, |
| 1217 | /// there may be other effects: if the type has a validity constraint loading the place might be UB |
| 1218 | /// if the validity constraint is not met. |
| 1219 | /// |
| 1220 | /// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri |
| 1221 | /// currently implements it, but it seems like this may be something to check against in the |
| 1222 | /// validator. |
| 1223 | #[derive (Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] |
| 1224 | pub enum Operand<'tcx> { |
| 1225 | /// Creates a value by loading the given place. |
| 1226 | /// |
| 1227 | /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there |
| 1228 | /// is no such requirement. |
| 1229 | Copy(Place<'tcx>), |
| 1230 | |
| 1231 | /// Creates a value by performing loading the place, just like the `Copy` operand. |
| 1232 | /// |
| 1233 | /// This *may* additionally overwrite the place with `uninit` bytes, depending on how we decide |
| 1234 | /// in [UCG#188]. You should not emit MIR that may attempt a subsequent second load of this |
| 1235 | /// place without first re-initializing it. |
| 1236 | /// |
| 1237 | /// **Needs clarification:** The operational impact of `Move` is unclear. Currently (both in |
| 1238 | /// Miri and codegen) it has no effect at all unless it appears in an argument to `Call`; for |
| 1239 | /// `Call` it allows the argument to be passed to the callee "in-place", i.e. the callee might |
| 1240 | /// just get a reference to this place instead of a full copy. Miri implements this with a |
| 1241 | /// combination of aliasing model "protectors" and putting `uninit` into the place. Ralf |
| 1242 | /// proposes that we don't want these semantics for `Move` in regular assignments, because |
| 1243 | /// loading a place should not have side-effects, and the aliasing model "protectors" are |
| 1244 | /// inherently tied to a function call. Are these the semantics we want for MIR? Is this |
| 1245 | /// something we can even decide without knowing more about Rust's memory model? |
| 1246 | /// |
| 1247 | /// [UCG#188]: https://github.com/rust-lang/unsafe-code-guidelines/issues/188 |
| 1248 | Move(Place<'tcx>), |
| 1249 | |
| 1250 | /// Constants are already semantically values, and remain unchanged. |
| 1251 | Constant(Box<ConstOperand<'tcx>>), |
| 1252 | } |
| 1253 | |
| 1254 | #[derive (Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 1255 | #[derive (TypeFoldable, TypeVisitable)] |
| 1256 | pub struct ConstOperand<'tcx> { |
| 1257 | pub span: Span, |
| 1258 | |
| 1259 | /// Optional user-given type: for something like |
| 1260 | /// `collect::<Vec<_>>`, this would be present and would |
| 1261 | /// indicate that `Vec<_>` was explicitly specified. |
| 1262 | /// |
| 1263 | /// Needed for NLL to impose user-given type constraints. |
| 1264 | pub user_ty: Option<UserTypeAnnotationIndex>, |
| 1265 | |
| 1266 | pub const_: Const<'tcx>, |
| 1267 | } |
| 1268 | |
| 1269 | /////////////////////////////////////////////////////////////////////////// |
| 1270 | // Rvalues |
| 1271 | |
| 1272 | /// The various kinds of rvalues that can appear in MIR. |
| 1273 | /// |
| 1274 | /// Not all of these are allowed at every [`MirPhase`] - when this is the case, it's stated below. |
| 1275 | /// |
| 1276 | /// Computing any rvalue begins by evaluating the places and operands in some order (**Needs |
| 1277 | /// clarification**: Which order?). These are then used to produce a "value" - the same kind of |
| 1278 | /// value that an [`Operand`] produces. |
| 1279 | #[derive (Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] |
| 1280 | pub enum Rvalue<'tcx> { |
| 1281 | /// Yields the operand unchanged |
| 1282 | Use(Operand<'tcx>), |
| 1283 | |
| 1284 | /// Creates an array where each element is the value of the operand. |
| 1285 | /// |
| 1286 | /// This is the cause of a bug in the case where the repetition count is zero because the value |
| 1287 | /// is not dropped, see [#74836]. |
| 1288 | /// |
| 1289 | /// Corresponds to source code like `[x; 32]`. |
| 1290 | /// |
| 1291 | /// [#74836]: https://github.com/rust-lang/rust/issues/74836 |
| 1292 | Repeat(Operand<'tcx>, ty::Const<'tcx>), |
| 1293 | |
| 1294 | /// Creates a reference of the indicated kind to the place. |
| 1295 | /// |
| 1296 | /// There is not much to document here, because besides the obvious parts the semantics of this |
| 1297 | /// are essentially entirely a part of the aliasing model. There are many UCG issues discussing |
| 1298 | /// exactly what the behavior of this operation should be. |
| 1299 | /// |
| 1300 | /// `Shallow` borrows are disallowed after drop lowering. |
| 1301 | Ref(Region<'tcx>, BorrowKind, Place<'tcx>), |
| 1302 | |
| 1303 | /// Creates a pointer/reference to the given thread local. |
| 1304 | /// |
| 1305 | /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a |
| 1306 | /// `*const T`, and if neither of those apply a `&T`. |
| 1307 | /// |
| 1308 | /// **Note:** This is a runtime operation that actually executes code and is in this sense more |
| 1309 | /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to |
| 1310 | /// SIGILL for some reason that I (JakobDegen) never got a chance to look into. |
| 1311 | /// |
| 1312 | /// **Needs clarification**: Are there weird additional semantics here related to the runtime |
| 1313 | /// nature of this operation? |
| 1314 | ThreadLocalRef(DefId), |
| 1315 | |
| 1316 | /// Creates a raw pointer with the indicated mutability to the place. |
| 1317 | /// |
| 1318 | /// This is generated by pointer casts like `&v as *const _` or raw borrow expressions like |
| 1319 | /// `&raw const v`. |
| 1320 | /// |
| 1321 | /// Like with references, the semantics of this operation are heavily dependent on the aliasing |
| 1322 | /// model. |
| 1323 | RawPtr(RawPtrKind, Place<'tcx>), |
| 1324 | |
| 1325 | /// Yields the length of the place, as a `usize`. |
| 1326 | /// |
| 1327 | /// If the type of the place is an array, this is the array length. For slices (`[T]`, not |
| 1328 | /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is |
| 1329 | /// ill-formed for places of other types. |
| 1330 | /// |
| 1331 | /// This cannot be a `UnOp(PtrMetadata, _)` because that expects a value, and we only |
| 1332 | /// have a place, and `UnOp(PtrMetadata, RawPtr(place))` is not a thing. |
| 1333 | Len(Place<'tcx>), |
| 1334 | |
| 1335 | /// Performs essentially all of the casts that can be performed via `as`. |
| 1336 | /// |
| 1337 | /// This allows for casts from/to a variety of types. |
| 1338 | /// |
| 1339 | /// **FIXME**: Document exactly which `CastKind`s allow which types of casts. |
| 1340 | Cast(CastKind, Operand<'tcx>, Ty<'tcx>), |
| 1341 | |
| 1342 | /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second |
| 1343 | /// parameter may be a `usize` as well. |
| 1344 | /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, |
| 1345 | /// raw pointers, or function pointers and return a `bool`. The types of the operands must be |
| 1346 | /// matching, up to the usual caveat of the lifetimes in function pointers. |
| 1347 | /// * Left and right shift operations accept signed or unsigned integers not necessarily of the |
| 1348 | /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is |
| 1349 | /// truncated as needed. |
| 1350 | /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching |
| 1351 | /// types and return a value of that type. |
| 1352 | /// * The `FooWithOverflow` are like the `Foo`, but returning `(T, bool)` instead of just `T`, |
| 1353 | /// where the `bool` is true if the result is not equal to the infinite-precision result. |
| 1354 | /// * The remaining operations accept signed integers, unsigned integers, or floats with |
| 1355 | /// matching types and return a value of that type. |
| 1356 | BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), |
| 1357 | |
| 1358 | /// Computes a value as described by the operation. |
| 1359 | NullaryOp(NullOp<'tcx>, Ty<'tcx>), |
| 1360 | |
| 1361 | /// Exactly like `BinaryOp`, but less operands. |
| 1362 | /// |
| 1363 | /// Also does two's-complement arithmetic. Negation requires a signed integer or a float; |
| 1364 | /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds |
| 1365 | /// return a value with the same type as their operand. |
| 1366 | UnaryOp(UnOp, Operand<'tcx>), |
| 1367 | |
| 1368 | /// Computes the discriminant of the place, returning it as an integer of type |
| 1369 | /// [`discriminant_ty`]. Returns zero for types without discriminant. |
| 1370 | /// |
| 1371 | /// The validity requirements for the underlying value are undecided for this rvalue, see |
| 1372 | /// [#91095]. Note too that the value of the discriminant is not the same thing as the |
| 1373 | /// variant index; use [`discriminant_for_variant`] to convert. |
| 1374 | /// |
| 1375 | /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty |
| 1376 | /// [#91095]: https://github.com/rust-lang/rust/issues/91095 |
| 1377 | /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant |
| 1378 | Discriminant(Place<'tcx>), |
| 1379 | |
| 1380 | /// Creates an aggregate value, like a tuple or struct. |
| 1381 | /// |
| 1382 | /// This is needed because dataflow analysis needs to distinguish |
| 1383 | /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo` |
| 1384 | /// has a destructor. |
| 1385 | /// |
| 1386 | /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After |
| 1387 | /// coroutine lowering, `Coroutine` aggregate kinds are disallowed too. |
| 1388 | Aggregate(Box<AggregateKind<'tcx>>, IndexVec<FieldIdx, Operand<'tcx>>), |
| 1389 | |
| 1390 | /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`. |
| 1391 | /// |
| 1392 | /// This is different from a normal transmute because dataflow analysis will treat the box as |
| 1393 | /// initialized but its content as uninitialized. Like other pointer casts, this in general |
| 1394 | /// affects alias analysis. |
| 1395 | ShallowInitBox(Operand<'tcx>, Ty<'tcx>), |
| 1396 | |
| 1397 | /// A CopyForDeref is equivalent to a read from a place at the |
| 1398 | /// codegen level, but is treated specially by drop elaboration. When such a read happens, it |
| 1399 | /// is guaranteed (via nature of the mir_opt `Derefer` in rustc_mir_transform/src/deref_separator) |
| 1400 | /// that the only use of the returned value is a deref operation, immediately |
| 1401 | /// followed by one or more projections. Drop elaboration treats this rvalue as if the |
| 1402 | /// read never happened and just projects further. This allows simplifying various MIR |
| 1403 | /// optimizations and codegen backends that previously had to handle deref operations anywhere |
| 1404 | /// in a place. |
| 1405 | CopyForDeref(Place<'tcx>), |
| 1406 | |
| 1407 | /// Wraps a value in an unsafe binder. |
| 1408 | WrapUnsafeBinder(Operand<'tcx>, Ty<'tcx>), |
| 1409 | } |
| 1410 | |
| 1411 | #[derive (Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 1412 | pub enum CastKind { |
| 1413 | /// An exposing pointer to address cast. A cast between a pointer and an integer type, or |
| 1414 | /// between a function pointer and an integer type. |
| 1415 | /// See the docs on `expose_provenance` for more details. |
| 1416 | PointerExposeProvenance, |
| 1417 | /// An address-to-pointer cast that picks up an exposed provenance. |
| 1418 | /// See the docs on `with_exposed_provenance` for more details. |
| 1419 | PointerWithExposedProvenance, |
| 1420 | /// Pointer related casts that are done by coercions. Note that reference-to-raw-ptr casts are |
| 1421 | /// translated into `&raw mut/const *r`, i.e., they are not actually casts. |
| 1422 | /// |
| 1423 | /// The following are allowed in [`AnalysisPhase::Initial`] as they're needed for borrowck, |
| 1424 | /// but after that are forbidden (including in all phases of runtime MIR): |
| 1425 | /// * [`PointerCoercion::ArrayToPointer`] |
| 1426 | /// * [`PointerCoercion::MutToConstPointer`] |
| 1427 | /// |
| 1428 | /// Both are runtime nops, so should be [`CastKind::PtrToPtr`] instead in runtime MIR. |
| 1429 | PointerCoercion(PointerCoercion, CoercionSource), |
| 1430 | IntToInt, |
| 1431 | FloatToInt, |
| 1432 | FloatToFloat, |
| 1433 | IntToFloat, |
| 1434 | PtrToPtr, |
| 1435 | FnPtrToPtr, |
| 1436 | /// Reinterpret the bits of the input as a different type. |
| 1437 | /// |
| 1438 | /// MIR is well-formed if the input and output types have different sizes, |
| 1439 | /// but running a transmute between differently-sized types is UB. |
| 1440 | /// |
| 1441 | /// Allowed only in [`MirPhase::Runtime`]; Earlier it's a [`TerminatorKind::Call`]. |
| 1442 | Transmute, |
| 1443 | } |
| 1444 | |
| 1445 | /// Represents how a [`CastKind::PointerCoercion`] was constructed. |
| 1446 | /// Used only for diagnostics. |
| 1447 | #[derive (Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 1448 | pub enum CoercionSource { |
| 1449 | /// The coercion was manually written by the user with an `as` cast. |
| 1450 | AsCast, |
| 1451 | /// The coercion was automatically inserted by the compiler. |
| 1452 | Implicit, |
| 1453 | } |
| 1454 | |
| 1455 | #[derive (Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 1456 | #[derive (TypeFoldable, TypeVisitable)] |
| 1457 | pub enum AggregateKind<'tcx> { |
| 1458 | /// The type is of the element |
| 1459 | Array(Ty<'tcx>), |
| 1460 | Tuple, |
| 1461 | |
| 1462 | /// The second field is the variant index. It's equal to 0 for struct |
| 1463 | /// and union expressions. The last field is the |
| 1464 | /// active field number and is present only for union expressions |
| 1465 | /// -- e.g., for a union expression `SomeUnion { c: .. }`, the |
| 1466 | /// active field index would identity the field `c` |
| 1467 | Adt(DefId, VariantIdx, GenericArgsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>), |
| 1468 | |
| 1469 | Closure(DefId, GenericArgsRef<'tcx>), |
| 1470 | Coroutine(DefId, GenericArgsRef<'tcx>), |
| 1471 | CoroutineClosure(DefId, GenericArgsRef<'tcx>), |
| 1472 | |
| 1473 | /// Construct a raw pointer from the data pointer and metadata. |
| 1474 | /// |
| 1475 | /// The `Ty` here is the type of the *pointee*, not the pointer itself. |
| 1476 | /// The `Mutability` indicates whether this produces a `*const` or `*mut`. |
| 1477 | /// |
| 1478 | /// The [`Rvalue::Aggregate`] operands for thus must be |
| 1479 | /// |
| 1480 | /// 0. A raw pointer of matching mutability with any [`core::ptr::Thin`] pointee |
| 1481 | /// 1. A value of the appropriate [`core::ptr::Pointee::Metadata`] type |
| 1482 | /// |
| 1483 | /// *Both* operands must always be included, even the unit value if this is |
| 1484 | /// creating a thin pointer. If you're just converting between thin pointers, |
| 1485 | /// you may want an [`Rvalue::Cast`] with [`CastKind::PtrToPtr`] instead. |
| 1486 | RawPtr(Ty<'tcx>, Mutability), |
| 1487 | } |
| 1488 | |
| 1489 | #[derive (Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] |
| 1490 | pub enum NullOp<'tcx> { |
| 1491 | /// Returns the size of a value of that type |
| 1492 | SizeOf, |
| 1493 | /// Returns the minimum alignment of a type |
| 1494 | AlignOf, |
| 1495 | /// Returns the offset of a field |
| 1496 | OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>), |
| 1497 | /// Returns whether we should perform some UB-checking at runtime. |
| 1498 | /// See the `ub_checks` intrinsic docs for details. |
| 1499 | UbChecks, |
| 1500 | /// Returns whether we should perform contract-checking at runtime. |
| 1501 | /// See the `contract_checks` intrinsic docs for details. |
| 1502 | ContractChecks, |
| 1503 | } |
| 1504 | |
| 1505 | #[derive (Copy, Clone, Debug, PartialEq, Eq, Hash)] |
| 1506 | #[derive (HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] |
| 1507 | pub enum UnOp { |
| 1508 | /// The `!` operator for logical inversion |
| 1509 | Not, |
| 1510 | /// The `-` operator for negation |
| 1511 | Neg, |
| 1512 | /// Gets the metadata `M` from a `*const`/`*mut`/`&`/`&mut` to |
| 1513 | /// `impl Pointee<Metadata = M>`. |
| 1514 | /// |
| 1515 | /// For example, this will give a `()` from `*const i32`, a `usize` from |
| 1516 | /// `&mut [u8]`, or a `ptr::DynMetadata<dyn Foo>` (internally a pointer) |
| 1517 | /// from a `*mut dyn Foo`. |
| 1518 | /// |
| 1519 | /// Allowed only in [`MirPhase::Runtime`]; earlier it's an intrinsic. |
| 1520 | PtrMetadata, |
| 1521 | } |
| 1522 | |
| 1523 | #[derive (Copy, Clone, Debug, PartialEq, Eq, Hash)] |
| 1524 | #[derive (TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] |
| 1525 | pub enum BinOp { |
| 1526 | /// The `+` operator (addition) |
| 1527 | Add, |
| 1528 | /// Like `Add`, but with UB on overflow. (Integers only.) |
| 1529 | AddUnchecked, |
| 1530 | /// Like `Add`, but returns `(T, bool)` of both the wrapped result |
| 1531 | /// and a bool indicating whether it overflowed. |
| 1532 | AddWithOverflow, |
| 1533 | /// The `-` operator (subtraction) |
| 1534 | Sub, |
| 1535 | /// Like `Sub`, but with UB on overflow. (Integers only.) |
| 1536 | SubUnchecked, |
| 1537 | /// Like `Sub`, but returns `(T, bool)` of both the wrapped result |
| 1538 | /// and a bool indicating whether it overflowed. |
| 1539 | SubWithOverflow, |
| 1540 | /// The `*` operator (multiplication) |
| 1541 | Mul, |
| 1542 | /// Like `Mul`, but with UB on overflow. (Integers only.) |
| 1543 | MulUnchecked, |
| 1544 | /// Like `Mul`, but returns `(T, bool)` of both the wrapped result |
| 1545 | /// and a bool indicating whether it overflowed. |
| 1546 | MulWithOverflow, |
| 1547 | /// The `/` operator (division) |
| 1548 | /// |
| 1549 | /// For integer types, division by zero is UB, as is `MIN / -1` for signed. |
| 1550 | /// The compiler should have inserted checks prior to this. |
| 1551 | /// |
| 1552 | /// Floating-point division by zero is safe, and does not need guards. |
| 1553 | Div, |
| 1554 | /// The `%` operator (modulus) |
| 1555 | /// |
| 1556 | /// For integer types, using zero as the modulus (second operand) is UB, |
| 1557 | /// as is `MIN % -1` for signed. |
| 1558 | /// The compiler should have inserted checks prior to this. |
| 1559 | /// |
| 1560 | /// Floating-point remainder by zero is safe, and does not need guards. |
| 1561 | Rem, |
| 1562 | /// The `^` operator (bitwise xor) |
| 1563 | BitXor, |
| 1564 | /// The `&` operator (bitwise and) |
| 1565 | BitAnd, |
| 1566 | /// The `|` operator (bitwise or) |
| 1567 | BitOr, |
| 1568 | /// The `<<` operator (shift left) |
| 1569 | /// |
| 1570 | /// The offset is given by `RHS.rem_euclid(LHS::BITS)`. |
| 1571 | /// In other words, it is (uniquely) determined as follows: |
| 1572 | /// - it is "equal modulo LHS::BITS" to the RHS |
| 1573 | /// - it is in the range `0..LHS::BITS` |
| 1574 | Shl, |
| 1575 | /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0 |
| 1576 | ShlUnchecked, |
| 1577 | /// The `>>` operator (shift right) |
| 1578 | /// |
| 1579 | /// The offset is given by `RHS.rem_euclid(LHS::BITS)`. |
| 1580 | /// In other words, it is (uniquely) determined as follows: |
| 1581 | /// - it is "equal modulo LHS::BITS" to the RHS |
| 1582 | /// - it is in the range `0..LHS::BITS` |
| 1583 | /// |
| 1584 | /// This is an arithmetic shift if the LHS is signed |
| 1585 | /// and a logical shift if the LHS is unsigned. |
| 1586 | Shr, |
| 1587 | /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0 |
| 1588 | ShrUnchecked, |
| 1589 | /// The `==` operator (equality) |
| 1590 | Eq, |
| 1591 | /// The `<` operator (less than) |
| 1592 | Lt, |
| 1593 | /// The `<=` operator (less than or equal to) |
| 1594 | Le, |
| 1595 | /// The `!=` operator (not equal to) |
| 1596 | Ne, |
| 1597 | /// The `>=` operator (greater than or equal to) |
| 1598 | Ge, |
| 1599 | /// The `>` operator (greater than) |
| 1600 | Gt, |
| 1601 | /// The `<=>` operator (three-way comparison, like `Ord::cmp`) |
| 1602 | /// |
| 1603 | /// This is supported only on the integer types and `char`, always returning |
| 1604 | /// [`rustc_hir::LangItem::OrderingEnum`] (aka [`std::cmp::Ordering`]). |
| 1605 | /// |
| 1606 | /// [`Rvalue::BinaryOp`]`(BinOp::Cmp, A, B)` returns |
| 1607 | /// - `Ordering::Less` (`-1_i8`, as a Scalar) if `A < B` |
| 1608 | /// - `Ordering::Equal` (`0_i8`, as a Scalar) if `A == B` |
| 1609 | /// - `Ordering::Greater` (`+1_i8`, as a Scalar) if `A > B` |
| 1610 | Cmp, |
| 1611 | /// The `ptr.offset` operator |
| 1612 | Offset, |
| 1613 | } |
| 1614 | |
| 1615 | // Some nodes are used a lot. Make sure they don't unintentionally get bigger. |
| 1616 | #[cfg (target_pointer_width = "64" )] |
| 1617 | mod size_asserts { |
| 1618 | use rustc_data_structures::static_assert_size; |
| 1619 | |
| 1620 | use super::*; |
| 1621 | // tidy-alphabetical-start |
| 1622 | static_assert_size!(AggregateKind<'_>, 32); |
| 1623 | static_assert_size!(Operand<'_>, 24); |
| 1624 | static_assert_size!(Place<'_>, 16); |
| 1625 | static_assert_size!(PlaceElem<'_>, 24); |
| 1626 | static_assert_size!(Rvalue<'_>, 40); |
| 1627 | static_assert_size!(StatementKind<'_>, 16); |
| 1628 | static_assert_size!(TerminatorKind<'_>, 80); |
| 1629 | // tidy-alphabetical-end |
| 1630 | } |
| 1631 | |