@@ -1592,24 +1592,33 @@ pub enum TagEncoding<VariantIdx: Idx> {
1592
1592
/// (so converting the tag to the discriminant can require sign extension).
1593
1593
Direct ,
1594
1594
1595
- /// Niche (values invalid for a type) encoding the discriminant:
1596
- /// Discriminant and variant index coincide.
1595
+ /// Niche (values invalid for a type) encoding the discriminant.
1596
+ /// Note that for this encoding, the discriminant and variant index of each variant coincide!
1597
+ /// This invariant is codified as part of [`layout_sanity_check`](../rustc_ty_utils/layout/invariant/fn.layout_sanity_check.html).
1598
+ ///
1597
1599
/// The variant `untagged_variant` contains a niche at an arbitrary
1598
- /// offset (field `tag_field` of the enum), which for a variant with
1599
- /// discriminant `d` is set to
1600
- /// `(d - niche_variants.start).wrapping_add(niche_start)`
1601
- /// (this is wrapping arithmetic using the type of the niche field).
1600
+ /// offset (field [`Variants::Multiple::tag_field`] of the enum).
1601
+ /// For a variant with variant index `i`, such that `i != untagged_variant`,
1602
+ /// the tag is set to `(i - niche_variants.start).wrapping_add(niche_start)`
1603
+ /// (this is wrapping arithmetic using the type of the niche field, cf. the
1604
+ /// [`tag_for_variant`](../rustc_const_eval/interpret/struct.InterpCx.html#method.tag_for_variant)
1605
+ /// query implementation).
1606
+ /// To recover the variant index `i` from a `tag`, the above formula has to be reversed,
1607
+ /// i.e. `i = tag.wrapping_sub(niche_start) + niche_variants.start`. If `i` ends up outside
1608
+ /// `niche_variants`, the tag must have encoded the `untagged_variant`.
1602
1609
///
1603
- /// For example, `Option<(usize, &T)>` is represented such that
1604
- /// `None` has a null pointer for the second tuple field, and
1605
- /// `Some` is the identity function (with a non-null reference).
1610
+ /// For example, `Option<(usize, &T)>` is represented such that the tag for
1611
+ /// `None` is the null pointer in the second tuple field, and
1612
+ /// `Some` is the identity function (with a non-null reference)
1613
+ /// and has no additional tag, i.e. the reference being non-null uniquely identifies this variant.
1606
1614
///
1607
1615
/// Other variants that are not `untagged_variant` and that are outside the `niche_variants`
1608
1616
/// range cannot be represented; they must be uninhabited.
1617
+ /// Nonetheless, uninhabited variants can also fall into the range of `niche_variants`.
1609
1618
Niche {
1610
1619
untagged_variant : VariantIdx ,
1611
- /// This range *may* contain `untagged_variant`; that is then just a "dead value" and
1612
- /// not used to encode anything.
1620
+ /// This range *may* contain `untagged_variant` or uninhabited variants;
1621
+ /// these are then just "dead values" and not used to encode anything.
1613
1622
niche_variants : RangeInclusive < VariantIdx > ,
1614
1623
/// This is inbounds of the type of the niche field
1615
1624
/// (not sign-extended, i.e., all bits beyond the niche field size are 0).
0 commit comments