Builtins
A builtin is a compiler-provided construct prefixed with @.
builtin = "@" IDENT "(" [ builtin_args ] ")" ;
builtin_args = builtin_arg { "," builtin_arg } ;
builtin_arg = IDENT | expression | type ;
The @ prefix distinguishes builtins from user-defined constructs.
Tokenization of builtins is uniform: @ is its own token and the builtin name is an ordinary identifier token. No builtin name — including import — forms a fused single token, and the name is interned like any other identifier.
Using an unknown builtin name is a compile-time error.
Builtin Kinds
There are two kinds of builtins, distinguished by their syntactic position:
| Kind | Position | Purpose | Examples |
|---|---|---|---|
| Intrinsic | Expression | Produces a value | @dbg, @size_of, @align_of |
| Directive | Before item/statement | Modifies compiler behavior | @allow, @copy, @repr |
An intrinsic builtin appears where an expression is expected and evaluates to a value. See Intrinsic Expressions for details.
A directive builtin appears before an item or statement and modifies how the compiler processes that construct. See Directives for details.
Directives
A directive is a builtin that modifies the behavior of the immediately following item or statement.
directive = "@" IDENT "(" [ directive_args ] ")" ;
directive_args = directive_arg { "," directive_arg } ;
directive_arg = IDENT ;
A directive MUST be immediately followed by an item or statement. A directive at the end of a file or block without a following construct is a compile-time error.
@allow
The @allow directive suppresses specific compiler warnings for the following item or statement.
@allow accepts one or more warning names as arguments.
The following warning names are recognized:
| Warning Name | Description |
|---|---|
unused_variable | Variable is declared but never used |
unused_function | Function is declared but never called |
unreachable_code | Code that can never be executed |
unreachable_pattern | Match arm pattern that can never match |
Using an unrecognized warning name in @allow is a compile-time error.
Suppressing Unused Variable Warnings
When @allow(unused_variable) precedes a let statement, no unused variable warning is emitted for that binding.
fn main() -> i32 {
@allow(unused_variable)
let x = 42; // no warning, even though x is unused
0
}
When @allow(unused_variable) precedes a function definition, no unused variable warnings are emitted for any bindings within that function.
@allow(unused_variable)
fn example() -> i32 {
let a = 1; // no warning
let b = 2; // no warning
0
}
Suppressing Unused Function Warnings
When @allow(unused_function) precedes a function definition, no unused function warning is emitted for that function.
@allow(unused_function)
fn helper() {
// This function is never called, but no warning is emitted
}
fn main() -> i32 {
0
}
Suppressing Unreachable Code Warnings
When @allow(unreachable_code) precedes a function definition, no unreachable code warnings are emitted for code within that function.
@allow(unreachable_code)
fn example() -> i32 {
return 0;
let x = 42; // unreachable, but no warning
x
}
Multiple Warnings
Multiple warning names MAY be specified in a single @allow directive, separated by commas.
@allow(unused_variable, unreachable_code)
fn example() -> i32 {
let x = 1;
return 0;
let y = 2;
0
}
Relationship to Underscore Prefix
The underscore prefix convention (e.g., _unused) and @allow(unused_variable) are both valid ways to suppress unused variable warnings. The underscore prefix is more concise for individual variables; @allow is useful when suppressing warnings for an entire function or when the variable name should not have an underscore prefix.
fn main() -> i32 {
let _x = 42; // underscore prefix suppresses warning
@allow(unused_variable)
let important_name = 42; // @allow preserves the meaningful name
0
}
@copy
The @copy directive marks a struct type as a Copy type.
@copy MUST appear immediately before a struct definition.
@copy takes no arguments.
@copy
struct Point { x: i32, y: i32 }
fn main() -> i32 {
let p = Point { x: 1, y: 2 };
let q = p; // p is copied, not moved
p.x + q.x // both are valid
}
See Move Semantics for the full semantics of @copy structs.
@repr
The @repr directive is a representation guarantee marker for a struct type. @repr(c) guarantees the struct's object representation follows the selected compilation target's default C data model (the platform psABI): its size, alignment, field order, field offsets, and tail padding equal the corresponding C aggregate's.
@repr MUST appear immediately before a struct definition, and is parameterized: it takes exactly one representation argument. Only c is accepted; any other argument is a compile-time error. The parameterized form reserves room for future representations without a re-spelling.
@repr(c) is gated behind the c_ffi preview feature (ADR-0064): the marker is meaningful only at a C FFI boundary, so it requires --preview c_ffi.
A @repr(c) struct MUST be FFI-eligible: it is not empty, and every field is a C-compatible scalar, a raw pointer, a fixed array of eligible elements, or a nested @repr(c) struct. An empty struct, an enum field, an aggregate field that is not itself @repr(c), and a linear or destructor-bearing field are each rejected — the representation is never guessed. A pointer field crosses without the pointee's layout, so a pointer to an opaque or incomplete type is eligible.
Because Rue's sole memory representation (compact layout) already matches the C aggregate rule for the supported field subset, @repr(c) changes no bytes today: it is a layout no-op whose value is the forward guarantee against future native-layout evolution, and the anchor of the FFI-safety predicates.
@repr(c)
struct Point { x: i32, y: i32 }
extern "C" {
fn translate(p: ptr const Point, dx: i32) -> i32;
}
See ADR-0064 for the full C FFI boundary contract, the three FFI-safety predicates, and the staged migration plan.