diff options
| author | Florian Sextl <florian.sextl@tuwien.ac.at> | 2025-06-27 13:04:16 +0200 |
|---|---|---|
| committer | Florian Sextl <florian.sextl@tuwien.ac.at> | 2025-06-28 13:54:51 +0200 |
| commit | ac6cfdef131b236609ad4e9d82a8474303b26d1b (patch) | |
| tree | 09959cfcf51b611ba8e6224f64d7f113df83d551 | |
| parent | d41e12f1f4e4884c356f319b881921aa37040de5 (diff) | |
| download | rust-ac6cfdef131b236609ad4e9d82a8474303b26d1b.tar.gz rust-ac6cfdef131b236609ad4e9d82a8474303b26d1b.zip | |
improve TagEncoding docs
| -rw-r--r-- | compiler/rustc_abi/src/lib.rs | 33 |
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). |
