about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2025-02-18 14:33:59 +1100
committerNicholas Nethercote <n.nethercote@gmail.com>2025-02-20 10:28:50 +1100
commitc039533656d344b465cf95da721197a6fdd3d7f7 (patch)
tree3e2cd7b5e0db8b521af2cc1575e6c31efcadaa9a
parentc9fbaab4533f109ce4e7b56ab8d3df0a49c46ffb (diff)
downloadrust-c039533656d344b465cf95da721197a6fdd3d7f7.tar.gz
rust-c039533656d344b465cf95da721197a6fdd3d7f7.zip
Improve MIR phase comments.
I found the dialect/phase distinction quite confusing when I first read
these comments. This commit clarifies things a bit.
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs51
1 files changed, 29 insertions, 22 deletions
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 69c19ae7b9c..b63c4d172f2 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -23,44 +23,49 @@ use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex}
 
 /// Represents the "flavors" of MIR.
 ///
-/// All flavors of MIR use the same data structure, but there are some important differences. These
-/// differences come in two forms: Dialects and phases.
+/// The MIR pipeline is structured into a few major dialects, with one or more phases within each
+/// dialect. A MIR flavor is identified by a dialect-phase pair. A single `MirPhase` value
+/// specifies such a pair. All flavors of MIR use the same data structure to represent the program.
 ///
-/// Dialects represent a stronger distinction than phases. This is because the transitions between
-/// dialects are semantic changes, and therefore technically *lowerings* between distinct IRs. In
-/// other words, the same [`Body`](crate::mir::Body) might be well-formed for multiple dialects, but
-/// have different semantic meaning and different behavior at runtime.
+/// Different MIR dialects have different semantics. (The differences between dialects are small,
+/// but they do exist.) The progression from one MIR dialect to the next is technically a lowering
+/// from one IR to another. In other words, a single well-formed [`Body`](crate::mir::Body) might
+/// have different semantic meaning and different behavior at runtime in the different dialects.
+/// The specific differences between dialects are described on the variants below.
 ///
-/// Each dialect additionally has a number of phases. However, phase changes never involve semantic
-/// changes. If some MIR is well-formed both before and after a phase change, it is also guaranteed
-/// that it has the same semantic meaning. In this sense, phase changes can only add additional
-/// restrictions on what MIR is well-formed.
+/// Phases exist only to place restrictions on what language constructs are permitted in
+/// well-formed MIR, and subsequent phases mostly increase those restrictions. I.e. to convert MIR
+/// from one phase to the next might require removing/replacing certain MIR constructs.
 ///
-/// When adding phases, remember to update [`MirPhase::phase_index`].
+/// When adding dialects or phases, remember to update [`MirPhase::phase_index`].
 #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
 #[derive(HashStable)]
 pub enum MirPhase {
-    /// The MIR that is generated by MIR building.
+    /// The "built MIR" dialect, as generated by MIR building.
     ///
     /// The only things that operate on this dialect are unsafeck, the various MIR lints, and const
     /// qualifs.
     ///
-    /// This has no distinct phases.
+    /// This dialect has just the one (implicit) phase, which places few restrictions on what MIR
+    /// constructs are allowed.
     Built,
-    /// The MIR used for most analysis.
+
+    /// The "analysis MIR" dialect, used for borrowck and friends.
     ///
-    /// The only semantic change between analysis and built MIR is constant promotion. In built MIR,
-    /// sequences of statements that would generally be subject to constant promotion are
-    /// semantically constants, while in analysis MIR all constants are explicit.
+    /// The only semantic difference between built MIR and analysis MIR relates to constant
+    /// promotion. In built MIR, sequences of statements that would generally be subject to
+    /// constant promotion are semantically constants, while in analysis MIR all constants are
+    /// explicit.
     ///
     /// The result of const promotion is available from the `mir_promoted` and `promoted_mir`
     /// queries.
     ///
-    /// This is the version of MIR used by borrowck and friends.
+    /// The phases of this dialect are described in `AnalysisPhase`.
     Analysis(AnalysisPhase),
-    /// The MIR used for CTFE, optimizations, and codegen.
+
+    /// The "runtime MIR" dialect, used for CTFE, optimizations, and codegen.
     ///
-    /// The semantic changes that occur in the lowering from analysis to runtime MIR are as follows:
+    /// The semantic differences between analysis MIR and runtime MIR are as follows.
     ///
     /// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly
     ///   speaking, if dataflow analysis determines that the place being dropped is uninitialized,
@@ -80,13 +85,15 @@ pub enum MirPhase {
     ///   retags can still occur at `Rvalue::{Ref,AddrOf}`).
     /// - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code
     ///   has access to. This occurs in coroutine bodies. Such locals do not behave like other
-    ///   locals, because they eg may be aliased in surprising ways. Runtime MIR has no such
+    ///   locals, because they e.g. may be aliased in surprising ways. Runtime MIR has no such
     ///   special locals. All coroutine bodies are lowered and so all places that look like locals
     ///   really are locals.
     ///
     /// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part
     /// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that
-    /// transformations which may suppress such errors should not run on analysis MIR.
+    /// transformations that can suppress such errors should not run on analysis MIR.
+    ///
+    /// The phases of this dialect are described in `RuntimePhase`.
     Runtime(RuntimePhase),
 }