Value Model
Value & Reference Model
Status: stable reference
Concrete uses a strict value/reference model with linear types by default.
For the full safety model (capabilities, trusted boundaries, Unsafe), see SAFETY. For FFI and trust boundaries, see FFI.
Value Categories
| Type | Semantics | Default | Notes |
|---|---|---|---|
Primitives (Int, i32, bool, etc.) | Value, Copy | Copy | Always passed by value |
&T | Shared reference | Copy | Immutable borrow |
&mut T | Exclusive reference | Linear | Mutable borrow, consumed on use |
*mut T / *const T | Raw pointer | Copy | Requires Unsafe capability |
Heap<T> | Owned heap pointer | Linear | -> field access, must be freed |
| Structs | Value | Linear | Opt-in Copy via marker |
| Enums | Value | Linear | Opt-in Copy via marker |
| Newtypes | Same as inner type | Inherits | newtype UserId = Int is Copy because Int is Copy |
| Function pointers | Value | Copy | No closures |
Copy vs Linear
- Copy types can be used multiple times. Primitives,
&T, raw pointers, and function pointers are always Copy. Structs and enums opt in with aCopymarker. - Linear types must be consumed exactly once. All structs and enums are linear by default. Branches must agree on consumption. A
mutlinear place may be rebound after its old value is consumed, but assigning over a live value is E0219. One lexical name denotes one binding; a linear place contains at most one live resource.
Newtype
newtype UserId = Int; // Copy (inner is Copy)
newtype OwnedBuf = String; // Linear (inner is linear)
newtype Wrapper<T> = T; // Inherits from T
- Wrap:
UserId(42)— type-checked constructor - Unwrap:
id.0— extracts inner value - No implicit conversions:
UserIdandIntare distinct types - Zero-cost: Erased at compile time, no runtime representation
Layout Attributes
#[repr(C)]
C-compatible struct layout. Required for FFI.
#[repr(packed)]
No padding between fields. Alignment forced to 1.
#[repr(C, packed)]
struct Header { version: u8, flags: u16, length: u32 }
// sizeof = 7 (1 + 2 + 4, no padding)
#[repr(align(N))]
Minimum alignment override (N must be a power of 2).
#[repr(C, align(16))]
struct Aligned { x: i32 }
// sizeof = 16 (rounded up), alignof = 16
packed and align(N) cannot be combined on the same struct.
Intrinsics
sizeof::<T>()— compile-time byte size ofT(returnsUint)alignof::<T>()— compile-time alignment ofT(returnsUint)