@@ -1592,24 +1592,33 @@ pub enum TagEncoding<VariantIdx: Idx> {
15921592 /// (so converting the tag to the discriminant can require sign extension).
15931593 Direct ,
15941594
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+ ///
15971599 /// 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`.
16021609 ///
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.
16061614 ///
16071615 /// Other variants that are not `untagged_variant` and that are outside the `niche_variants`
16081616 /// range cannot be represented; they must be uninhabited.
1617+ /// Nonetheless, uninhabited variants can also fall into the range of `niche_variants`.
16091618 Niche {
16101619 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.
16131622 niche_variants : RangeInclusive < VariantIdx > ,
16141623 /// This is inbounds of the type of the niche field
16151624 /// (not sign-extended, i.e., all bits beyond the niche field size are 0).
0 commit comments