Attributes
Attributes are metadata that can be applied to data types, functions, and some statements and expressions,
using the following syntax: #[attribute(value)].
allow(dead_code)
When applied to a data type or function, the compiler won't produce a warning if the data type or function ends up being unused.
Example:
#[allow(dead_code)]
struct Unused {}
allow(unused_mut)
When applied on a let statement, the compiler won't produce a warning if the variable is mut but
is never mutated.
Example:
fn main() {
#[allow(unused_mut)]
let mut never_mutated = 1;
println(never_mutated);
}
allow(unused_variables)
When applied on a let statement, the compiler won't produce a warning if the variable ends up being unused.
Example:
fn main() {
#[allow(unused_variables)]
let unused = 1;
}
builtin
When applied to a function, indicates that the function is implemented by the compiler, for efficiency purposes.
deprecated
Marks a function as deprecated. Calling the function will generate a warning: warning: use of deprecated function
Example:
#[deprecated]
fn slow_function() {}
The attribute takes an optional string which will be used as the deprecation message:
#[deprecated("use some other function")]
Example:
#[deprecated("use fast_function")]
fn slow_function() {}
fn fast_function() {}
To change the warning into a hard error, deny can be specified on the attribute:
#[deprecated(deny, "don't use this!")]
fn broken() {}
field
Can be used on functions to enable conditional compilation of code depending on the field size.
The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve.
Example: we define the function foo() three times below. Once for the default Noir bn254 curve, once for the field , which will normally never be used by Noir, and once again for the bls12_381 curve.
#[field(bn254)]
fn foo() -> u32 {
1
}
#[field(23)]
fn foo() -> u32 {
2
}
// This commented code would not compile as foo would be defined twice because it is the same field as bn254
// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)]
// fn foo() -> u32 {
// 2
// }
#[field(bls12_381)]
fn foo() -> u32 {
3
}
If the field name is not known to Noir, it will discard the function. Field names are case insensitive.
fuzz
Marks the functions for fuzzing. See Fuzzer for more details.
oracle
Mark a function as oracle; meaning it is an external unconstrained function, implemented in noir_js. See Unconstrained for more details.
fold
Marks a function for ACIR fold optimization. The compiler will generate a separate circuit for this function which is then recursively verified at runtime. This can reduce total circuit size when a function is called multiple times or contains a large number of constraints.
Note that this requires the backend supports folding multiple circuits.
Example:
#[fold]
fn expensive_computation(x: Field) -> Field {
// ... many constraints ...
x
}
inline_always
Forces the compiler to always inline this function at its call sites. This can improve performance by avoiding function call overhead, at the cost of increased circuit size.
Since constrained calls are always inlined, this will only ever have any effect in unconstrained code.
Example:
#[inline_always]
fn small_helper(x: Field) -> Field {
x + 1
}
inline_never
Prevents the compiler from inlining this function. This can be useful to keep artifact size manageable when a function is called from many places.
Since constrained calls are always inlined, this will only ever have any effect in unconstrained code.
Example:
#[inline_never]
fn large_function(x: Field) -> Field {
// ... complex logic ...
x
}
no_predicates
Disables predicate optimization for this function's ACIR output. This can be useful when the predicate optimization would produce incorrect results for certain foreign function patterns.
This will have no effect in unconstrained code.
See [../../explainers/explainer-writing-noir.md] for more detail.
export
Marks a function for export in compiled artifacts. This is primarily used inside contract blocks to indicate that a function should be accessible externally. This can also be used by libraries for testing or benchmarking by exporting artifacts to test libraries against without having to create many individual binaries.
must_use
Produces a warning if the return value of this function call is unused. Optionally takes a message string explaining why the value should be used.
Example:
#[must_use]
fn important_result() -> Field {
42
}
#[must_use = "the new vector is returned, the original is not modified"]
fn push(vec: [Field], value: Field) -> [Field] {
// ...
}
abi
Tags a struct or global for inclusion in a contract's ABI with the given tag name. Used inside contract blocks to indicate which types should appear in the compiled artifact's interface.
Example:
#[abi(events)]
struct Transfer {
from: Field,
to: Field,
amount: Field,
}
contract_library_method
Marks a function inside a contract block as a helper method rather than a contract entry point. Functions with this attribute will not be included as callable endpoints in the compiled contract artifact.
varargs
Allows a comptime attribute function to accept a variable number of arguments. See Compile-time Code for more details.
derive
Derives trait implementations for a struct using comptime macros. Multiple traits can be derived at once by separating them with commas. See Compile-time Code for more details.
Example:
#[derive(Default, Eq, Ord)]
struct MyStruct {
field1: u32,
field2: Field,
}
test
Marks the function as a unit test. See Tests for more details.
Inner Attributes
Inner attributes apply to the enclosing module rather than the item that follows. They use the syntax #![attribute]:
#![allow(unused_variables)]
Inner attributes support #[allow(...)], #[deprecated], and custom meta attributes, using the same syntax as outer attributes but prefixed with !.