batch-impl 0.6.2

A proc-macro library for batch generating trait impls with a powerful DSL
Documentation
# Changelog (User)

> User-visible feature and behavior changes; for internal implementation details, see `docs/dev-changelog.md`.
>
> English docs are the release artifact, translated from the development Chinese docs in
> `docs/zh-CN/` right before publishing.

## 0.6.2 (2026-08-05)

### Span-based diagnostics

- Every `Ty` node now carries its source `Span` (`enum Ty``struct Ty { span, kind: TyKind }`);
  `Ty::apply` takes the node's own span and threads it through combinator output — errors raised inside
  `apply` point at the left operand's position;
- `compile_error_str` / `compile_err_at!` accept an explicit span; errors from parse, constants, directives,
  blanket, and apply all attach to the offending token's span (`^` missing an operand now points at `^`
  itself rather than the whole macro invocation);
- Platform limitation (rustc behavior): top-level tokens of attribute-macro input carry precise spans, but
  tokens inside groups degrade to the call-site span, and errors returned as `Err` always display on the
  macro invocation line — what actually shows precise locations are the parse/apply errors on the
  `Ty::Error` (Ok output) path;
- `compile_error!` only stamps the target span onto the keyword identifier, keeping everything else at the
  call site — if every token carried a span, rustc would treat the error as user code at the item position
  ("macros that expand to items must be delimited...").

### `#blanket` static method delegation

- `#blanket` now forwards receiverless methods (static methods / `@all_static_methods` /
  `@all_methods`) through the blanket generic `t``fn make() -> u8 { t::make() }`,
  instead of the deref-chain delegation body `(**self).make()` (static methods have no `self`; E0424);
- Direct calls, nested wrappers (`Box<Box<u8>>`), and argument forwarding all reach the underlying
  impl through the `t: Trait` bound — the same forwarding semantics as associated-item projection;
- Philosophical unification: instance methods forward via deref, static methods via the bound — both are
  forwarding, no special cases.

### `@all` filtering by receiver kind

- New `@all` family markers filter trait methods by receiver kind:
  `@all_ref_methods` (`&self` / `&mut self`), `@all_value_methods`
  (`self`, including typed receivers), `@all_static_methods` (associated functions);
- Typical use: `#blanket(@all_ref_methods){Box}` delegates only reference-receiver methods,
  sidestepping the semantic ambiguity of by-value delegation for wrapper types (by-value methods
  fall back to the trait's default implementations);
- Like the rest of the `@all` family, shared by `#fill` / `#delegate` / `#blanket` and the `-`
  exclusion; `batch_trait!` errors on them (they need a trait definition).

### Comments, error messages, and docs fully anglicized

- **Comments and error messages are now all in English** (source, tests, ui fixtures) — a wider audience;
  DSL markers in messages (`` `@uint` ```` `#fill` ```` `@0` ``) stay unchanged;
- **Documentation language policy established**: during development, the Chinese docs (`docs/zh-CN/`)
  are the primary record of changes; before publishing, they are translated into English and placed in
  the English docs (`README.md`, `CHANGELOG.md`, `docs/tutorial.md`, `docs/architecture.md`,
  `docs/dev-changelog.md`); 0.6.2 has completed the initial English translation, and the Chinese docs
  continue to evolve as the development-side primary docs;
- Code examples in the docs are unchanged (doubling as doctests — all 46 pass);
- Fixed the broken fence of a mid-level `@trait` example in the tutorial (`` `ust ```` ```rust ``),
  incidentally bringing it under doctest coverage.

## 0.6.1 (2026-08-05)

### New Features: `@all_required*` / `@all_default*` scope markers

- Directive scope is now filtered by the trait item's **default-implementation status** (fn with a default body / const with a default value /
  type with a default type = default; no default = required, and the impl must provide it):
  - `@all_required_methods` / `@all_required_constants` / `@all_required_types` / `@all_required`;
  - `@all_default_methods` / `@all_default_constants` / `@all_default_types` / `@all_default`;
