Attributes (v0.2.1)
Declaration modifiers for linkage, calling convention, and compile-time behavior.
Overview
Attributes add extra instructions to a declaration. They can make a symbol public, bind it to a C name, change how a function is called, or give the compiler a code generation hint.
They are written next to the declaration they affect, so the rule is visible where the function, constant, static, struct, or enum is defined.
Most code only needs a few attributes, usually @public, @extern, @convention, @align, or @packed. Keep experimental attributes in narrow places where their purpose is clear.
Primary source: syntax/attributes/attributes.md
Syntax Signatures
fn printf(fmt: const array[char]) s32
@public
@arbitraryArgs
@extern("printf")
@convention("C");
@if(isLinux()) const PLATFORM: u32 = 2;
Behavior and Use
Attribute order does not change what they mean, but using a consistent order makes declarations easier to read.
Be careful with @extern and @convention. They describe how Thrust code connects to external symbols, so changing them can break linking or calls into C code.
Best Practices
- Use @public only for symbols that should be visible outside the module.
- Use @extern and @convention on functions that connect to outside code.
- If an attribute combination is unusual, explain it near the declaration.
Complete Attribute Catalog
This list is aligned with the compiler sources in thrustc_attributes, thrustc_token_type, and thrustc_attribute_checker.
@public- exports the declaration with public visibility. Required alongside @extern.@extern("symbol")- binds a declaration to an external symbol name.@convention("name")- chooses calling convention, for example C, fast, Win64, or X86_64_SysV.@linkage("kind")- sets LLVM linkage behavior. Accepted kinds include standard, common, dllimport, dllexport, externweak, weak, internal, linkerprivate, and linkerprivateweak.@align(N)- sets explicit alignment in bytes (static/const/local contexts depending on declaration kind).@heap- requests heap storage for local declarations.@packed- uses packed struct layout with reduced/removed padding.@hot- marks a function as frequently executed.@minSize- asks the compiler to prefer smaller generated code.@inline- inline hint that allows the backend to inline when beneficial.@noInline- prevents inlining of the function.@alwaysInline- requests mandatory inlining at call sites.@safeStack- recognized by the lexer, but the current attribute checker does not accept it on functions.@weakStack- enables lighter stack protection mode.@strongStack- enables stronger stack protection mode.@preciseFloatingPoint- preserves strict floating-point behavior where supported.@noUnwind- marks function as non-unwinding.@noReturn- marks a function as non-returning. The compiler enforces a void return type and a terminating body.@optFuzzing- marks a function for fuzzing-related compiler behavior.@pure- recognized by the lexer, but the current attribute checker does not accept it on functions.@thunk- marks function as thunk/trampoline style entry.@constructor- runs at load/init stage and must be public.@destructor- runs at unload/finalization stage and must be public.@cuda- marks a function for a CUDA-oriented code generation path.@asmSyntax("Intel"|"AT&T")- selects assembler syntax for asm functions (unstable).@asmAlignStack- requests stack alignment for assembler function contexts (unstable).@asmSideEffects- declares that assembler block has side effects (unstable).@asmThrowErrors- enables assembler error propagation behavior (unstable token maps to asm throw attribute).@promote(T1 -> T2, ...)- configures promotion map between types (unstable).@arbitraryArgs- marks a function as variadic in user-facing syntax.@if / @elif / @else- compile-time conditional directives (attribute-like syntax, handled in statement processing).
Where Each Attribute Applies
For functions, the compiler accepts attributes for visibility, linking, calling convention, inlining, stack behavior, floating-point behavior, constructors, destructors, cuda, and promote.
Assembler functions also accept asm-specific attributes such as @asmSyntax, @asmAlignStack, @asmSideEffects, and asm-throw behavior.
Static and const declarations accept a narrower set: @public, @extern, @linkage, and @align.
Struct declarations accept @public and @packed. Enum declarations accept @public. Local declarations accept @heap and @align.
Linkage and Visibility
Visibility attributes decide whether a symbol remains internal or is visible outside the module.
- @public exports a declaration through the generated object file.
- @extern binds a declaration to a symbol name that exists outside the normal Thrust name mangling path.
- @linkage selects the LLVM linkage mode. Use non-standard linkage only when object-file or platform behavior requires it.
Calling and Code Generation
Some attributes affect how a function is called or emitted by the backend.
- @convention selects the calling convention. It must match the caller and callee across FFI boundaries.
- Inlining and size attributes are backend hints or requirements. They should describe a specific need, not be applied everywhere.
- @constructor and @destructor create load and unload hooks. Keep their bodies small and avoid hidden dependencies between them.
Layout and Storage
Layout attributes should be tied to the data format or ABI that requires them.
- @align(N) sets an explicit byte alignment where the declaration kind accepts it.
- @packed changes struct padding. It can make field access less natural for the target, so use it for external layouts rather than normal data.
- @heap requests heap storage for local declarations that need it. Keep ownership and destruction rules visible near the allocation.
Example
fn c_puts(text: CString) s32
@public
@extern("puts")
@convention("C");
fn exported_add(a: s32, b: s32) s32
@public
@convention("C") {
return a + b;
}