Skip to content

feat: support row attributes - #9

Closed
tisonkun wants to merge 2 commits into
mainfrom
codex/row-attributes
Closed

feat: support row attributes#9
tisonkun wants to merge 2 commits into
mainfrom
codex/row-attributes

Conversation

@tisonkun

Copy link
Copy Markdown
Contributor

No description provided.

Signed-off-by: tison <wander4096@gmail.com>
@tisonkun
tisonkun requested review from andylokandy and Copilot July 25, 2026 06:37
Signed-off-by: tison <wander4096@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for per-row outer attributes in repeat! and splice!, enabling row-level conditional compilation (e.g., #[cfg(...)]) while keeping the attribute attached to the generated tokens.

Changes:

  • Parse and retain leading outer attributes for each input row (Row { attrs, values }).
  • Emit collected row attributes immediately before the expanded tokens for that row in both repeat! and splice!.
  • Add documentation and regression tests covering items, statements, and match arms.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
README.md Documents “Row attributes” feature and adds a syntax note.
macroweave/tests/tests.rs Adds tests ensuring #[cfg(...)] row attributes correctly gate emitted items/statements/arms.
macroweave/src/parse.rs Introduces Row with attrs + bound values, and parses leading outer attributes per row.
macroweave/src/expand.rs Emits row.attrs before substituting/expanding each row in repeat! and splices.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tisonkun

Copy link
Copy Markdown
Contributor Author

@andylokandy Is this feature reasonable?

I found such use case when developing bsize where I have to set two macroweave calls:

macroweave::repeat!((Trait, Ty, DecimalName, BinaryName, Scale) in [
    (KiloByteSize, u16, KB, KIB, 1),
    (KiloByteSize, u32, KB, KIB, 1),
    (MegaByteSize, u32, MB, MIB, 2),
    (GigaByteSize, u32, GB, GIB, 3),
    (KiloByteSize, u64, KB, KIB, 1),
    (MegaByteSize, u64, MB, MIB, 2),
    (GigaByteSize, u64, GB, GIB, 3),
    (TeraByteSize, u64, TB, TIB, 4),
    (PetaByteSize, u64, PB, PIB, 5),
    (ExaByteSize, u64, EB, EIB, 6),
] {
    const impl Trait for Ty {
        const DecimalName: Self = Ty::pow(1000, Scale);
        const BinaryName: Self = Ty::pow(1024, Scale);
    }
});

macroweave::repeat!((PointerWidth, Trait, DecimalName, BinaryName, Scale) in [
    ("16", KiloByteSize, KB, KIB, 1),
    ("32", KiloByteSize, KB, KIB, 1),
    ("32", MegaByteSize, MB, MIB, 2),
    ("32", GigaByteSize, GB, GIB, 3),
    ("64", KiloByteSize, KB, KIB, 1),
    ("64", MegaByteSize, MB, MIB, 2),
    ("64", GigaByteSize, GB, GIB, 3),
    ("64", TeraByteSize, TB, TIB, 4),
    ("64", PetaByteSize, PB, PIB, 5),
    ("64", ExaByteSize, EB, EIB, 6),
] {
    #[cfg(target_pointer_width = PointerWidth)]
    const impl Trait for usize {
        const DecimalName: Self = usize::pow(1000, Scale);
        const BinaryName: Self = usize::pow(1024, Scale);
    }
});

... while with this patch I should be able to do

macroweave::repeat!((Trait, Ty, DecimalName, BinaryName, Scale) in [
    (KiloByteSize, u16, KB, KIB, 1),
    (KiloByteSize, u32, KB, KIB, 1),
    (MegaByteSize, u32, MB, MIB, 2),
    (GigaByteSize, u32, GB, GIB, 3),
    (KiloByteSize, u64, KB, KIB, 1),
    (MegaByteSize, u64, MB, MIB, 2),
    (GigaByteSize, u64, GB, GIB, 3),
    (TeraByteSize, u64, TB, TIB, 4),
    (PetaByteSize, u64, PB, PIB, 5),
    (ExaByteSize, u64, EB, EIB, 6),
    #[cfg(target_pointer_width = "16")]
    (KiloByteSize, usize, KB, KIB, 1),
    #[cfg(target_pointer_width = "32")]
    (KiloByteSize, usize, KB, KIB, 1),
    #[cfg(target_pointer_width = "32")]
    (MegaByteSize, usize, MB, MIB, 2),
    #[cfg(target_pointer_width = "32")]
    (GigaByteSize, usize, GB, GIB, 3),
    #[cfg(target_pointer_width = "64")]
    (KiloByteSize, usize, KB, KIB, 1),
    #[cfg(target_pointer_width = "64")]
    (MegaByteSize, usize, MB, MIB, 2),
    #[cfg(target_pointer_width = "64")]
    (GigaByteSize, usize, GB, GIB, 3),
    #[cfg(target_pointer_width = "64")]
    (TeraByteSize, usize, TB, TIB, 4),
    #[cfg(target_pointer_width = "64")]
    (PetaByteSize, usize, PB, PIB, 5),
    #[cfg(target_pointer_width = "64")]
    (ExaByteSize, usize, EB, EIB, 6),
] {
    const impl Trait for Ty {
        const DecimalName: Self = Ty::pow(1000, Scale);
        const BinaryName: Self = Ty::pow(1024, Scale);
    }
});

@andylokandy

andylokandy commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

The use case makes sense, but I think the existing syntax can already cover it by making the cfg predicate a column:

repeat!((Cfg, Trait, Ty) in [
    (all(), KiloByteSize, u16),
    (target_pointer_width = "64", KiloByteSize, usize),
] {
    #[cfg(Cfg)]
    const impl Trait for Ty {
        // ...
    }
});

all() covers unconditional rows, and placeholders are already substituted inside attributes.

I also have two concerns with the current design:

  • The attribute is emitted once before the expanded token sequence, so if a row generates multiple items, statements, or arms, it only applies to the first one.
  • For single-value rows, a leading attribute previously belonged to the row value; hoisting it changes the meaning of existing inputs.

Given this, perhaps a documentation example and regression test would be sufficient?

@tisonkun

Copy link
Copy Markdown
Contributor Author

Cool! Thank you.

Let me try to migrate bsize code to see if your trick works there :D

@tisonkun

tisonkun commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

[REPLIED BY AGENT]

Thanks! I tried the suggested approach in fast/bsize#19: fast/bsize#19

Using a Cfg column with all() for unconditional rows and target_pointer_width = "..." for usize rows works with macroweave 0.1.0. The refactor consolidates 8 repeat! invocations into 4 and removes 45 net lines across the stable and nightly implementations. Both cargo x test and cargo x lint pass.

This confirms that the existing syntax already covers the bsize use case, so the row-attributes feature is not needed here. I am closing this PR.

@tisonkun tisonkun closed this Jul 25, 2026
@tisonkun
tisonkun deleted the codex/row-attributes branch July 25, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants