v0.3.0
Full Changelog: v0.2.10...v0.3.0
Vix Language v0.3.0 Release Notes
Release Date: 2026-06-07
New Features
Lightweight Owner system
Vix v0.3.0 introduces the first version of the lightweight Owner system: a compile-time ownership and borrow checker designed to provide most of Rust-style memory safety with a much simpler language model.
The goal of this release is practical safety without Rust-level complexity:
- Ownership transfer for non-Copy values.
- Exclusive mutable references.
- Shared immutable references.
- Use-after-move detection.
- Dangling local reference detection.
- Copy-type inference for small/simple values.
- Statement-scoped temporary borrows as a simplified “last use” model.
The Owner pass runs after type checking, using inferred AST type information from typecheck_program(...).
Files:
include/ownership.hsrc/Ownership/Ownership.cppsrc/main.cCMakeLists.txt
New reference syntax: ref and mut ref
References now use explicit keyword syntax instead of the old & spelling.
Immutable shared reference:
fn read(x: ref i32): i32
{
return @x
}
fn main(): i32
{
let value = 10
print(read(ref value))
return 0
}
Mutable exclusive reference:
fn inc(mut p: ref i32)
{
@p = @p + 1
}
fn main(): i32
{
let mut value = 10
inc(mut ref value)
print(value)
return 0
}
Rules:
ref valuecreates an immutable shared borrow.mut ref valuecreates a mutable exclusive borrow.- A value may have many immutable borrows in the same statement.
- A mutable borrow cannot overlap another mutable or immutable borrow in the same statement.
- Temporary borrows are released at the end of the statement.
The parser still maps references internally to the existing pointer AST representation, so existing code generation can continue to reuse pointer lowering.
Files:
src/parser/lexer.lsrc/parser/parser.ysrc/Ownership/Ownership.cpp
Move checking for non-Copy values
Non-Copy values are moved by ownership-transfer operations such as assignment into another variable.
Example rejected by the Owner checker:
fn main(): i32
{
let xs = [1, 2, 3]
let ys = xs
return xs[0]
}
Diagnostic:
error [SemanticError]: use of moved value 'xs'
Legal last-use move:
fn take(xs: [i32]): i32
{
return xs[0]
}
fn main(): i32
{
let xs = [1, 2, 3]
let ys = xs
return take(ys)
}
Copy type inference
The Owner system uses a heuristic Copy model instead of requiring explicit user annotations.
Currently treated as Copy:
- Integer types.
- Floating-point types.
- Boolean values.
- References/pointers.
- Function values.
- Strings as lightweight reference-like values.
- Struct values in the current lightweight model.
- Small fixed-size arrays when their element type is Copy.
- Uppercase enum-like constructors/constants.
Currently treated as non-Copy:
- Dynamic arrays.
- Generic application/container values by default.
This keeps common Vix code ergonomic while still catching important ownership errors around arrays, containers, references, and moves.
Dangling reference checks
The Owner checker rejects returning a reference to a local variable.
Example rejected:
fn bad(): ref i32
{
let local = 99
return ref local
}
Diagnostic:
error [SemanticError]: cannot return reference to local variable 'local'
Optional references
Optional references can be expressed with ?ref T.
fn maybe_ref(flag: i32, value: ref i32): ?ref i32
{
if (flag == 0)
{
return None
}
return Some(value)
}
This provides a simple way to model “maybe a reference” without explicit lifetime annotations.
Diagnostics
Ownership diagnostics now include file, line, and column
Example:
error [SemanticError]: use of moved value 'xs'
--> src/test.vix:15:11
|
14 | print(ys[0])
15 | return xs[0]
| ^
Fixes:
- Ownership errors now fall back to
current_input_filenamewhen AST nodes do not havesource_fileset. - Ownership errors now call
set_location_with_column(...)before reporting. - Parser-generated unary reference/deref nodes now preserve source locations through
create_unaryop_node_with_yyltype(...).
Files:
src/Ownership/Ownership.cppsrc/parser/parser.y
Examples and Tests
Updated examples for ref
The following examples were updated from old & reference syntax to ref:
examples/quicksort.vixexamples/swap.vixexamples/pointer.vixexamples/pointer2.vixexamples/nullptr.vixexamples/list.vix
Ownership test fixture
src/test.vix now acts as a negative Owner-system test file.
It intentionally triggers:
- Use-after-move.
- Duplicate mutable borrow with
mut ref. - Returning a reference to a local variable.
It also contains legal comparison functions for:
- Last-use move.
- Copy values.
- Immutable shared borrows.
Python tests
Added ownership-focused tests covering:
- Move consumes non-Copy values.
- Last-use move is allowed.
- Copy values remain usable after assignment.
- Duplicate mutable borrow is rejected.
- Returning local references is rejected.
File:
tests/test_ownership.py
Updated existing test strings for ref syntax:
tests/test_types.pytests/feat.py
Compatibility Notes
What v0.3.0 intentionally does not include
The Owner system is intentionally smaller than Rust’s ownership model.
Not included:
- Explicit lifetime annotations such as
<'a>. - Full non-lexical lifetime analysis.
- Pin/Unpin.
- Drop checking.
- Higher-ranked trait bounds.
- Full support for complex self-referential structures.
Current simplifications
- Temporary borrow scopes are statement-based.
- Function arguments are treated as read/borrowed by default for compatibility with existing Vix code.
- The Copy model is heuristic and may evolve as the type system gains explicit Copy/Move traits.
- References are still lowered through the existing pointer representation internally.
Validation
- Rebuilt
vixcsuccessfully with the newOwnership.cppcompilation unit. - Verified
src/test.vixemits the expected Owner errors. - Verified ownership diagnostics include real file names and columns.
- Verified
ref valuepermits shared immutable borrows. - Verified
mut ref valueenforces mutable borrow exclusivity. - Verified updated examples pass
--check:examples/quicksort.vixexamples/swap.vixexamples/pointer.vixexamples/pointer2.vixexamples/nullptr.vixexamples/list.vix
- Verified regression sources no longer fail with ownership-specific
moved/borrowdiagnostics after compatibility adjustments. - Full Python test execution was not run in this environment because
pytestis not installed.