- Shared by the three directives `#fill` / `#delegate` / `#blanket`, and by the `-` exclusion;
- Typical use: `#fill(@all_required_methods){...}` = implement only the required ones, keeping the trait's
  default implementations for default methods (previously you needed `@all` plus per-method `-name` exclusions); `@all_required*` and
  `@all_default*` can be combined to fill the two groups separately (required ∪ default = all).

### Fixed: `@` constants pair before `<>` (`@ <> # where` preprocessing order)

- The previous pipeline was `<> @ # where`: with forms like `Vec<@inner>` in `batch_trait!` where the
  constant value contains `<...>`, `@inner` got paired into the angle-bracket group and was no longer expanded,
  leaving `found '@'` in the output (a direct value like `@map = HashMap<u32, String>` happened to be
  saved by the pairing fallback at its definition site; nested/reference scenarios exposed it);
- Fixed so that at the outermost macro-meta layer, `@` expansion precedes `<>` pairing, and all expansion
  output (including flattened `<...>`) is uniformly paired by angle_collect;
- `batch_impl`/`batch_impl_only` support built-in `@` + `<>` + `#` + where;
  `batch_trait!` supports custom `@` + `<>` + where (`#` requires a trait definition, which a function-like
  macro cannot access).

### Macro-meta layer completed: `@` is the sole macro-meta marker

- **`#all` family removed, all migrated to the `@all` family** (`@all` / `@all_methods` /
  `@all_constants` / `@all_types` / `@all_required*` / `@all_default*`):
  `#` is now only for directive names; scope selection belongs to the macro-meta layer — write
  `#fill(@all)` instead of `#fill(#all)`, with subtraction unchanged (`#fill(@all, -foo)`);
- `@all` expands to an `[item, ...]` list; directive arguments support hand-written `[a, b]` lists and
  `-[a, b]` exclusions;
- **Trait-aware constants** (exclusive to `#[batch_impl]` / `#[batch_impl_only]`;
  `batch_trait!` has no trait definition and errors on them): `@trait` (the local trait name),
  `@Cow` (`Cow<'_>` plus its inherent constraints bundled);
