Absolute supports parameter-only const T& and T& borrows for large,
resource-free value types. const ref T and ref T are accepted as source
aliases for C#-style code, but both are normalized immediately to the canonical
ampersand form. Value references are an ABI and aliasing feature, not a new
runtime pointer kind and not an alternative ownership model.
The first implementation is intentionally narrow:
Tmust be a concrete value type for whichTypeOwnsResources(T)is false;- the useful default threshold is the existing indirect-ABI boundary, greater than 16 bytes;
- reference parameters are permitted on functions, methods, and constructors;
- they are forbidden as return types, fields, globals, array elements, generic arguments, lambda captures, task payloads, and stored function values;
- reference mode is part of override, interface, and mangled-signature identity;
- overloads cannot differ only by value/reference mode because calls have no
separate argument-side
refmarker.
This keeps the feature separate from managed pointers. A value reference has no
allocation, generation, ownership, null state, pointer arithmetic, or delete.
Its lifetime is exactly one synchronous call.
const T& accepts an initialized value and grants shared read-only access.
It may also accept a temporary whose lifetime is extended through the call.
T& accepts only an initialized mutable lvalue and grants exclusive mutable
access for the call. Neither form may be rebound by the callee.
Both forms lower to one non-null pointer to caller-owned storage:
int64 inspect(const WideValue& value);
void normalize(WideValue& value);
define i64 @inspect(ptr nonnull nocapture readonly %value)
define void @normalize(ptr nonnull nocapture %value)The caller does not create the isolated aggregate copy required by the current
large by-value ABI. const T& may be reborrowed as const T&; T& may be
reborrowed as either mode. Conversion to raw or managed pointers is rejected.
At one call site, an lvalue passed as T& must not overlap any other argument
that can read or write the same storage. Multiple const T& arguments may
alias. Initially, overlap should be diagnosed conservatively by root symbol;
field-sensitive disjointness can be added later.
The aliases have no distinct AST, signature, overload, or ABI identity:
void normalize(ref WideValue value); // canonical: WideValue&
int64 inspect(const ref WideValue value); // canonical: const WideValue&
All escapes are compile-time errors: converting the borrow to raw, capturing
it in a closure, scheduling it with spawn, or otherwise retaining it beyond
the call is invalid. The grammar admits reference mode only on parameters, and
async/C-ABI callables, lambdas, stored function values, resource-owning structs,
classes, primitives, and generic aggregates reject it explicitly.
benchmarks/value-ref-suite compares the by-value ABI, the implemented
const T& ABI, and a raw-address control. The workload passes a 128-byte
resource-free struct to an @noinline read-only function 20 million times.
Every variant must produce the same checksum.
On 2026-07-22, an AMD Ryzen 7 5700U Windows Release run with three warmups and 15 alternating samples produced:
| Mode | Median | Min | Max |
|---|---|---|---|
| Current by-value ABI | 0.156551 s | 0.147269 s | 0.215253 s |
| Borrowed-address proxy | 0.131116 s | 0.126508 s | 0.192288 s |
The median speedup is 1.19x. This is large enough to justify explicit reference parameters at opaque call boundaries, but not large enough to replace value semantics implicitly. Small values remain by-value, and the programmer opts in where ABI stability or measured copying cost matters.
The historical table predates the direct const T& workload and is retained as
baseline evidence. New runs report all three modes. The raw-pointer control
does not claim source-level safety equivalence; it only measures the physical
address-passing floor.