rustc_middle/mir/syntax.rs
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
6use rustc_abi::{FieldIdx, VariantIdx};
7use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece, Mutability};
8use rustc_data_structures::packed::Pu128;
9use rustc_hir::CoroutineKind;
10use rustc_hir::def_id::DefId;
11use rustc_index::IndexVec;
12use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
13use rustc_span::def_id::LocalDefId;
14use rustc_span::source_map::Spanned;
15use rustc_span::{Span, Symbol};
16use rustc_target::asm::InlineAsmRegOrRegClass;
17use smallvec::SmallVec;
18
19use super::{BasicBlock, Const, Local, UserTypeProjection};
20use crate::mir::coverage::CoverageKind;
21use crate::ty::adjustment::PointerCoercion;
22use 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)]
43pub 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)]
103pub 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)]
125pub 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)]
151pub 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)]
182pub 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)]
198pub 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)]
248pub 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)]
307pub 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)]
479pub 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]
507pub 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)]
520pub 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)]
576pub 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)]
587pub 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
606pub 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)]
644pub 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)]
910pub enum BackwardIncompatibleDropReason {
911 Edition2024,
912}
913
914#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
915pub 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)]
946pub 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)]
965pub 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)]
976pub 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)]
990pub 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.
1022pub 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)]
1104pub 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)]
1113pub 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.
1204pub 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)]
1224pub 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)]
1256pub 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)]
1280pub 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)]
1412pub 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)]
1448pub 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)]
1457pub 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)]
1490pub 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)]
1507pub 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)]
1525pub 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")]
1617mod 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}