- **Blanket wrapper constraint predicates**: `{Cow<'_> where{@0: ToOwned + ?Sized, @0::Owned: @trait}}`
  — solves wrappers whose deref target ≠ T (`Cow`'s deref target is `T::Owned`),
  with `@0` referring to the target generic; in ordinary where predicates, `@N` is a generic positional reference
  (e.g. tuples `()^2 where{@0: Clone}`); with "`<>` keeps only names, constraints all go into where",
  constraint merging = juxtaposed predicates (zero analysis); the `<T: Clone>` form in ordinary impls remains compatible.

### Docs fixed: `batch_trait!` directive boundary clarified

- Previously the `lib.rs` docs and `docs/tutorial.md` claimed that `batch_trait!`'s spec syntax
  was "identical to `#[batch_impl]`" — in fact, `batch_trait!` **does not support `#` directives**
  (`#fill`/`#delegate`/`#blanket`/open extension), and errors out on `#`;
- Reason: directives need the trait definition as the source of truth for signatures, and `batch_trait!` is a
  function-like macro that cannot obtain the definition. If you need directives, use `#[batch_impl]` / `#[batch_impl_only]`
  (same origin as the existing limitations that `A<>` is copied verbatim and generic bounds are inherited).
- No behavior change: `batch_trait!` supports `@` constants and the full type DSL; only the docs now state
  the directive boundary truthfully.

## 0.6.0 (2026-08-04)

### New Feature: `@` constant system (named reuse of type matrices)

`@` constants expand to literal lists at the preprocessing stage, token-for-token equivalent to hand-written lists:

- **Built-in name families**: `@uint` / `@int` / `@float` / `@num` / `@scalar`
  (e.g. one line of `#[batch_impl(@scalar)]` generates 16 impls: u8..char);
- **Built-in range families**: `@u8..u128` / `@i8..i128` / `@f32..f64` (**inclusive of both endpoints**,
  with width validation; `@u8..u128` = `[u8, u16, u32, u64, u128]`);
- **User-defined** (only in `batch_trait!`): a leading `@name=value;` section, reusable across
  subsequent sections and traits. Values are **arbitrary tokens** (**lazy expansion** — stored as-is,
  recursively expanded after splicing at the use site), so DSL operations can be written directly
  (`@wrapped=[Box,Rc]^@num`) or other constants chained (`@chain=@wrapped`); circular references (`@a=@a`)
  and forward references (`@a=@b` defined later) error at the definition site;
- Unknown `@xxx`, illegal range endpoints, and custom/built-in name clashes all raise `compile_error!`.

### New Feature: `#blanket(methods){wrapper list}` — blanket delegation

`#blanket(#all){&,Box,Rc}` generates a full delegation spec for each wrapper type — no need to hand-write the
wrapper matrix or the delegation body. First implement the trait for the inner type, then blanket-cover the
wrappers (`impl<T: Trait> Trait for Box<T>` and so on).

- **Wrapper elements are arbitrary type expressions**: `&`/`&mut`/`Box`/`Rc`/`Arc`/custom smart pointers/
  nesting (`Box^Arc:2``Box<Arc<T>>`)/pre-filled (`Cow<'_>``Cow<'_, T>`);
- **`:N` depth annotation**: the number of `*` in the delegation body = N + 1 (`Box^Arc:2``***self`),
  defaulting to 1 — the macro does not guess how many Deref levels a wrapper has internally, so nesting must be annotated explicitly;
- **Generic trait support** (`trait Foo<X: Clone>`): the trait's formal parameters are copied verbatim as
  impl generics, with parameter names as actuals and trait-level where predicates passed through
  (`impl<X: Clone, T: Foo<X>> Foo<X> for wrapper<T> where ...`);
- **Assoc type / const delegation**: when `#all` includes const/type items, projections are generated
  (`type Item = <T as Foo<X>>::Item;` / `const N: Ty = <T as Foo<X>>::N;`) —
  traits with required associated types can also be blanket-covered;
- `*const`/`*mut`, `self`, empty elements, and invalid `:N` error out, steering users to hand-written `#delegate`;
  delegation of by-value receiver methods depends on the wrapper's Deref/move capability, so everything is
  still allowed with rustc as the backstop (documented as a caveat).

### Behavior changes

- Directive expansion protocol changed to `Vec<TokenTree>` (internal): existing directive output is unchanged
  (a single `{...}` group), enabling multi-output directives like `#blanket`. Not user-visible.

### Docs

- README trimmed to a promotional version (why use it, mental model, quick start, feature overview);
  the full tutorial moved to `docs/tutorial.md`, developer docs to `docs/architecture.md`
- CHANGELOG split into this file (user perspective) and `docs/dev-changelog.md` (developer perspective)
- Tutorial gained `@` constant and `#blanket` sections; architecture docs gained "syntax domain isolation" and
  "attachment semantics" sections

## 0.5.7 (2026-08-03)

### New Feature: trait-level where clause inheritance (automatic, no code changes needed)

All forms of predicates on `trait Foo<T> where T: Clone` are inherited into the generated impls:

- **Single-parameter predicates** (`T: Clone`) merge into generic bounds — `<T> Foo<T>`  `impl<T: Clone>`, sharing the same inheritance pipeline as inline bounds (`trait Foo<T: Clone>`)
  (same-name inheritance / rename errors / reference checks all reused);
- **All other predicates pass through verbatim** into the impl's where clause: `T::Item: Clone`, `Vec<T>: ...`,
  lifetime predicates (`'a: 'b`), etc., fully covered; the `<T>` and `A<>` forms behave the same.

### Behavior changes

- Previously compound predicates (`T::Item: Clone`, etc.) were silently dropped, generating impls missing
  constraints that failed with rustc E0277 (and confusing locations); now they are automatically appended to
  the impl's where clause, equivalent to hand-written code. Code that failed before upgrades cleanly.
- New error message: `inherited where predicate ... references parameter ..., declare it or write a where clause`
  (guidance for rename scenarios).
- No breaking changes; `batch_trait!` has no trait definition and is unaffected.

## 0.5.6 (2026-08-03)

### Behavior change: unmatched `<` / `>` now error

- Unmatched `<` (no matching `>`) and stray `>` (no matching `<`) used to pass through as garbage
  tokens; now they raise `compile_error!` (invalid input).

## 0.5.5 (2026-08-03)

### New Feature: `A<>` trait generics copied verbatim

- `A<>`: an empty argument list means "actuals and bounds all come from the trait definition" —
  `trait Foo<T: Clone>` + `#[batch_impl(Foo<> ())]` expands to
  `impl<T: Clone> Foo<T> for ()`, with no generics to write by hand;
- `A<bounds>` copies the same way: `Foo<Item=T>` copies positional actuals and keeps the bindings verbatim;
- Only `#[batch_impl]` / `#[batch_impl_only]` (which need a trait definition) support this;
  `batch_trait!` has no trait definition, so `A<>` passes through verbatim.

### Behavior change: renaming = explicit error, never silent

- When an actual `X` maps to a formal `T` (with bounds) but the names differ, or an inherited bound references
  formal names like `'a`/`U` that the impl does not declare — both raise `compile_error!` with guidance
  (rename or write the bound by hand). Previously renaming silently degraded to non-inheritance, generating
  impls missing bounds that failed with E0277.

## 0.5.4 (2026-08-03)

### New Feature: automatic inheritance of trait generic bounds

With `trait Foo<T: Clone>`, impl generic parameters that have **no bound written** in the spec inherit the
inline bound of the trait's same-named parameter by name — `#[batch_impl(<T> Foo<T> Vec<T>)]` directly
generates `impl<T: Clone> Foo<T> for Vec<T>`, no hand-writing needed (previously the generated impl lacked the
bound and failed with E0277).

- If a bound is written, the user owns it and the macro does not interfere (sub-trait entailment is left to rustc to verify);
- Inherits inline bounds like `T: Clone` / `T: 'a`; trait-level where clauses are not inherited (supported from 0.5.7);
- Only `#[batch_impl]` / `#[batch_impl_only]` support this; `batch_trait!` does not inherit.

### New Feature: directive argument list subtraction `-name` (replaces `#except`)

`#fill`/`#delegate` arguments gain `-`-prefixed exclusions: keep-list minus exclusion-list, with exclusions
taking priority. The `#except(keep){exclude}` double-bracket form is superseded and removed:

- `#fill(#all,-foo){body}` = all items except `foo`
- `#fill(#all,-#all_methods)` = only const + type items
- Missing target after `-`, or an empty result after exclusion, raises `compile_error!`

## 0.5.3 (2026-08-02)

### New Features

- **`unsafe fn(...)` types**: `unsafe` immediately followed by `fn` decorates the fn type itself
  (`unsafe fn(u32)->u32`, `unsafe fn^(A,B)-C`); `unsafe X` (X not a fn, juxtaposed) is an error
  (the typo of forgetting `^`); bare `unsafe` followed by `^`/`-` is still the unsafe impl marker.
- **Open extension mechanism fixed**: an unrecognized `#name(args){body}` expands to a function-like macro
  call `name!{(args){body} trait ...}` — the method name list, body, and the whole trait are handed to the
  user's same-named macro ("a user-customized `#fill`"; the previous attribute-delegation form always failed to compile).
- **Directive subtraction `#except(keep){exclude}`** (superseded and removed by `-name` in 0.5.4).

### Fixed

- **`#delegate` argument forwarding hardened**: destructuring-pattern parameters (`(a, b)` / `_`) cannot be
  forwarded for delegation; previously silently dropped to produce a wrong call, now raising `compile_error!`
  (including the trait name and method name).
- **Empty range diagnostics**: empty ranges like `()^3..2` used to silently generate zero impls, now error.
- **Trailing-operator segment swallowing fixed**: trailing operators such as `A^`, `f32 Vec^-` used to
  silently disappear wholesale (downstream E0599 with confusing locations), now raising `compile_error!`.
- **Empty operand strictness**: `-A` (empty left silently swallows the segment), `^A` (generates garbage types), `,A`,
  `A,,B` all error; trailing commas (`A,`) and real `()`/`[]` tokens are unaffected.
- **Directive argument comma strictness**: leading/trailing/consecutive commas like `#fill(a,,b)` error
  (previously skipped silently).

### Behavior constraint: combined expansion count cap

Expansions from `^N` / Cartesian products / range batching exceeding 1024 products (e.g. `()^100000`,
`[A,B]^[C,D]^[E,F]`) raise `compile_error!`, preventing typos from hanging the compilation.

## 0.5.2 (2026-08-01)

### New Feature: array/slice builder

- `[]^T``[T]` (empty seed wrapping a slice)
- `[T]^N``[T; N]` (fixed-length array; `N` can be a numeric literal, a const-generic identifier, a range, or a list)
- `<const N: usize> []-X-N``[X; N]`: `[]` serves as the `-` accumulation-chain seed, wrapping the whole type
  matrix into a const-generic fixed-length array
- Fresh generic tuples from `()^N` are automatically hoisted out when used as generic arguments/array elements
  (fixes the pre-existing bugs in `Box^()^N` and matrix embedding)

## 0.5.1 (2026-07-31)

### New Feature: `where{...}` suffix

- `where{...}` following the target type adds a where clause to the generated impl; multiple ones are merged.
- New syntax for writing bare `where predicate {code block}` (shared by all three interfaces): commas in the
  predicate region are not split by the spec, `ident!{...}` macro bodies are not counted toward boundaries, and
  multiple `where` sections can be written in sequence.

## 0.5.0 (2026-07-28)

### New Feature: `#[batch_impl_only]` external trait path prefix

`#[batch_impl_only(#ext::mod::TraitName: usize, isize)]` generates impls for a trait defined in an external
module (the final path identifier must match the local dummy trait name; `#[batch_impl]` does not support this prefix).

## 0.4.2 (2026-07-27)

### New Features

- **`#name{body}` supports const / type items**: `#CONST{value}``const ... = value;`,
  `#Type{def}``type ... = def;`, no longer limited to fn.
- **`#fill` extended and `#all` marker**: `#fill` works for fn + const + type;
  `#all` now means all items; added `#all_methods` / `#all_constants` / `#all_types`.
- `#delegate` still supports only Fn; passing a non-Fn item raises `compile_error!`.

## 0.4.1 (2026-07-25)

- Fixed custom (open extension) macros not carrying trait_def.

## 0.4.0 (2026-07-25)

### New Feature: directive system

| Directive | Syntax                    | Effect                                                              |
|-----------|---------------------------|---------------------------------------------------------------------|
| Single method | `#method{body}`       | `{fn method(signature) { body }}`                                  |
| Fill       | `#fill(args){body}`       | `{fn m1(sig){body} fn m2(sig){body} ...}`                           |
| Delegate   | `#delegate(args){target}` | `{fn m1(sig){(target).m1(args)} ...}`                               |

- `#fill(#all){body}` covers all methods of the trait
- Directives combine freely with DSL operators, `{body}` consecutive attachment, generics, unsafe, and other features
- Only `#[batch_impl]` / `#[batch_impl_only]` support directives

### New Feature: `#[batch_impl_only]` and `{body}` consecutive attachment

- `#[batch_impl_only]`: discards the trait definition and outputs only the impl block (for when the trait is already defined elsewhere)
- `T{body1}{body2}` attaches consecutively and correctly recursively

## 0.3.0 (2026-07-24)

### Complete rewrite

v0.3.0 is a complete rewrite from scratch. The public API and DSL syntax stay consistent with v0.2.x.
Feature list:

- `#[batch_impl]` attribute macro + `batch_trait!` function-like macro
- `^` (right-associative) / `-` (left-associative) operators: generic application, type composition
- `[A, B, C]` juxtaposition lists + `{ body }` standalone/shared implementation body merging
- `<T: Clone, Item=V>` generic parameters and associated type bindings
- `()^N` tuple generation + `(<Bound>)^N` constrained tuples + `(T1,T2)^N` Cartesian product + range syntax
- `&` / `&mut` / `*const` / `*mut` / `fn` / `self` / `unsafe` / `#[attr]` prefix modifiers
- `fn(A,B)->C` function types
- `HashMap<K>^V` pre-filled generic appending
- `unsafe^T` per-item unsafe + `unsafe trait` automatically unsafe
- `compile_error!` error output (no panics, no ICEs)

### Fixed (relative to v0.2.x)

- Specs containing `->` such as `fn(i32) -> bool` in `batch_trait!` no longer incorrectly break segment boundaries
- `()^0` correctly generates the empty tuple `()`

## 0.2.2 (2026-07-20)

### Fixed

- `fn^i32` correctly generates `fn(i32)` instead of `fn i32`
- All utility functions uniformly exclude the `>` inside `->` (types containing `->` like `HashMap^<u32>-String` are no longer misjudged as angle brackets)

## 0.2.1 (2026-07-20)

### Fixed

- **Precedence**: `HashMap^K-V` now parses correctly as `HashMap<K, V>` (previously parsed as
  `HashMap<K<V>>`). Note: `Box^Vec-u32` is still a wrong form; write `Box^Vec^u32`
- `-String` in `HashMap^<u32>-String` is no longer silently dropped
- `unsafe^#[attr]^T` no longer reports an "internal error with attribute ^"
- `fn^(u32,i32)-usize` correctly generates `fn(u32,i32)->usize` (previously the return type was appended as an argument)
- Nested `fn^(u32,i32)^i64-usize` no longer loses the `Fn` prefix

## 0.2.0 (2026-07-19)

### New Features

- **Associated type shorthand**: `TraitName<AssocType=value>` (multiple bindings and complex types supported,
  combinable with `^`/`-`/unsafe)
- **Standalone/shared body merging**: `[A{bodyA}, B{bodyB}]{shared}` (multi-level nesting supported)
- **Tuple generation rule change**: `()^N` generates a tuple with N generic parameters; `(T)^N` generates a
  repeated tuple of length N; `(T1,T2)^N` is a Cartesian product; range syntax `()^M..N` / `()^M..=N`
- **`*const`/`*mut` pointers**: `*const^T``*const T`, chainable
- **Reference modifier special behavior**: `&^A^B``&A<B>` (bind first, then apply)
- **fn keyword**: `fn^(A,B)` creates, `fn(A,B)^T` appends a return type, `fn-(A,B)^N` composes
- **`#[...]` attributes**: `#[attr]^T` adds the attribute before the impl block

## 0.1.1 (2026-07-19)

### New Feature: pre-filled generic appending

- `A<B>^C``A<B, C>` (when the container has pre-filled generics, `^` appends arguments instead of producing `A<B><C>`)
- `[Box, Cow<'_>]^T``Box<T>, Cow<'_, T>` (list support)
- The `-` operator benefits automatically: `HashMap-u32-String``HashMap<u32, String>`

## 0.1.0 (2026-07-19)

### Initial release

- `#[batch_impl(...)]` attribute macro + `batch_trait!(...)` function-like macro
- `^` (right-associative) / `-` (left-associative) operators: generic application
- Tuple generation: `()^N`, `(<Bound>)^N`, `(T1,T2)^N` Cartesian product, `()^M..N` ranges
- Generic support: impl generics (incl. const), trait generics, lifetimes, generic inheritance
- `unsafe^T` / `unsafe trait` / `batch_trait!(unsafe ...)`
- Chinese-language error messages, `compile_error!` instead of panic