about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Sextl <florian.sextl@tuwien.ac.at>2025-06-27 13:04:16 +0200
committerFlorian Sextl <florian.sextl@tuwien.ac.at>2025-06-28 13:54:51 +0200
commitac6cfdef131b236609ad4e9d82a8474303b26d1b (patch)
tree09959cfcf51b611ba8e6224f64d7f113df83d551
parentd41e12f1f4e4884c356f319b881921aa37040de5 (diff)
downloadrust-ac6cfdef131b236609ad4e9d82a8474303b26d1b.tar.gz
rust-ac6cfdef131b236609ad4e9d82a8474303b26d1b.zip
improve TagEncoding docs
-rw-r--r--compiler/rustc_abi/src/lib.rs33
1 files changed, 21 insertions, 12 deletions
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 6d729b6919a..b38ee52b796 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1592,24 +1592,33 @@ pub enum TagEncoding<VariantIdx: Idx> {
     /// (so converting the tag to the discriminant can require sign extension).
     Direct,
 
-    /// Niche (values invalid for a type) encoding the discriminant:
-    /// Discriminant and variant index coincide.
+    /// Niche (values invalid for a type) encoding the discriminant.
+    /// Note that for this encoding, the discriminant and variant index of each variant coincide!
+    /// (This gets checked, for example, in [codegen_ssa](https://github.com/rust-lang/rust/blob/df32e15c56f582eb2bdde07711af6271f2ae660b/compiler/rustc_codegen_ssa/src/mir/operand.rs#L485).)
+    /// 
     /// The variant `untagged_variant` contains a niche at an arbitrary
-    /// offset (field `tag_field` of the enum), which for a variant with
-    /// discriminant `d` is set to
-    /// `(d - niche_variants.start).wrapping_add(niche_start)`
-    /// (this is wrapping arithmetic using the type of the niche field).
-    ///
-    /// For example, `Option<(usize, &T)>`  is represented such that
-    /// `None` has a null pointer for the second tuple field, and
-    /// `Some` is the identity function (with a non-null reference).
+    /// offset (field [`Variants::Multiple::tag_field`] of the enum).
+    /// For a variant with variant index `i`, such that `i!=untagged_variant`,
+    /// the tag is set to `(i - niche_variants.start).wrapping_add(niche_start)`
+    /// (this is wrapping arithmetic using the type of the niche field, cf. the 
+    /// [`tag_for_variant`](../rustc_const_eval/interpret/struct.InterpCx.html#method.tag_for_variant)
+    /// query implementation).
+    /// To recover the variant index `i` from a `tag`, the above formula has to be reversed,
+    /// i.e. `i = (tag.wrapping_sub(niche_start))+niche_variants.start`. If `i` ends up outside
+    /// `niche_variants`, the tag must have encoded the `untagged_variant`.
+    /// 
+    /// For example, `Option<(usize, &T)>`  is represented such that the tag for
+    /// `None` is the null pointer in the second tuple field, and
+    /// `Some` is the identity function (with a non-null reference) 
+    /// and has no additional tag, i.e. the reference being non-null uniquely identifies this variant.
     ///
     /// Other variants that are not `untagged_variant` and that are outside the `niche_variants`
     /// range cannot be represented; they must be uninhabited.
+    /// Nonetheless, uninhabited variants can also fall into the range of `niche_variants`.
     Niche {
         untagged_variant: VariantIdx,
-        /// This range *may* contain `untagged_variant`; that is then just a "dead value" and
-        /// not used to encode anything.
+        /// This range *may* contain `untagged_variant` or uninhabited variants; 
+        /// these are then just "dead values" and not used to encode anything.
         niche_variants: RangeInclusive<VariantIdx>,
         /// This is inbounds of the type of the niche field
         /// (not sign-extended, i.e., all bits beyond the niche field size are 0).