Anodized Core
This crate is the interoperability layer for tools connected to the Anodized specification system.
Who Is This For?
-
If you want to add specifications to your code...
You're looking for the
anodizedcrate, which provides the#[spec]macro. -
If you're building a tool and want to work with Anodized specifications...
You're in the right place! This crate provides the necessary components to parse and interact with Anodized specification annotations.
-
If you're looking for blockchain smart contracts...
"These are not the contracts you're looking for." 🤖
But don't leave yet! While Anodized is about Design by Contract (not blockchain), it can still help make your smart contracts more robust through formal specifications.
Specification Syntax
The #[spec] attribute's parameters follow a specific grammar, which is formally defined using EBNF as follows.
params = [ requires_params ]
, [ maintains_params ]
(* not a typo: at most one `captures:` *)
, [ captures_param ]
(* not a typo: at most one `binds:` *)
, [ binds_param ]
, [ ensures_params ];
requires_params = { requires_param };
maintains_params = { maintains_param };
ensures_params = { ensures_param };
requires_param = [ cfg_attr ] , `requires:` , conditions, `,`;
maintains_param = [ cfg_attr ] , `maintains:` , conditions, `,`;
captures_param = `captures:` , captures, `,`;
binds_param = `binds:` , pattern, `,`;
ensures_param = [ cfg_attr ] , `ensures:` , post_conds, `,`;
conditions = expr | condition_list;
condition_list = `[` , expr , { `,` , expr } , [ `,` ] , `]`;
captures = capture_expr | capture_list;
capture_list = `[` , capture_expr , { `,` , capture_expr } , [ `,` ] , `]`;
capture_expr = expr | (expr , `as` , ident);
post_conds = post_cond_expr | post_cond_list;
post_cond_list = `[` , post_cond_expr , { `,` , post_cond_expr } , [ `,` ] , `]`;
post_cond_expr = expr | closure_expr;
cfg_attr = `#[cfg(` , settings , `)]`;
Notes:
- The last
,is optional. - The
paramsrule defines a sequence of optional parameter groups that must appear in the specified order. expris a Rustexpression; type checking will fail if it does not evaluate tobool.closure_expris a Rustclosurethat receives the function's return value as a reference; type checking will fail if it does not evaluate tobool.patternis an irrefutable Rustpattern; type checking will fail if its type does not match the function's return value.settingsis the content of thecfgattribute (e.g.test,debug_assertions).
Runtime Checks
The #[spec] macro transforms the function body by injecting runtime checks whose behavior is controlled by runtime-* feature settings. This process, known as instrumentation, follows a clear pattern.
Given an original function like this:
The macro rewrites the body to be conceptually equivalent to the following:
When a condition has a #[cfg(...)] attribute, the corresponding check! is wrapped in an if cfg!(...) block. This follows standard Rust #[cfg] semantics: the check only runs when the configuration predicate is true. The behavior of the check! itself is controlled by the global runtime-* feature setting.