Files
bux-lang/compiler/tests/borrow_test.nim
T
dimgigov 9c6b516453 feat: restructure repo, borrow checker, expanded stdlib
- Reorganize repository to Rust-style layout:
  compiler/bootstrap/  compiler/selfhost/  compiler/tests/
  library/std/  library/runtime/  tests/  tools/
- Add buxs/ Windows-compatible project root
- Add borrow checker tests and implement:
  - Alias analysis (double mutable borrow detection)
  - Use-after-move detection for own T
- Expand standard library:
  - Std::Os: Args, Env, Cwd, Chdir
  - Std::Time: NowMs, NowUs, SleepMs
  - Std::Process: Run, Output
  - Std::Io: PrintInt64 (fixes 32-bit truncation bug)
- Add examples: os_time.bux, process.bux
- Fix PrintInt to use int64_t in C runtime
2026-06-05 20:08:17 +03:00

118 lines
2.3 KiB
Nim

import std/[unittest, strutils]
import ../bootstrap/[lexer, parser, sema, types]
proc checkSource(source: string): SemaResult =
let lexRes = tokenize(source, "<test>")
check not lexRes.hasErrors
let parseRes = parse(lexRes.tokens, "<test>")
check parseRes.diagnostics.len == 0
result = analyze(parseRes.module)
suite "Borrow Checker":
test "@[Checked] function with &mut allows mutation":
let res = checkSource("""
func Mutate(val: &mut int) {
*val = 42;
}
func Main() -> int {
var x: int = 10;
Mutate(&x);
return 0;
}
""")
check(not res.hasErrors)
test "@[Checked] function rejects write through &T":
let res = checkSource("""
@[Checked]
func BadWrite(val: &int) {
*val = 42;
}
func Main() -> int {
var x: int = 10;
BadWrite(&x);
return 0;
}
""")
check(res.hasErrors)
check(res.diagnostics[0].message.contains("cannot assign through shared reference"))
test "unchecked function allows write through raw pointer":
let res = checkSource("""
func RawWrite(val: *int) {
*val = 42;
}
func Main() -> int {
var x: int = 10;
RawWrite(&x);
return 0;
}
""")
check(not res.hasErrors)
test "&T allows reading":
let res = checkSource("""
@[Checked]
func Read(val: &int) -> int {
return *val;
}
func Main() -> int {
var x: int = 10;
return Read(&x);
}
""")
check(not res.hasErrors)
test "own T type parses and resolves":
let res = checkSource("""
struct Box {
value: int;
}
func TakeOwn(b: own Box) -> int {
return b.value;
}
func Main() -> int {
var b: Box = Box { value: 42 };
return TakeOwn(b);
}
""")
check(not res.hasErrors)
test "@[Checked] rejects double mutable borrow in call":
let res = checkSource("""
@[Checked]
func Swap(a: &mut int, b: &mut int) {
let tmp = *a;
*a = *b;
*b = tmp;
}
@[Checked]
func Main() -> int {
var x: int = 10;
Swap(&x, &x);
return 0;
}
""")
check(res.hasErrors)
check(res.diagnostics[0].message.contains("mutable borrow"))
test "@[Checked] rejects use after move":
let res = checkSource("""
struct Box {
value: int;
}
@[Checked]
func Consume(b: own Box) -> int {
return b.value;
}
@[Checked]
func Main() -> int {
var b: Box = Box { value: 42 };
let x: int = Consume(b);
return b.value;
}
""")
check(res.hasErrors)
check(res.diagnostics[0].message.contains("moved"))