Skip to content

v3: fix self-host OOM and five checker/cgen regressions blocking -building-v - #27973

Merged
medvednikov merged 2 commits into
masterfrom
v3-selfhost-oom-fixes
Jul 29, 2026
Merged

v3: fix self-host OOM and five checker/cgen regressions blocking -building-v#27973
medvednikov merged 2 commits into
masterfrom
v3-selfhost-oom-fixes

Conversation

@medvednikov

Copy link
Copy Markdown
Member

`./v3 -nocache -building-v -o v4 -no-memory-limit v3.v` was OOM-killed by macOS right after the parse phase (the process allocated at ~20 GB/s in the parallel checker until jetsam sent SIGKILL — `-no-memory-limit` only disables the internal watchdog, not the OS kill). Fixing the OOM then exposed five more self-host blockers. With this PR the full bootstrap chain is green again: v1 → v3(prod) → v4 → v5, ~1.8 s total, ~740 MB steady footprint.

Memory explosion (checker)

  • `source_enclosing_fn_has_generic_param` copied the whole source file twice per call (`source[..offset]`, `source[fn_start..]` — ~5 MB per call on checker.v) and was reached for every identifier in `resolve_type`/`check_ident` because the cheap `is_bare_generic_param` guard was applied after the expensive `||` chain. Now index-scans without copies, and both call sites short-circuit on the guard first (behavior-preserving: the chain's result was only ever consumed under that same guard).
  • `closest_identifier_span` copied the file suffix once per occurrence of the searched name (O(occurrences × file size) bytes). Now uses `index_after_` and stops after the first word match past the anchor (later matches are strictly farther).

Checker fixes

  • `s[a..n] or { ... }` (gated range slice) was typed as the element type `u8` instead of the slice type; `or_expr_payload_type` now recognizes `value == 'range'` index sources (broke `v/util/version.v`).
  • `name.str` on a string in infix position resolved to the `str()` method value (`fn () string`) instead of the `&u8` field; declared builtin-struct fields now take priority over builtin method values in `selector_type`.

Transform fixes

  • `a, b := match e { ... else { return } }`: the multi-value match lowering bailed out on branches whose tail exits (return/break/continue/noreturn), falling into a broken `_ifexpr` fallback. Exiting branches now keep their body unchanged with no assignment.
  • Value-producing if-guards with multi-value destructuring (`x := if a, b, _ := f() { ... }`) bound the whole tuple to the first name; `build_if_value_guard_chain` now emits per-name `.value.argN` bindings like the statement path.

Cgen fixes (-building-v)

  • The fixed-storage-const optimization miscompiled `in const_array`: the lowered `array_get(const, i)` shares its const AST node with a `.len` selector base, which the safety scan had whitelisted, so the const was wrongly promoted to a C fixed array. Const references in plain call arguments now always count as dynamic uses.
  • `v.token` newly entered the v3.v closure (checker.v imports `v.util`), and `-building-v` template erasure left `scanner_matcher = new_keywords_matcher_trie(...)` calling a deleted function (the keep-list preserves the template AST, but cgen never emits open generic templates). Const initializers that call erased templates are now dropped with their storage; the compiler never reads them, and any new use fails loudly at C compile time instead.

Each fix was reduced to a minimal repro first (match-tuple exit branches, guard destructuring, slice-or, `.str` infix, `import v.token` under `-building-v`), and all repros compile and run correctly after the fix.

79e0c1c armed qualify_name_cache on the main checker permanently. Under
-prealloc, scoped driver stages then grow the cache map inside disposable
scope arenas, and freeze_interface_impl_names later reads freed buckets
(SIGSEGV in map_get_check). Restore the nil-unless-armed discipline; the
parallel cgen forks keep their private armed instances.
@medvednikov
medvednikov force-pushed the v3-selfhost-oom-fixes branch from d2ecd5e to 3d80692 Compare July 29, 2026 04:31
@medvednikov

Copy link
Copy Markdown
Member Author

Rebased on master. Note: the rebase surfaced a separate master regression from 79e0c1c — permanently arming qualify_name_cache on the main checker segfaults every -prealloc build (scoped driver stages grow the cache map inside disposable scope arenas; freeze_interface_impl_names later reads freed buckets in map_get_check). Fixed here as a second commit by restoring the nil-unless-armed discipline; parallel cgen forks keep their private armed instances. Verified: v1 → v3 → v4 → v5 bootstrap chain green with -gc none -prealloc.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d80692d60

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vlib/v3/types/checker.v
Comment on lines +21785 to +21793
if source.value == 'range' {
// A gated range index yields a slice of the container, not an element.
if base_type is ArrayFixed {
return Type(Array{
elem_type: base_type.elem_type
})
}
if base_type is Array || base_type is String {
return base_type

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add regression coverage for gated range slicing

This changes Option/Result payload typing for s[a..n] or { ... }, including distinct string, dynamic-array, and fixed-array paths, but the commit adds no test file. Without a focused regression test, the original element-vs-slice typing failure can recur unnoticed; please add coverage for these gated range cases as required for Option/Result behavior changes.

AGENTS.md reference: AGENTS.md:L657-L659

Useful? React with 👍 / 👎.

@medvednikov
medvednikov merged commit f8d15a3 into master Jul 29, 2026
0 of 3 checks passed
@JalonSolov
JalonSolov deleted the v3-selfhost-oom-fixes branch July 29, 2026 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant