Support enum variants in offset_of! by GKFX · Pull Request #114208 · rust-lang/rust (original) (raw)

Some discussion w.r.t. syntax on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/.60offset_of!.60.20Syntax

My proposed bikeshed color: offset_of!(Type, field, as Enum::Variant, field), with Enum::Variant being a name-resolved item path (like Type, unlike fields). This separates the items/types/variants from fields predictably.

macro_rules! matcher syntax

macro_rules! offset_of { ($Container:ty, (((($midfields:tt).+, as $Variant:path,)* (((fields:tt).+ $(,)? ) => { ... }; // and for top-level enum types: ($Container:ty, as $TopVariant:path, (((($midfields:tt).+, as $Variant:path,)* (((fields:tt).+ $(,)? ) => { ... }; }

Requiring full item name lookup is tbf unnecessary since we do already know the type contextually, but the same applies to patterns and we don't use the contextual information there either. I'd expect _::Variant to work if/when it works for patterns.

The as could be dropped, but I think it's useful for clarity, as well as it allows spelling the inspection of a top-level enum offset_of!(Option::<T>, as Some, 0) instead of requiring something like perhaps offset_of!(Option::<T>, self, as Some, 0) to have a no-op field path (in order to distinguish between the item/type/variant name and field name(s)).

Whether the as Type segments are additionally permitted to assert the specific type at a point in the path in addition to traversing variants, it could go either way tbh. Maybe give every "type segment" of offset_of! a syntax of $($Container:ty)? <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>a</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">(as </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mord mathnormal">s</span></span></span></span>Variant:ident)?,? E.g. offset_of!(Type, field, _ as Variant, field) and offset_of!(Option::<T> as Some, 0).

My opinion changes if the basic syntax changes. If offset_of!(Type.field) were permitted, I'd be fully on board with using offset_of!(Type.field.Variant.field). It's because the initial type is comma separated that I feel later type variants should also be comma separated.