vlang

/

v Public
0 commits 39 issues 0 pull requests 0 contributors Discussions Projects CI

Restore CI step: Ensure V2 can be compiled with -autofree #30

The CI step Ensure V can be compiled with -autofree in .github/workflows/other_ci.yml (./v -autofree cmd/v) has been temporarily commented out because -autofree produces a compiler that cannot reliably self-compile or compile non-trivial programs.

Current status

v_af (a cmd/v build with -autofree) can compile a trivial hello world end-to-end, but aborts with double-free / use-after-free errors on programs that exercise more parser paths (e.g. struct + method + array).

Several distinct autofree-codegen bugs surface in sequence:

  1. Shared sub-buffers via shallow array push — e.g. params << params_t and for attr in attrs { p.attrs << attr }. The destination's elements share string buffers with the source; freeing both at scope end double-frees.
  2. Non-owning pointer locals — e.g. for sc := s; true; sc = sc.parent { ... }. sc is a non-owning &Scope, but autofree generates Scope_free(sc) because Scope has a user-defined free() method.
  3. Sumtype payload double-free — auto-generated sumtype _free calls _v_free on the heap-boxed variant pointer, but the same pointer is shared across copies of the sumtype value (e.g. empty_scope_object referenced by every default-constructed Ident.obj).
  4. Pointer struct fields treated as ownedgen_free_for_struct recursively frees fields like &Scope, but pointer fields in V are conventionally non-owning, so this corrupts shared state.
  5. Locals leaked into globals/struct fields — e.g. lines_cache.lines[path] = lines, p.table.module_attrs[p.mod] = module_attrs, &ast.File{stmts: stmts.clone()} — autofree of the local frees buffers still referenced through the leak target.

What's needed

Each fix here is partial — every bug fixed exposes a deeper one. A more principled approach is needed than the current shallow-detection patches:

  • A real ownership model in -autofree (escape analysis for locals stored into external storage)
  • Idempotent _free for shared types (Scope, sumtype payloads, etc.)
  • Don't auto-emit _free for pointer struct fields by default
  • Don't _v_free the variant box inside auto-generated sumtype _free

Reproducer

./v -o v_af -autofree cmd/v
echo 'fn main() { println("hi") }' > /tmp/h.v
./v_af -o /tmp/h /tmp/h.v   # works
cat > /tmp/t.v << 'V'
struct Point { x int  y int }
fn (p Point) sum() int { return p.x + p.y }
fn main() {
    p := Point{x: 1, y: 2}
    println('sum: \${p.sum()}')
}
V
./v_af -o /tmp/t /tmp/t.v   # aborts with double-free during parsing

Re-enable the CI step once a self-compiled v_af can compile a representative subset of programs (e.g. examples/tetris, option_test.c.v) without aborts.

[!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.