RFA-605 · Case file with fixtures · Case 577 of 694 · Compiler evidence
Rust repr(align) Uses List Syntax, Not Name-Value Syntax
Attribute meta syntax is part of the language contract. Use align(N), then validate that N is legal and justified by an ABI or measurement.
- Reviewed
- Rust
- Rust 1.98.1, edition 2024
- Targets
- all Rust targets
- Profiles
- dev, release, test
Direct answer
What this Rust failure means
- Why it happens
- A name-value attribute form was used where repr's grammar expects an alignment hint carrying a parenthesized integer argument.
- First discriminating check
- Write align(N), verify N is supported, then justify and test the stronger address contract across allocations and targets.
Rust attributes use several meta-item shapes. The align representation hint expects its numeric argument in parentheses. The failing fixture writes align = 16, so Rust 1.98.1 reports E0539 and expects list syntax.
Attribute arguments have a grammar
Some attributes accept a path, some a name-value pair, and some a delimited list. Visual similarity does not make these forms interchangeable. repr accepts a list of representation hints, and align is itself a hint with a nested argument.
The official E0539 page covers malformed representation input. The Reference documents general meta-item syntax.
I follow the specific attribute documentation rather than generalising from path = "value" attributes such as some linker controls.
The repair fixes grammar and records the result
The repaired fixture uses #[repr(align(16))] and asserts that the type alignment is 16 on the target. The payload already has 16 bytes, but payload length alone is not the reason to align its address.
After syntax is valid, the alignment number must be a supported power of two within Rust's limits. E0589 covers invalid values such as 24. E0539 here only addresses how the hint was written.
This distinction is useful in automation: a generator can emit grammatically correct syntax and still choose a semantically unsupported or unnecessary value.
Explicit alignment affects containing layouts
Raising a type's alignment may increase its size through tail padding, change array stride, insert padding in containing structs, and require allocators to return more strictly aligned addresses. Large collections can consume much more memory.
I inspect size_of and align_of for the type and important containers. FFI code also checks offsets and the foreign compiler's layout. A Rust attribute cannot force a foreign allocator or incoming pointer to meet its promise.
The Reference section on alignment modifiers defines interactions with packed types. I avoid composing layout hints without understanding their restrictions.
Performance reasons need measurement
Explicit alignment can support instructions with alignment requirements or reduce false sharing when data is placed appropriately. It can also hurt cache density and allocation efficiency. The type name CacheLine or Simd is not evidence.
I benchmark the real access pattern on supported hardware and record variance, memory cost, and allocator behaviour. False-sharing work must consider which fields different threads write and whether array elements or allocations are actually adjacent.
If alignment is required only for one buffer, a specialised allocation may be better than raising every instance of a public type. I keep the constraint as local as its proof.
Macro-generated attributes should be tested as tokens
Procedural and declarative macros may accept an alignment parameter. They should validate or forward it in the correct token form and provide an error at the user's input. Snapshot or compile tests cover legal and illegal arguments.
Using a string such as "16" is not equivalent to the integer literal token. Generated code should not build attribute text through unchecked concatenation when structured tokens are available.
Public aligned types carry compatibility commitments. Changing alignment can break FFI and custom allocation users even if fields remain unchanged.
Documentation should record the reason beside the type
I leave a short comment naming the instruction, external ABI, or benchmark that requires alignment and link to reproducible evidence. Without this, a future maintainer cannot tell a necessary contract from an abandoned experiment. I also record why the chosen value is sufficient, because doubling alignment “just in case” can multiply padding costs. This small explanation turns unusual layout syntax into a reviewable engineering decision.
My E0539 checklist
- Is align written as the nested list
align(N)? - Is N an integer literal rather than a string or name-value pair?
- Is the value a supported power of two?
- What ABI, instruction, or measured workload requires it?
- How does it change type size, array stride, and containing layouts?
- Do all allocators and foreign pointers meet the stronger alignment?
- Are macros validating and testing emitted attribute tokens?
- Would the change alter a public layout or binary interface?
The core principle is that low-level promises begin with precise language syntax. E0539 fixes the grammar, not the engineering justification. I apply the correct form and then prove that the resulting alignment is necessary and satisfied end to end.