Problem
The model macros prefix many generated identifiers with __. Some of these
leak into the user-facing surface — rustdoc signatures and compiler error
messages — where they add noise and make the API harder to read.
The clearest example is the generated select method
(crates/toasty-macros/src/model/expand/query.rs:56):
#vis fn select<__E, __T>(
self,
projection: __E,
) -> #toasty::stmt::Query<#toasty::List<__T>>
where
__E: #toasty::IntoExpr<__T>,
__T: #toasty::Load,
A user who mistypes a projection sees an error mentioning __E and __T, and
the same names show up in rustdoc. Plain E / U would read better. Other
user-visible generic params with the same treatment: __Origin and __T in
the Model trait associated types and method signatures, and the __T on the
generated query struct.
The __ prefix is a hygiene guard: quote! emits call-site spans, so a
generated generic param could in principle collide with a user type spliced
into the same signature (e.g. Path<__Origin, #model_ident> breaks if the
model is named Origin). But many uses carry no such risk — select's
signature splices only toasty paths, never a user ident, so __E/__T guard
against nothing. Those are pure noise.
Proposed solution
Audit every __-prefixed identifier in generated code and split them into two
buckets:
- No collision possible — drop the prefix in favor of a readable name.
select<__E, __T> → select<E, U> is the motivating case.
- Could collide with a spliced user ident — keep a guard, but prefer the
least intrusive option. Where the ident is purely internal (macro-local
let bindings, #[doc(hidden)] helpers like __macro_fields_root), the
prefix is fine and invisible. Where it appears in a user-visible signature
(__Origin in trait/Model method signatures), consider whether def-site /
mixed-site hygiene lets us use a readable name without the collision risk,
rather than carrying __ into rustdoc.
Scope of the audit (from a sweep of crates/toasty-macros/src/):
- User-facing generic params:
__E, __T in select; __Origin, __T in
Model trait assoc types / methods and the query struct.
- Internal-only (likely keep): macro-local vars (
__update, __scope,
__scope_fields, __fields), the __macro_fields_root hidden method,
type-check aliases (__RelationTarget, __via_typed/__via_untyped,
_check<__T>), and the __toasty_ collision-avoidance prefix in
model/expand/util.rs.
Alternatives considered
- Leave as-is. The names work; they're just ugly. The cost is paid by every
user who reads a generated signature or hits a related compile error.
- Blanket-strip all
__ prefixes. Risks reintroducing the splice
collisions the prefix was added to prevent. The point of the audit is to
separate the safe cases from the load-bearing ones.
Scope
Medium — touches the generated public API surface (rustdoc + error messages),
but no behavior change.
Additional context
Identified while reading the macro source; no functional bug, purely a
readability/ergonomics cleanup of generated code.
Problem
The model macros prefix many generated identifiers with
__. Some of theseleak into the user-facing surface — rustdoc signatures and compiler error
messages — where they add noise and make the API harder to read.
The clearest example is the generated
selectmethod(
crates/toasty-macros/src/model/expand/query.rs:56):A user who mistypes a projection sees an error mentioning
__Eand__T, andthe same names show up in rustdoc. Plain
E/Uwould read better. Otheruser-visible generic params with the same treatment:
__Originand__Tinthe
Modeltrait associated types and method signatures, and the__Ton thegenerated query struct.
The
__prefix is a hygiene guard:quote!emits call-site spans, so agenerated generic param could in principle collide with a user type spliced
into the same signature (e.g.
Path<__Origin, #model_ident>breaks if themodel is named
Origin). But many uses carry no such risk —select'ssignature splices only
toastypaths, never a user ident, so__E/__Tguardagainst nothing. Those are pure noise.
Proposed solution
Audit every
__-prefixed identifier in generated code and split them into twobuckets:
select<__E, __T>→select<E, U>is the motivating case.least intrusive option. Where the ident is purely internal (macro-local
letbindings,#[doc(hidden)]helpers like__macro_fields_root), theprefix is fine and invisible. Where it appears in a user-visible signature
(
__Originin trait/Modelmethod signatures), consider whether def-site /mixed-site hygiene lets us use a readable name without the collision risk,
rather than carrying
__into rustdoc.Scope of the audit (from a sweep of
crates/toasty-macros/src/):__E,__Tinselect;__Origin,__TinModeltrait assoc types / methods and the query struct.__update,__scope,__scope_fields,__fields), the__macro_fields_roothidden method,type-check aliases (
__RelationTarget,__via_typed/__via_untyped,_check<__T>), and the__toasty_collision-avoidance prefix inmodel/expand/util.rs.Alternatives considered
user who reads a generated signature or hits a related compile error.
__prefixes. Risks reintroducing the splicecollisions the prefix was added to prevent. The point of the audit is to
separate the safe cases from the load-bearing ones.
Scope
Medium — touches the generated public API surface (rustdoc + error messages),
but no behavior change.
Additional context
Identified while reading the macro source; no functional bug, purely a
readability/ergonomics cleanup of generated code.