Valid-Elixir macro frontend for generating RustQ Rust fragments.
defrust captures a normal Elixir function-shaped body plus its preceding
@spec, lowers that quoted Elixir AST to Rust, and exposes generated Rust
items through __rustq_items__/0 and __rustq_source__/0.
defrustmod is for RustQ-owned Rust module structure. Prefer its block form
when RustQ is generating the Rust module and the nested functions. Do not use
it as a hand-written alias for Rust modules/types that are owned by another
generator or crate; those callers should derive/render their Rust paths at
their own codegen boundary instead of pretending external Rust modules are
Elixir modules.
defrustmacro defines a small macro_rules! item from a Rusty-Elixir body.
Its arguments are Rust macro fragments (:expr by default, with :ty
supported for type arguments) while the body still uses ordinary Rusty-Elixir
forms such as calls, decode_as!/2, and inference-backed propagation.
Prefer @spec plus defrust for user-facing Rusty Elixir. Generated or
external Rust paths should normally be expressed as ordinary remote types such
as GeneratedOpts.OvalOpts.t(R.lifetime(:a)); use RustQ.Type markers such
as R.ref/1, R.nif_result/1, R.unit/0, R.slice/1, and R.lifetime/1
only where Elixir typespecs need Rust-specific precision. The internal
RustQ.Meta.AST bridge is for generators that already hold RustQ AST
signature metadata; it is not the intended authoring surface.
Preferred Rusty-Elixir body forms are ordinary Elixir where possible:
- final
:okunderNifResult<()>returnsOk(()) name = expressionlowers to Rustlet name = expression- method calls, field access, aliases, and Elixir tuples lower to their Rust equivalents
- plural alias calls such as
Atoms.fill()lower to snake-case Rust module calls such asatoms::fill() - ordinary Elixir macros are expanded before lowering, so reusable body
fragments can use
defmacro,quote, andunquote - fallible calls in argument, return, case-scrutinee,
some(...),decode_as!, and many local-binding positions can infer Rust?from type metadata unwrap!(expression)is the explicit spelling for Rustexpression?; prefer inference when callable metadata is availableref(expression)/mut_ref(expression)spell explicit Rust borrows; many ordinary calls infer borrows from expected argument typesderef(expression)spells Rust dereference and can propagate fallible reference access such asargs.first().ok_or(badarg())- Option branching should use Elixir
case, for examplecase maybe do {:some, value} -> ...; :none -> ... end; do not introduce Rust-shapedif_letsyntax at the authoring layer
Escape hatches such as raw_expr! remain low-level last resorts, not the
normal way to reference project-owned Rust modules or types.