100 Commits
Author SHA1 Message Date
Alexander Medvednikov 9695dbbd72 types: avoid interning and decoding type spellings in checker name filters (#31277)
Sum/alias short-name filters, builtin-symbol probes, sum constructor
callee checks, generic cast callee checks and receiver method suffix
indexing now work on existing spelling ids or raw text instead of
interning and re-parsing every name they see. A spelling that was never
interned cannot be a collected struct, enum or sum type, so the probes
return early without entering the interner.
2026-10-28 03:04:02 +03:00
Alexander Medvednikov 064d83671c compiler: compile vox2 with ~14% fewer instructions; add -show-instructions (#31274)
* compiler: add -show-instructions to report retired instructions per stage

-show-timings only prints wall time, which is noisy on a loaded machine.
-show-instructions implies -show-timings and appends the retired CPU
instructions of each stage (summed over all threads) and of the whole
process, read from proc_pid_rusage on macOS.

* transform: cache bare struct candidates and use interned names for registry lookups

Receiver method resolution scanned every checker struct for each bare
type name. Build a short-name -> qualified-struct index once per struct
registry and invalidate it when generic templates are erased.

Generic name checks rebuilt name-id indexes of the enum and transform
registries whenever they grew; look the interned name up in the
registry map directly instead.

* markused: build interface dispatch keys once per scan

The used-interface dispatch pass rebuilt every implementer method key
on each worklist round. Precompute the groups and keys once, skip the
pass when no new functions were marked, and enqueue IError keys once.
2026-10-28 02:11:29 +03:00
Alexander Medvednikov 727f3cde79 flat: test source_type_existing_id during concurrent table growth (#31273)
Follow-up to #31271. Reader threads call source_type_existing_id while
writer threads intern new spellings, so the shared table gains new chunks
and the hash index is regrown and republished several times during the
lookups. The readers clear recent-cache slots to force index probes and
check that known spellings keep their IDs, absent spellings stay absent,
lookups never intern, and a writer's earlier spellings are visible once a
later one is.
2026-10-28 01:30:08 +03:00
Alexander Medvednikov cf4ff83bc9 compiler: use numeric keys for nominal type registries (#31271) 2026-10-28 00:59:03 +03:00
Alexander Medvednikov 9cf7fe51b1 transform: invalidate receiver-method misses on checker-only registrations (#31270)
ReceiverMethodCache was reset only when the module or the transformer fn
table size changed. A method registered only in the checker (generated
specializations, signatures merged back from scoped transform batches)
left that size unchanged, so a cached miss kept returning none.

Record the checker signature snapshot (checker pointer, return-type
revision, return/param table sizes) with the cached misses and drop them
when it changes. The check runs only on negative answers, so cache hits
keep their cost.

Add late_registration_cache_test.v, which covers cached negative
is_known_fn_name and receiver-method answers followed by late
registration: in the transformer, in the checker only, in a scoped batch
worker before and after merge, in the next batch worker, and across
module switches and fn-return cache clears.
2026-10-28 00:10:56 +03:00
Alexander Medvednikov eda8ea0130 fastc: fix production PGO self-build training (#31269) 2026-10-28 00:10:26 +03:00
Alexander Medvednikov 3ebaeb81d6 compiler: cut self-compilation instructions by ~7% (#31266)
* types: skip the pref test-file check for non-test paths

* types: reuse the serial check batch arena

* transform: cache promoted scoped texts by content

* driver: reuse eager import-scan sources for the parse

The -building-v import scan read every compiler source file with
os.read_file, and the eager parse then read each file again. The scan now
reads with parser.read_batch_source into C allocator memory and the eager
parse preloads those texts, so each file is opened and read once. The
import keyword test compares bytes instead of allocating a substring.

* types: use the cached import info for active import checks

* transform: skip repeated used-fn marking for a name

* transform: front interface type lookups with a direct-mapped cache

* transform: avoid copying receiver names in method matching

* transform: match noreturn candidates without building strings

* cgen: generate fn bodies in 16 scoped batches instead of 256

Every scoped cgen batch starts with a fresh worker, so generator and
checker caches (C names, parsed types, interned types, local scopes)
are cold again. With 256 batches the self-host build re-derives the
same facts hundreds of times. 16 batches keep most of the cache warmth
while still bounding the retained scratch: peak RSS is unchanged and
the generated C is byte-identical. cgen retires about 0.5G fewer
instructions on the self-compile benchmark.

* markused: probe node visibility before names and skip repeated fn_decls miss

* cgen: return a view from const_call_name_suffix instead of a copy

* cgen: skip fixed-array return wrapper scans for types without fixed-array returns

* types: build receiver method keys lazily in selected-file collection

Try the plain receiver method key before building the escaped one, and
compare module short names through short_name_view instead of allocating
all_after_last. Self-compile fixture: -247M instructions (-0.42%), C identical.

* transform: memoize variadic and array builtin method name lookups

Probe the variadic recent cache before scanning call names for the
generic `_T_` marker, and cache `array.<method>` known-fn lookups per
method spelling, invalidated when the signature maps grow.

* cgen: build the struct field index once for serial codegen

* markused: bind fn param types without a temporary name table

* transform: add direct-mapped fronts for base type, known fn and receiver method lookups

* types: test the test-file exemption only after a private declaration is found

* types: match `mut <name> :=` without building the needle string

* transform: avoid a per-node heap copy in the escape scan

* cgen: prefilter local name exception lookups with a bitset

* markused: skip omitted-param scans for calls that pass every param

Count a callee's positional params first, return when it has none, and
stop counting call arguments once they cover all params. The scan over
omitted param types moves to an out-of-line helper, and the params loop
stops at the first body statement.

* cgen: share resolved call target matching between call_key and generic base lookup

* types: keep only set call flags in the call_info bloom

* transform: copy only live bindings when entering an implicit err scope

* cgen: reuse one scratch arena across serial codegen batches

* cgen: skip redundant call target and type resolution in call argument helpers

* types: resolve a selector's declared value type once per call-info lookup

* types: skip reflected method argument checks when no methods loop is parsed

* cgen: reuse canonical declared fn return types in the call return memo

* types: size the const selector bloom to the const tables

The shared 4096-bit name bloom saturates on the self-compile const tables,
so almost every selector field fell through to two map lookups. Build a
two-probe bloom sized to about 16 bits per const key and suffix instead.

* types: try only non-collection receiver names when no array or map method has the name

* types: skip the bodyless-method lookup when no bodyless declaration has the method name

check_call resolved every method receiver and built its `Type.method` key
whenever the program had any bodyless declaration. Collect the method names
of bodyless declarations and skip the lookup for other names. The set is
never pruned, so it stays a superset of the names that can match.

* transform: resolve the scoped node payload once when promoting batch results

* cgen: skip the veb ctx receiver scan for non-Result returns

* cgen: skip builtin leaf types when collecting referenced C structs

* cgen: walk C extern references over direct child ranges

Skip non-identifier leaves before recursing and compare the `C.`
prefix inline. The visit order and the collected reference set are
unchanged.

* transform: prefilter fixed-array view escapes by stack-local arguments

Every mark in mark_fixed_array_reference_argument_escapes needs a receiver
or argument that is stack-local storage holding an inline fixed array.
Check that per argument before resolving the callee signature, and skip
the arguments that cannot be marked.

* cgen: compare current-module selector bases without allocating

* transform: keep compilation-table text ids across promotion windows

* cgen: skip impossible special-name comparisons in direct_call_name

* builtin: let the compiler skip unmapping prealloc arenas at exit

* markused: cache the positional param count of fn decls

* cgen: record a local's declaration facts under one storage key

* builtin: recycle 1M prealloc scope blocks instead of refaulting them

Scope arenas grow to 1M blocks, but the per-thread recycle cache was
capped at 2 MiB, so it held at most two of them. Every scope end unmapped
the rest and the next scope faulted the same pages in again. Keep up to
16 blocks or 16 MiB per thread.
2026-10-27 23:09:06 +03:00
Alexander Medvednikov ba73b08b1b compiler: keep structural type queries in numeric dataflow (#31237)
* compiler: cache structural type queries by spelling ID

* compiler: close remaining getter-based structural type queries

* compiler: compact numeric type syntax and cache registry queries

* compiler: defer unused type views and index syntax by numeric ID

* compiler: make rare type views lazy and remove cold query allocations

* compiler: reuse numeric type metadata and inline syntax hits

* compiler: finish numeric warm queries and defer rare name views

* compiler: defer uncommon lexical type views until requested

* compiler: skip redundant syntax lookups and defer qualifier views

* Reuse unchanged type IDs and compact plain-name syntax publication

* compiler: compact immutable type query metadata

Store query flags in bitsets and omit zero and owner-identity scalar and span values from the persistent payload. Preserve full-width signed query values and process-owned immutable views.

* compiler: bound type syntax scratch allocations and packing work

* flat: share syntax layouts and reclaim query construction scratch

* flat: pack spelling metadata and avoid short render arenas

* flat: reduce immutable syntax lookup and name packing work

* compiler: avoid interning unused written type operands
2026-10-27 17:55:53 +03:00
Alexander Medvednikov 0cfd53ef3f compress.szip: preserve UTF-8 filename encoding (#31243) 2026-10-27 17:47:24 +03:00
Alexander Medvednikov c81b3b236f transform: avoid folding array text after storage escapes (#31234) 2026-10-27 17:46:11 +03:00
Alexander Medvednikov 9e1d7f2416 docs: clarify when generated platform C type names are available (#31244) 2026-10-27 13:11:11 +03:00
Alexander Medvednikov 0550bf7a4f x.markdown: fix numeric reference and URI autolink boundaries (#31246) 2026-10-27 13:10:55 +03:00
Alexander MedvednikovandAlbris W 8a3f84415a math.decimal: preserve internal scale with Go-style formatting (#31245)
Preserve decimal coefficient and scale internally, trim normal string output, and provide explicit fixed-place formatting. Keep default division at sixteen fractional places regardless of stored operand scale. Supersedes #31215 with the requested Go-style semantics.

Validated with literal ./v self, decimal tests under normal GC and GC none, formatting, Markdown and the executable README example. Independent agent review approved the exact source and validation evidence.

Co-authored-by: Albris W <admin@albrisllc.com>
2026-10-27 12:18:14 +03:00
Alexander Medvednikov ac58c9b1d2 net.smtp: bound TLS test server accept and publish ready port atomically (#31239) 2026-10-27 11:48:27 +03:00
Alexander Medvednikov f5b7142aba net.openssl: honor TLS server upgrade verification and ALPN config (#31238) 2026-10-27 11:48:19 +03:00
Alexander Medvednikov 75365168ad cache: reuse bootstrap builtin objects in test builds (#31219)
* cache: retain builtin objects across test compilations

* checker: recognize builtin lifecycle attributes

* cache: stabilize ignored local names across source reparsing

* transform: preserve generic struct map return types

* cache: preserve error dispatch IDs and portable make warmups
2026-10-27 11:46:33 +03:00
Alexander Medvednikov 7ec48941f8 driver: remove implicit test binaries after execution (#31236) 2026-10-27 10:16:31 +03:00
Alexander Medvednikov 11c80aa65b transform: preserve nested array initializer clone decisions (#31222)
* transform: retain clone decisions in nested array initializers

* types: exercise clone-copy cache lifecycle in normal tests
2026-10-27 07:42:55 +03:00
Alexander Medvednikov 74fa65136a types: check quoted labels in raw inline assembly (#31221) 2026-10-27 07:42:50 +03:00
Alexander Medvednikov efa3d1ce5e parser: preserve keyword fields after match defaults (#31226) 2026-10-27 07:42:04 +03:00
Alexander Medvednikov d980d51c14 cgen: avoid double-dropping runtime-owned map keys (#31223) 2026-10-27 01:59:50 +03:00
Alexander Medvednikov 75320536e6 cgen: deduplicate owned closure drop helpers by symbol (#31213) 2026-10-26 23:38:43 +03:00
Alexander Medvednikov 9db0ba48fa ci: fix macOS bootstrap and example builds (#31205)
* fastc: dereference pointer-returning calls with indexed arguments

* builtin: avoid FastC symbol collision in two-byte string search

* tools: build the macOS tray example as a project folder

* tests: align parser and Wasm audits with supported features

* transform: preserve caller types in generic specializations

* cgen: preserve source module identity in cached declarations

* cgen: resolve cached capture array fields in their source module

* test: assert the default SLH-DSA key description
2026-10-26 22:30:54 +03:00
Alexander Medvednikov f06ca10c87 net.mbedtls: avoid empty client credentials with system trust (#31202) 2026-10-26 18:55:01 +03:00
Alexander Medvednikov 742c65766b tests: read canonical struct initializer operand in defaults regression (#31207) 2026-10-26 18:33:19 +03:00
Alexander Medvednikov 03b23d184d tests: isolate codegen fixtures between concurrent runs (#31206) 2026-10-26 17:49:07 +03:00
Alexander Medvednikov f13fb293ad ci: fix macOS self-test failures and worker selection (#31196)
* ci: respect macOS self-test workers with fail-fast

* builtin: keep vgc thread-cache test allocation at runtime

* driver: align wasm array gate tests with string support

* tests: use selected C compiler for raw assembly fixture
2026-10-26 16:58:04 +03:00
Alexander Medvednikov 6cce632507 compiler: avoid repeated self-compilation lookups and copies (#31197)
* compiler: reduce repeated self-compilation lookups and copies

Reuse immutable type and call metadata, avoid unnecessary name work and
node copies, and accelerate standard map, string and builder operations.
Add focused coverage for cache invalidation and borrowed storage lifetime.

* docs: record paired self-compilation results
2026-10-26 16:01:18 +03:00
Alexander Medvednikov 88ef628eb4 checker: transfer aggregate closure captures atomically (#31182) 2026-10-26 10:40:16 +03:00
Alexander Medvednikov 90d0a9f585 types: track owned string pop arguments and refresh ownership fixtures (#31180)
* tests: align ownership fixtures with current compiler contracts

* types: track owned string pop arguments before clone shortcuts
2026-10-26 09:48:58 +03:00
Alexander Medvednikov 73180e3ccc transform: retain borrowed clone decisions in array initializers (#31179) 2026-10-26 09:21:46 +03:00
Alexander Medvednikov 49dd786cdd tests: avoid factory module name in generic chain fixture (#31178) 2026-10-26 09:07:39 +03:00
Alexander Medvednikov b99da43ad4 transform: preserve lexical ownership scopes during map cleanup (#31177)
* transform: preserve ownership scopes around map cleanup

* tests: avoid Result error binding in Option projection fixtures
2026-10-26 09:03:04 +03:00
Alexander Medvednikov 5aa85424da tests: match current integer type in naked profiling regression (#31175) 2026-10-26 08:49:18 +03:00
Alexander Medvednikov 7e7080cf23 tests: align ownership regression fixtures with current metadata APIs (#31173)
* tests: update ownership fixtures for current metadata and output

* tests: migrate remaining ownership descriptor identities
2026-10-26 08:43:02 +03:00
Alexander Medvednikov c564117346 tests: preserve builtin interface implementers in identity fixture (#31172) 2026-10-26 08:42:09 +03:00
Alexander Medvednikov cf3d560a56 tests: resolve indexed generic match pattern spellings (#31171) 2026-10-26 08:12:57 +03:00
Alexander Medvednikov df0d61edb9 tccbin: refresh the immutable validator bootstrap (#31163)
* tccbin: refresh the immutable validator bootstrap

* tccbin: preserve bootstrap flags under Bash 3.2
2026-10-26 08:11:42 +03:00
Alexander Medvednikov 523bdcbd5a gg, multiwindow: repair macOS native drawing and string bridges (#31170)
* gg, multiwindow: repair macOS native drawing and string bridges

* tests: verify current macOS bridge geometry and helper contracts
2026-10-26 08:02:14 +03:00
Alexander Medvednikov 578b7c6e32 transform: publish all scoped node payload metadata (#31169) 2026-10-26 08:00:21 +03:00
Alexander Medvednikov 67c46cde0c net.http: test ALPN fallback overlap with a response barrier (#31168) 2026-10-26 08:00:06 +03:00
Alexander Medvednikov 5ab5f9b0c2 db.redis: allow bounded RSA handshake time in TLS fixtures (#31166) 2026-10-26 07:41:43 +03:00
Alexander Medvednikov 7017c7ccf1 tools: use current serial compiler self-check in test-all (#31165) 2026-10-26 07:23:52 +03:00
Alexander Medvednikov 976e9bbb74 tests: exercise portable header embedding and preserve SDK ownership (#31164) 2026-10-26 07:23:29 +03:00
Alexander Medvednikov ac5a2d2bab tests: repair source-value checker fixtures and ORM formatting (#31162) 2026-10-26 07:06:23 +03:00
Alexander Medvednikov 8e899f1765 types: enable diagnostics in synthetic string cast fixture (#31159) 2026-10-26 06:51:52 +03:00
Alexander Medvednikov 79b37ae493 fastc: speed up full compiler builds (#31045)
* fastc: avoid repeated local type and member lookups

* fastc: reduce token, dispatch, and compilation overhead

* fastc: match native write count to current uint ABI
2026-10-26 06:41:27 +03:00
Alexander Medvednikov d0a2eae518 cgen: preserve deferred constant dependency context (#31055)
* cgen: preserve deferred constant dependency context

* driver: reuse diagnostic state when printing type errors

* cgen: store deferred constant dependencies beside their names
2026-10-26 06:33:40 +03:00
Alexander Medvednikov be72ff28cc launcher: keep fallback installation progress out of fixture diagnostics (#31158) 2026-10-26 06:32:13 +03:00
Alexander Medvednikov d2fc18b534 gg, test-all: repair macOS drawing bridges and portable C checks (#31157)
* driver: reuse diagnostic state when printing type errors

* gg, test-all: repair macOS geometry bridges and portable C checks

* test-all: propagate output expectation failures to the summary

* gg: document touched macOS drawing and screen helpers
2026-10-26 06:25:03 +03:00
Alexander Medvednikov 1e2ca845ca compiler: carry type operands as u32 and cache syntax queries (#31153)
Carry compiler type operands and explicit generic arguments as interned u32 spelling IDs through checking, transforms, reachability and backends. Cache composite spellings and immutable syntax-query metadata. Keep semantic TypeId values distinct and preserve textual parsing, diagnostics and emission boundaries.

Resolve integration with current master, including typeof operand relocation in both parallel parser merge paths and the diagnostic state variable rename.

Validation: all-backend/ownership compiler C generation, Clang syntax checks, twelve affected-source -check runs, typeof compile and diagnostic comparisons, matched loom2v C and diagnostics, and five chained ./v self replacements without fallback. Assertion and test-suite execution remains deferred by the user until performance parity.
2026-10-26 05:55:48 +03:00
Alexander Medvednikov e160c30952 driver: reuse diagnostic state when printing type errors (#31156) 2026-10-26 05:54:48 +03:00
Alexander Medvednikov 87401cb4bc driver: enable cross_compile for the bundled Linux sysroot (#31140) 2026-10-26 05:32:23 +03:00
Alexander Medvednikov 8795d8ea6c cgen: avoid Windows macro collisions in main functions (#31054)
* cgen: avoid Windows macro collisions in main functions

* cgen: keep Windows macro function names in the reserved namespace
2026-10-26 05:30:37 +03:00
Alexander Medvednikov f90ea2e0a8 fontstash: document isolated stb_truetype implementations (#31053) 2026-10-26 05:30:32 +03:00
Alexander Medvednikov 8bd7ffa3f8 Fix macOS CI with default caching and integer migration (#31154)
* cgen: scope cleanup switch cases for older Apple Clang

* checker: let zero assignments leave reference sum variants

* math.big: pass signed byte counts to memory helpers

* checker: limit zero literal inspection to reference narrowing

* checker: stop loop narrowing scans before the current assignment

* tests: repair integer migration inputs for macOS self tests

* checker: return platform int for translated pointer differences

* examples: use signed byte counts for graphics buffers

* cgen: preserve headerless mmap bindings in cached modules

* fastc: repair pointer difference formatting and bootstrap fallback
2026-10-26 05:23:57 +03:00
Alexander Medvednikov f7e9ee96c2 compiler: reduce repeated work in self-compilation hot paths (#31109)
* compiler: reduce repeated work in self-compilation hot paths

* tests: remove diagnostic traces from compiler regressions

* docs: record verified self-compilation improvement
2026-10-25 23:10:04 +03:00
Alexander Medvednikov eab77e7ec3 fastc: match cgen for printing, typeof names, numeric promotion, ** and generic struct operators (#31114)
* fastc: promote mixed numeric operands the way the checker does

FastC typed `u8 * int` as u8 and `int * i64` as int, so values were
truncated and `typeof` disagreed with cgen. Infix arithmetic now uses
the checker's rule: the operand the other one widens to wins, f32 only
stays f32 against non-f64 operands, and an integer literal adopts the
other operand's type unless it does not fit it. `**` uses the same
rule instead of its own copy.

A prefix `&` now addresses only the operand before a top-level `+` or
`-`, so `&u8(raw) + n` stays a `u8` pointer step. The old "left side
wins" rule hid that scope bug.

* fastc: spell typeof names the way V does

`typeof(x).name` returned FastC's C spelling of the type (`Array_int`,
`Point*`, `strings__Builder`, `FixedArray_3_FASTC_ARRAY_OF_int`) and the
literal pseudo-types (`integer literal`). Convert them to V's spelling,
as cgen does: `[]int`, `&Point`, `strings.Builder`, `[3]int`, and
`int literal` / `f64` for literal expressions.

program_output_test.v compiles and runs a FastC program and compares
its output; later FastC printing fixes add their cases there.

* fastc: print non-string values with eprint and eprintln

`eprintln(5)` reached the C compiler as `builtin__eprintln(5)`, an int
passed for a string. eprint and eprintln now take the selfhost print
path of print and println: a value is converted with its `str()` method,
or formatted as string interpolation formats it, and an enum goes
through its generated `str` helper, since the enum print helper writes
to stdout. The simple call fast path no longer takes them either.

The program output test helper now merges stderr into the output it
returns, as its comment said.

* fastc: print inline map literals

FastC could not infer the type of an inline map literal, so
`println({'k': 1})`, a map literal passed to a function and an array of
map literals were emitted as raw tokens and failed to compile. Infer
`{key: value, ...}` from its first entry, as the streaming map literal
reader does, and register the map typedef where the literal argument is
rendered.

* fastc: fold integer powers in enum discriminants

C has no `**` operator, so an enum value like `a = 2 ** 3` made FastC
stop with "does not support enum discriminant". Fold every `**` whose
operands are integer literals before the discriminant is rendered,
innermost first, so `2 ** 2 ** 2`, `1 + 2 ** 4` and `(2 ** 2) ** 3`
become constants as they do in the C backend. Parenthesized literal
operands now fold as well.

* fastc: keep the module prefix and indent nested values in default str()

The default struct `str()` printed `Pt{` for `mymod.Pt` and left nested
structs, arrays of structs and sum type fields unindented. Print the
source type name (stripping only `main.` and `builtin.`) and indent
nested aggregate fields the way cgen does, with a self-contained C
helper (builtin string functions may be pruned).

* fastc: print pointers and options like cgen

Interpolation and print/println of a `&T` value keep the `&` (`&nil` for
a null pointer), and options print as `Option(5)` / `Option(none)`, as
cgen does. Struct fields of these types print the same way. A `mut`
local or a smartcast, which C holds through a pointer, prints as its
value.

* fastc: monomorphize generic struct operators and self-referencing methods

Operator methods (`fn (a Gen[T]) + (b Gen[T]) Gen[T]`) were not scanned
as generic methods, because their name token is not a `.name`. Their
receiver then looked like a non-concrete instance, and any further
`Gen[T]` inside a method body or signature counted as a nested generic
reference. Both left the struct unresolved, so `Gen[int]{3} + ...`
stopped the parser with "top-level `+` after `main`".

Scan overloadable operator methods too, and render every own-struct
`S[T]` in a generic method as `S_mono_<C>`, like the receiver.

* fastc: update stale expectations in the reserved identifiers test

FastC now emits the platform int type (i64 on 64-bit targets) and
module-prefixed function names (main__calculate, main__auto), so the
keyword-escaped function name __vf_function_auto is no longer produced.
Update the expectations to the current output; the program still
compiles with tcc and prints 66.
2026-10-25 19:05:55 +03:00
Alexander Medvednikov a6a1c3c7dd vgc, driver, sync: static MinGW runtime, TinyCC TryAcquireSRWLock*, high arenas, STW backoff (#31108)
* driver: link the MinGW runtime statically

GCC on MinGW keeps thread-local variables with emutls, which calls into
libwinpthread, and its driver adds -lpthread after all user arguments.
Programs built with MinGW GCC or Clang therefore needed
libwinpthread-1.dll next to the executable.

End the link with -Wl,-Bstatic, after the program's own libraries, so the
libraries that the MinGW driver appends come from static archives. The
program's libraries keep their import libraries. MSVC, TinyCC, object
builds and freestanding builds are unchanged.

* sync: look up TryAcquireSRWLock* at run time under TinyCC on Windows

TinyCC links kernel32.dll through its own lib/kernel32.def, which lists
neither TryAcquireSRWLockExclusive nor TryAcquireSRWLockShared. A program
built with `-d windows_7` calls them from Mutex.try_lock,
RwMutex.try_rlock and RwMutex.try_wlock, and did not link:
"tcc: error: unresolved reference to 'TryAcquireSRWLockExclusive'".

sync_windows_tcc.h now maps both names to small wrappers that find the
function in kernel32.dll with GetProcAddress once and cache the address.
The executable no longer imports them, so the bundled .def can stay as
it is. GCC, Clang and MSVC builds do not include the header and still
import the functions directly.

try_lock_windows_7_test.v builds with `-d windows_7` on Windows, so the
TinyCC Windows job now links and runs these calls.

* vgc: start the arenas at 0xc000000000 on 64-bit macOS and Linux

macOS hands out low addresses first. In a large heap the arenas reached
0x300000000, where data constants like 0x300000001 point, and the
conservative scan kept objects alive through them.

vgc_os_alloc_heap now passes an address hint to mmap, starting at
0xc000000000 (the hint Go uses for the same reason) and advancing by the
arena size, rounded to 64 MB. The hint is only advisory: when the range is
taken, macOS searches upward from it, and Linux picks its default, which
is already high. Hints stay below 2^47, because macOS silently returns low
addresses for hints at or above 2^48. A failed mmap falls back to the plain
one. Other systems and 32-bit targets keep the plain mmap; Windows keeps
MEM_TOP_DOWN.

test_the_heap_is_far_from_small_numbers now also checks 64-bit macOS and
Linux.

* vgc: back off instead of spinning while the world is stopped

Safepoint waiters, the collector waiting for them, the unregister loop
and the vgc mutex now pause, then yield, then sleep 50 us (Windows:
SwitchToThread) instead of spinning on sched_yield. Threads acknowledge
the stop request by epoch instead of a shared counter, so a waiter that
is still leaving one collection is not counted for the next one. The
collector waits at most 1 ms for the stops.
2026-10-25 19:04:01 +03:00
Alexander Medvednikov 54ea05696e parser, cgen, transform: named constants next to f32/small ints, 5 - -a, f32 assert digits (#31102)
* parser: accept a negated right operand after a binary minus

`5 - -a`, `c - -1.2` and `a - - b` failed with "invalid expression:
unexpected token `-`". The parser rejected every prefix `-` that had
exactly one `-` before it in the source text.

V 0.5.2 rejects a doubled minus only when the right operand negates a
literal again: `5 - - -5` and `5 - -(3)`. `-3` is a number literal there,
so `5 - -3` is accepted. Check the parsed right operand of a binary `-`
instead of the source text, and keep translated code exempt.

translated_expressions_test.v used `13 - -5` as the ordinary-code
rejection; it now uses `13 - - -5`, which 0.5.2 also rejects.

* cgen: print f32 assert operands with f32 digits

A failed assert printed an f32 operand through f64__str((double)x), so
`p := f32(1.2)` showed as `1.2000000476837158`. Use f32__str for f32
values in interface_implicit_str_expr, which also serves generic
println and the debugger, so they print `1.2` like V 0.5.2.

* cgen: treat named float constants as f32 next to an f32

With `const c = 1.2` and `p := f32(1.2)`, `p == c` was false and
`p - c` was not 0. An untyped float const is a C double macro, and cgen
cast only literals and literal arithmetic to `float` where an f32 is
expected. V 0.5.2 keeps such a const an untyped float, so it compares
equal.

untyped_numeric_literal_expr_info now follows a const name (bare,
module-qualified or a selector) to its initializer, and the const is
cast as a whole, `(float)(main__c)`. Locals and parameters shadow
consts, and inside an initializer only the bare consts of the const's
own module are followed.

* transform: promote named and folded int constants next to a small int

With `const c = 3` and `u := u8(255)`, `u + c` was 258 and
`typeof(u + c).name` was `int`; V 0.5.2 and V3's checker give 2 and
`u8`. The same happened for `u + 0x03`, `u + (3)`, `u + (1 + 2)` and
`i8(100) * c`, and i8/i16 operands were never promoted.

promote_numeric_literal_infix_type accepted only a bare decimal int
literal next to an unsigned type. It now evaluates untyped int
constants built from literals in any base, signs, parentheses,
`+ - * / %` and named constants, and gives the other operand's type
when that type is u8, u16, i8, i16, u32, u64 or usize and the value
fits it. A value that does not fit keeps the previous type, so
`u8(255) + 300` is still an `int`.
2026-10-25 19:00:10 +03:00
Alexander Medvednikov ad4f91f3e6 vet, types: fix the musl CI jobs (vet $if branches, library exports exempting no-main programs) (#31096)
* vet: keep every $if branch, so strings in other hosts' branches are skipped

`v vet` parsed each file with only `is_fmt` set, so the parser evaluated
`$if` conditions for the host and dropped the false branches. Their
string literals never reached vet's AST walk, which is what marks the
lines of a multi-line string as exempt from the indentation and
trailing whitespace checks, so those lines were reported as space
indentation. The result depended on the host: the arm64 native tests in
vlib/v/gen/arm64, which embed V programs inside `$if macos && arm64`,
passed on macOS arm64 and failed `v test-cleancode` everywhere else,
including the docker-ubuntu-musl and docker-alpine-musl-gcc CI jobs.

Set `preserve_comptime_conditionals`, as vfmt does, so every branch is
kept and walked.

* types, driver: count only the program's own exports as a library

A project without a `main` module was accepted whenever any function in
the build had `@[export]`. Builtin exports `backtrace` and `data_start`
under `-d musl` (added for `-cc musl-gcc` and on musl hosts), and stbi
exports its allocator, so with musl, or with `import stbi`, a module
without `main` built silently, while glibc rejected it. On Alpine 15
compiler_errors_test fixtures failed because of that.

The checker now looks for exported functions only in the files it
reports diagnostics for, and the driver no longer passes "any export"
as an exemption.
2026-10-25 18:32:46 +03:00
Alexander Medvednikov ff86d4d4c0 ci: install the X11/GL libraries the compiler job's GUI smoke tests need (#31120)
test_all.vsh compiles and smoke-runs examples/2048 and examples/tetris
whenever `xvfb-run` exists, which it does on the GitHub ubuntu-24.04
image. The compiler job only installed gobjc, so the 2048 compile failed
with "library 'Xrandr' not found" / "X11/Xlib.h: No such file or
directory", failing section 5/8 (Unlocked examples C oracle) on every
master push.

Install the headers and libraries gg and sokol link against
(X11, Xi, Xcursor, Xrandr, GL, EGL), plus the Mesa DRI drivers for the
xvfb run.
2026-10-25 18:32:34 +03:00
Alexander Medvednikov 5fd1f6a03b builtin,v.workers: declare linked Linux helpers with @[c_extern] for FastC (#31138)
* builtin,v.workers: declare linked Linux helpers with @[c_extern] for FastC

FastC only emits prototypes for @[c_extern] C functions (or header-free
.c.v files whose stem matches a linked .c/.o input). v3_linux_name_worker
(syscalls_linux.c) and the v__gc_*_linux helpers (gc_boehm_helpers.c) are
defined in linked objects, so FastC called them undeclared, which the
bundled tcc rejects as an implicit declaration on Linux.

cgen is unaffected in ordering: the static copies embedded in cross/object
output are emitted before the runtime prototypes, and a plain prototype
after a static definition keeps internal linkage.

* builtin: declare GC_set_no_dls with @[c_extern] for FastC

FastC emits C prototypes only for `@[c_extern]` C functions. The Linux
debugger-init path calls `C.GC_set_no_dls`, so FastC Linux builds of
programs using the real builtin failed under tcc with "implicit
declaration of function 'GC_set_no_dls'" (vlib/v/gen/fastc/
vlib_constructs_test.v). The other GC entry points used at startup are
already declared this way.
2026-10-25 18:29:48 +03:00
Alexander Medvednikov e19a0f4d71 driver, ci: fix Linux Objective-C link failures in the V3 unit shards (#31137)
* driver: name GNU ld missing libraries without the trailing colon

GNU ld reports `cannot find -lobjc: No such file or directory`, so the
missing-library hint said C library `objc:` was not found. Strip the
separator that follows the library name.

* ci: install libobjc-14-dev next to gobjc on ubuntu-24.04

clang on the runner selects the GCC 14 installation, while gobjc only
provides the libobjc.so development link for GCC 13, so linking the
Objective-C tests with `-lobjc` failed.
2026-10-25 18:29:41 +03:00
Alexander Medvednikov 055e061b52 fastc, v3 tests: fix three Linux V3-shard failures on master (#31135)
* fastc: keep static initializers for target globals with fixed-array struct defaults

Dynamic struct literals copy fixed-array fields with memcpy since #31036.
global_initializer_is_constant rejected that call, so such globals were
initialized at startup and target_global_startup_test failed. Accept the
memcpy only in the temporary-allowing pass; the static re-render is
checked again without temporaries.

* fastc: skip prestarted worker test where prestart is unsupported

fastc_start_capture_input only starts compiler processes on macOS, so on
Linux workers.active is false and the test failed in the V3 shards.

* v3 tests: scope fixed-array heap check to the tested function

On Linux glibc the backtrace reader in vlib/builtin keeps its read buffer
on the heap because it escapes into the returned string. The whole-file
assert matched that helper; check only the body of local_score.
2026-10-25 18:29:33 +03:00
Alexander Medvednikov 1a228e188b ci: fit the cmd/v series of the perf comparison within the time limits (#31127)
A serial non-prod self-build of cmd/v now averages about 65s on the
ubuntu-24.04 runner, above the default 60s `v repeat` limit, so the
perf-compare job failed with "Performance regression detected" for the
master build itself. Raising only the limit would not help: 3 repeats of
2x12 runs of that series alone take about 78 minutes, more than the
80 minute job timeout once the builds and the other series are counted.

Run the cmd/v -check, -o .c and -o .exe series once, with 3 measured
runs and 1 warmup each, and a 300s limit.
2026-10-25 18:29:26 +03:00
Alexander Medvednikov de9b76e869 cgen: cast string literals to u8* in static string initializers (C++ compatibility) (#31126)
C++ rejects initializing the `u8*` string field from a `const char*`
literal. The `_SL` macro alone produced about 19k of the errors in the
Other CI g++ step; the const initializers, the debugger string literal
and the error sentinel global produced most of the rest.
2026-10-25 18:29:20 +03:00
Alexander Medvednikov 1be458cf31 fastc: declare thread handle types at .wait() sites too (#31124)
The thread handle typedef and its waiter were only registered by `spawn`.
A `[]thread T` that is waited on in code whose only `spawn` is compiled
out by `$if` referenced both without defining them. The driver does this
with its prestarted FastC workers, which only macOS spawns, so FastC
builds of cmd/v failed on Linux with
`'__vf_thread_kF_5f_5fFastcPrestartedCUnits' undeclared`.

`.wait()` lowering now registers the typedef and waiter when the file
has not done so yet.
2026-10-25 18:29:11 +03:00
Alexander Medvednikov c984dc6e33 fastc: declare vlib native helpers like cgen does (#31123)
FastC skipped extern prototypes for helpers declared in vlib files that
also include a C header, or whose linked object has a different stem
than the declaring file. On Linux with tcc this produced implicit
declarations of `v__gc_debugger_present_linux` and
`v3_linux_name_worker`, breaking the FastC channel, miscompile and vlib
construct tests.

Mirror cgen's rule: declare `v3_`, `v_runtime_`, `v_time_`,
`v_builtin_`, `v_set_` (and FastC's `v__gc_`) helpers when their
declaring vlib file links a C/Objective-C source or object via `#flag`.
2026-10-25 18:29:04 +03:00
Alexander Medvednikov 7071d606bb generics: fix mut a ?&T instances, typeof smartcasts, guards (#31116)
* checker: accept `mut a ?T` with a pointer `T` in generic instances

A `mut a ?T` parameter is stored as its semantic type `&?&T` (see
mut_param_semantic_type). Substituting `T=&Point` into that gave
`&?&&Point`, so `bump[&Point](mut pr)` with `pr ?&Point` failed with
"cannot use `&?&Point` as `&?&&Point`", for generic fns, methods of
generic structs and generic interface methods. V 0.5.2 accepts it.

Such a parameter is now re-derived from its declared `&?T` text,
substituted, and given its semantic type again, so the instance takes
`&?&Point`, the type of a `mut a ?&Point` parameter.

* checker: keep the `mut` of parameters in generic fn and method values

The value of a generic fn (`f := clear[Point]`) or of a generic method
(`m := s.set[Point]`) got a fn type without parameter mutability, so
calling it with `mut` args failed with "parameter 1 is not `mut`",
while the value of a plain fn keeps it. V 0.5.2 accepts the generic fn
values (and panics on the generic method values).

Both now take the declared mutability of the fn's parameters; a method
value drops its receiver's, since the receiver is bound.

* transform: name the smartcast type in `typeof` of generic bodies

`typeof(a).name` in a generic body is folded while the body is cloned
for an instance, from the declared type of `a`. It ignored the
narrowing of the enclosing `if a != none`, `if a == none {} else`,
`if a is T`, `if a !is T {} else` and `match a` branches, so it named
`?Point` (or `IntOrStr`, `Named`) where the same non-generic body
names `Point` (`int`, `&Dog`).

The clone now records those narrowings, with the instance's types, for
the branches it clones, and the `typeof` fold names the narrowed type
as the non-generic fold does (`&Point` for a `mut a ?Point` parameter,
`&Dog` for an interface).

* checker: report `if v := x` over a non-option in generic instances

A generic body like `fn show[T](a T) { if v := a { ... } }` called with
a `T` that is neither an option nor a result was accepted by the
checker and then failed in the C compiler. The clone of the instance
does report "expression should either return an Option or a Result",
but check_concrete_instance_members dropped it with every other error
that is not known to be reliable for clones.

Keep that error when the guarded operand is a name, a literal or a
field of them, as is done for operator errors, and its declared type
is not an option or a result. The instance is now reported at the
guard, as in a non-generic body and as in V 0.5.2, whose output the
new checker fixture matches byte for byte. Guards over option
instances, `?T` and `mut ?T` parameters, map indexes and options that
a smartcast narrowed to their payload (accepted since #30979) stay
valid.
2026-10-25 18:28:56 +03:00
Alexander Medvednikov 59380ef36e types, transform: fix sum type narrowing after = and += (#31115)
* types, transform: end a sum type narrowing when another variant is assigned

After `if mut b.v is int { b.v = 5; y := b.v + 1 }` the checker typed
`b.v` as `int`, but the transform had dropped the narrowing at the
assignment, so cgen read the sum value as an int and emitted invalid C.
Assigning another variant (`b.v = 'str'`) left the checker narrowed
too, so `b.v + 1` was accepted after it.

The checker now decides whether an assignment keeps a narrowing. A
value of the narrowed variant keeps it, as in V 0.5.2. Any other value
(another variant, a `Val(...)` sum value) ends it, and so does an
assignment to a parent of the narrowed value. (0.5.2 rejects such an
assignment to a narrowed member, and keeps a local narrowed after it,
reading a string as an int.) The lexical smartcast queries that the
transform relies on ask the same question (assignment_keeps_narrowing),
in nested blocks, `for` bodies and `match` branches as well, so the
checker, the transform and cgen agree.

* types, transform: check compound assignments to narrowed sums on the variant

`b.v += 2` inside `if mut b.v is int` was rejected ("operator `+=` not
defined on left operand type `Val`") although `b.v++` and
`b.v = b.v + 2` work there, because the operator was checked on the
declared sum type.

A compound assignment to a sum value narrowed by `is` or `match` now
operates on the narrowed variant, for members, locals and values
reached through a pointer, and keeps the narrowing, so the later reads
in the checker, the transform and cgen all use the variant.
2026-10-25 18:28:48 +03:00
Alexander Medvednikov abec0a455a operators: reject unsupported overloads, fix enum alias operators (#31101)
* parser: reject `|` and `^` operator overloads

token.is_overloadable came from the tinyv parser and includes `|` and
`^`, so `fn (a T) | (b T) T` parsed as an operator method and passed
the checker. Nothing lowers those operators, though: transform's
struct_operator_symbol only maps the documented `+ - * ** / % < ==`
(and the comparisons derived from them), so `a | b` on struct operands
was emitted unchanged and failed in the C compiler.

V 0.5.2 never accepted these overloads (its parser reports `expecting
method name` at the operator), and the docs list only `+ - * ** / % <
==`. Report the same error, at the same token. The declaration is still
parsed as an operator method, so the rest of the file parses normally.
A `|` inside an unclosed receiver (`fn (x int | string)`) already has
its own error, so it is not reported a second time.

* types: reject operator overloads on enums and interfaces

The checker validated the arguments and return type of an operator
method, but not its receiver kind, so `fn (a Color) + (b Color) Color`
on an enum compiled. Nothing lowers such a method: transform only turns
infix expressions on struct, alias and (for `==`) sum type operands into
operator calls. So `Color.red + Color.red` kept the enum's integer
addition and silently ignored the overload. On an interface, `==` kept
the builtin interface equality and `+` left `a + b` on the interface's C
struct, which failed in the C compiler.

V 0.5.2 rejects these with `operator methods are only allowed for
struct and type alias`, at the declaration. Report the same error for
receivers that are enums or interfaces. An alias of an enum keeps
overloading operators, as in 0.5.2. Unlike 0.5.2, `**` is checked too:
0.5.2 left it out of the list of checked operators. Also unlike 0.5.2,
sum types are not rejected: #29578 lowers their `==` overloads, and
v.types relies on one (`Type.==`).

* parser: reject explicit `!=`, `>`, `<=` and `>=` overloads

The docs say these operators are generated from `==` and `<` and cannot
be overridden, but token.is_overloadable includes them, so
`fn (a T) != (b T) bool` parsed as an operator method and transform
then called it, in place of the negated `==`, for every `a != b`.

V 0.5.2 rejects these declarations in its parser with `cannot overload
`!=`, `>`, `<=` and `>=` as they are auto generated from `==` and `<``,
at the operator. Report the same error, at the same token (0.5.2's
message lacks the space before `<`; it is added here).

* cgen: give operator overloads of enum aliases their own C names

An alias of an enum can overload operators, but its methods are named
by enum_method_c_name_in_module, which spells a method as
`<Enum>_<cname(method)>`. cname of a bare operator is `_`, so every
operator of the alias got the same C name (`Pitch__`): only one body
was emitted, and `a - b` or `a < b` called the `+` overload.

Name operator methods there the way naming.c_name names every other
operator overload, in the internal namespace
(`__v3_internal_symbol_op_Pitch__plus`), so they cannot collide with
each other or with a method of the same word.

* types: derive `>`, `<=` and `>=` from an alias's own `<`

An alias that declares `<` gets `>`, `<=` and `>=` generated from it,
and transform lowers them that way, but check_infix only skipped the
builtin checks of the aliased type for an operator the alias declares
itself. So `a > b` fell through to the checks of the aliased type: an
alias of a struct without `<` reported `undefined operation`, and an
alias of an enum `only `==` and `!=` are defined on `enum``. Only an
alias of a primitive, whose own ordering is valid, compiled.

Look up the alias's `<` for these operators, as V 0.5.2 does.
2026-10-25 18:28:40 +03:00
Alexander Medvednikov d9a7697015 transform, types: convert fixed array field inits to interface arrays; reject numbers behind pointers stored differently (#31095)
* transform: convert fixed array elements in dynamic array field inits

A `[2]Item` used to initialize a `[]Named` (or `[]Shape`) struct field,
as in `Holder{ f: x }`, was copied into the dynamic array as it was, so
the field held concrete `Item` values where interface or sum type values
are read: `h.f[0].name()` panicked with `interface method Named.name not
implemented`, and a `match` over the sum type values matched nothing.
Returns, assignments, arguments and field assignments convert the
elements. transform_struct_fields and the struct update lowering sent
every fixed array value of a dynamic array field to
fixed_array_value_to_owned_array, which only copies. They now use
fixed_array_value_to_field_array, which converts elements stored
differently through transform_array_value_for_dynamic_target, as call
arguments do, and copies the other fixed arrays as before. This covers
positional, nested, anonymous, embedded and promoted fields, struct
updates, generic structs and `@[params]` arguments.

* types: reject numbers behind pointers that are stored differently

`fn take(p &u64)` accepted `take(&x)` with `x u8`, and read 8 bytes
from a 1-byte variable. The pointer branch of type_compatible compared
the pointees with plain type_compatible, which converts numbers, and
checked layouts only for containers. The call-argument fallbacks for
explicit and implicit references compared the pointees the same way.

A number behind a pointer is read in place, so its storage must match:
`&u8` as `&u64`, `&u64` as `&f64` and `&int` as `&i64` are now errors
in V calls, assignments, returns, field values, appends and generic
instances. The sign does not count, so `&char`, `&u8` and `&i8` stay
interchangeable. C calls, `unsafe` blocks and translated C code keep
accepting the number pointees they accepted before; voidptr and
explicit casts are unchanged.
2026-10-25 18:28:33 +03:00
Alexander Medvednikov 267dd7a171 tests: fix five V3 shard fixtures (#31142)
* tests: fix two Linux-only V3 shard fixtures

- fastc spawn_parameter_escape_test: gate.h declared set_state_value
  with `long long`, while the C definition used FastC's `i64`
  (`int64_t`, which is `long` on Linux). Use `int64_t` in both.
- inline_asm_c_lowering_test: the amd64 runtime program took the
  address of a fixed array element outside `unsafe`, which the checker
  rejects. Wrap it in `unsafe {}`.

* tests: print the cc command in the #flag target filter tests

The V3 driver prints the C compiler command only with `-showcc` or
`-v`, so on Linux `compile.output` was empty and the `-ldl` assertion
failed. The negative "does not leak" assertions passed vacuously for
the same reason. Pass `-showcc`, as the Objective-C flags test does.

* tests: pin arm64 in windows_header_macro_names_test so tcc stays TinyCC

On amd64 hosts the driver replaces `-os windows -cc tcc` with MinGW gcc,
so cgen never emitted the over-aligned TinyCC alloca and the test failed
on the Linux V3 shards. No MinGW gcc exists for arm64, so tcc is kept.

* tests: expect uint for sizeof in match_clone_test after #31113
2026-10-25 18:28:20 +03:00
Alexander Medvednikov c651d50bed toml: fix stack overflow on deeply nested inline tables, reject dotted keys extending arrays of tables (#31122)
* toml: parse deeply nested inline tables and arrays in less stack

Since #29578 sum type values are tagged unions stored inline, so every
`ast.Value` local and temporary of the recursive parser functions takes
the size of the largest variant. The frames of `inline_table`, `value`
and `array` grew to 5-7 KB each, and one level of inline table nesting
took 18 KB of stack (tcc, arm64), so the toml CI job overflowed the 8 MB
main thread on `qa-table-inline-nested-1000.toml` of the iarna suite.

The recursive path now writes each value into its destination slot
instead of returning it: `value_into`, `array_into` (which pushes a
placeholder and parses into it) and `assigned_value_into`, called from
`noinline` key parsers. The work around the recursive calls (separators,
comments, errors, insertion, the immutable keys of the enclosing inline
tables, now kept in `outer_immutables`) moves to `noinline` helpers.
One level of inline table nesting now takes 3.9 KB, an array level
2.3 KB (were 18.4 KB and 6.6 KB). `value()` and `array()` keep their
public signatures.

nested_depth_test.v parses 1001 levels of inline tables, arrays and
dotted keys in inline tables, and 500 levels of arrays of inline tables,
each in a spawned thread (8 MB stack on every 64-bit target).

* toml: keep dotted keys and table headers from extending arrays of tables

Since da62dd4bd7, find_in_table_view selects the last element of any
array segment for every caller. Table headers need that for their
leading segments (`[[fruit]]` then `[fruit.physical]`), but two callers
must not descend into an array:

- the dotted keys of key/value pairs, which may only extend tables, so
  `[[tab.arr]]`, `[tab]`, `arr.val1=1` was accepted (toml-test
  invalid/array/extend-defined-aot.toml). The same held for static
  arrays: `a=[{}]` followed by `a.b=1`;
- the last segment of a `[x]` header, so `[[tbl]]` followed by `[tbl]`
  was accepted as a redeclaration (toml-test
  invalid/table/duplicate-key-07.toml).

Add find_key_table_view, which never enters arrays, and use it for the
dotted keys in root tables, table contents, inline tables and array
of tables entries. allocate_in_table now resolves the header's parent
path as before but requires its last segment to be a table.

array_of_tables_extension_test covers both toml-test cases, the static
array and inline table variants, and the valid documents that still
need to descend into arrays of tables.
2026-10-25 18:28:13 +03:00
Alexander Medvednikov 87b0a0ca01 driver: support -dump-modules and -dump-defines (fix vab CI) (#31117)
vab runs `v -dump-modules <file> -dump-defines <file> -dump-c-flags <file>`
and parses the results line by line. V3 broke it in four ways:

* `-dump-defines` was swallowed by the `-d` define prefix branch, and
  `-dump-modules` was ignored, so neither file was written.
* Module names must be the full dotted import paths (`sokol.c`), not the
  last path segment.
* The C flags dump was written after link preparation, which the Android
  builds never reach; it is now written as soon as the flags are known.
* Value-taking flags (`-I`, `-L`, `-isystem`, `-include`, `-framework`)
  are kept on one line with their value, as V 0.5.2 printed them.

Defines are dumped as `system,<os>,true` and `user,<name>,<value>`.
2026-10-25 18:28:05 +03:00
Alexander Medvednikov 21b4171b29 cgen: fix OpenBSD struct stat and addrinfo layouts in the headerless prelude (#31119)
* cgen: fix OpenBSD struct stat field order in the headerless prelude

OpenBSD keeps `__st_birthtim` last in `struct stat`, after `st_gen`.
The headerless prelude put it after `st_ctim`, as on FreeBSD and
NetBSD. Every field from `st_size` on was then read 16 bytes too far:
`st_size` read `st_blksize | st_flags << 32`, which is 16384 for most
files on FFS. The fields up to `st_ctim` were not affected.

Generated compilers therefore got 16384 from `os.stat().size`,
`os.file_size()` and every raw `fstat` size on OpenBSD. That broke the
`tcc-openbsd` CI job twice over:

- Since the parallel source reader (#30874), `v2` reads source files
  with `fstat` + `read` of `st_size` bytes, so every file bigger than
  16 KiB was cut at byte 16384 and `v2 -> v` failed with parse errors
  at that offset (driver.v, os.v, string.v, format.v, ...).
- Before that, `$embed_file` took its length from `os.file_size()`, so
  the C prelude that `./v` embeds was over-read (int128_helpers.h,
  into rodata: `\x00division by zero\x00...`) or cut
  (manual_stdlib_c_headers.h), and the first program `./v` compiled
  failed with `unrecognized character \x00` and `unknown type name`.

Add a test that checks the emitted field order and, with the host C
compiler, the LP64 offsets and size from OpenBSD's <sys/stat.h>.

* cgen: fix OpenBSD addrinfo order and EAI_SYSTEM in headerless prelude

OpenBSD's `struct addrinfo` has `ai_addr` before `ai_canonname`, like
glibc and musl. The headerless prelude grouped OpenBSD with Darwin,
FreeBSD, NetBSD and DragonFly, which put `ai_canonname` first. On
OpenBSD, `net` then copied every resolved address from the
`ai_canonname` slot. That slot is null, because `net` never asks for
AI_CANONNAME, so every successful lookup crashed in memcpy(). The
essential tests of the `tcc-openbsd` job (net/tcp_test.v, the
net.http tests) resolve addresses.

OpenBSD's EAI_* codes are negative, and EAI_SYSTEM is -11, but the
prelude defined 11 for every BSD. getaddrinfo() failures with
EAI_SYSTEM were then reported with gai_strerror() text instead of
the errno message.

Move OpenBSD to the `ai_addr`-first layout, and pass EAI_SYSTEM to
headerless_bsd_constants per platform: -11 on OpenBSD, 11 on NetBSD,
FreeBSD and DragonFly, as in their netdb.h.

Add a test that preprocesses the emitted prelude for each platform
macro and checks both against the platform headers.
2026-10-25 18:27:57 +03:00
Alexander Medvednikov 93fbc4adf5 math.bits: use _BitScanReverse for msvc leading_zeros (fix Cross CI MinGW build) (#31136)
* math.bits: use _BitScanReverse for msvc leading_zeros

`__lzcnt`/`__lzcnt64` need the LZCNT target feature. MinGW GCC 13 declares
them always_inline with `target("lzcnt")`, so compiling `-cc msvc` C output
with it fails ("inlining failed in call to 'always_inline' '__lzcnt64'").
`_BitScanReverse` has no such requirement and is available in MSVC and MinGW.
The zero input is already handled before the intrinsic call.

Declare `_BitScanReverse`/`_BitScanReverse64` in the headerless Windows SDK
prelude and keep them as preserved C functions.

* ci: build v_win.c with -cross in Cross CI

The step links the generated C with MinGW, outside the V driver. Without
`-cross`, the C output relies on native helper bodies (`v_toolcache_*`,
`v_set_unhandled_exception_filter`, `_udiv128`) that the driver compiles
separately, so the MinGW link fails with undefined references. `-cross`
emits a self-contained portable C file.
2026-10-25 18:27:49 +03:00
Alexander Medvednikov 1b3d7de4c7 tools: do not pad the numeric worker args of v test-parser (#31125)
Since #29365 the worker is started with an argument array, not a shell
command, so the padding of `${i:5}` reached the flag parser, which
rejected `    0` as an integer. This broke the parser-silent CI job.
2026-10-25 18:27:42 +03:00
Alexander Medvednikov 8a2276d36b vdoc: remove the unused without_line_comment (fix -W build-tools) (#31111)
#31002 added `without_line_comment` to cmd/tools/vdoc/document, but
only a test calls it; `declaration_shape` already skips `//` comments
itself. The FreeBSD CI job runs `v -N -W -check build-tools`, where the
"unused function" warning is an error, so it has failed on master since
then.

Remove the function and its test assertion.
2026-10-25 18:27:35 +03:00
Alexander Medvednikov f42e6de746 os: allow reserved blocks in the disk_usage self-consistency test (#31110)
On Unix, `disk_usage` takes `available` from `f_bavail`, which leaves
out the blocks reserved for root (`f_bfree - f_bavail`, e.g. on ext4).
Those blocks are neither available nor used, so `available + used`
can be smaller than `total`. The space-paths-linux CI job failed on
`du.total == du.available + du.used` with 154894188544 vs
154877411328 (16 MiB reserved). Assert `<=` instead.
2026-10-25 18:27:27 +03:00
Alexander Medvednikov 4704735bbc vvet: keep $if branches for other platforms (fix Linux CI) (#31118)
`v vet` parsed files without `preserve_comptime_conditionals`, so the
parser dropped `$if` branches that do not match the host. The lines of
multi-line string literals inside those branches were then checked as
code, and space-indented assembly in the `$if macos && arm64` branches
of vlib/v/gen/arm64/native_*_test.v failed `v vet` on Linux.

Preserve the conditionals, like vfmt does, so the vetted AST matches
the source on every host.
2026-10-25 18:27:20 +03:00
Alexander Medvednikov fca9fad345 compiler: deprecate isize and usize in favor of int and uint (#31113) 2026-10-25 14:43:23 +03:00
Alexander Medvednikov 1f4d705322 compiler: extend u32 type spelling dataflow through resolution and lowering (#31132)
* v3: carry source type IDs through resolution and assignment helpers

* v3: compare pointer spellings and index generic receivers by ID

* v3: avoid spelling allocation in declaration and method-value checks
2026-10-25 14:22:32 +03:00
Alexander Medvednikov 4d3a93d7e0 compiler: retain numeric source type IDs through lookup paths (#31043)
* compiler: keep source type queries and cache hits numeric

* compiler: retain alias spelling IDs and compare cache owners by address

* compiler: carry source spelling IDs through remaining lookup paths

* tests: initialize SSA checker references explicitly
2026-10-25 11:45:35 +03:00
Alexander Medvednikov ff75f005fe cgen: fix Windows TinyCC macro names and aligned stack allocation (#31065)
* cgen: escape Windows header macros in V identifiers

* cgen: use TinyCC alloca for aligned stack values

* cgen: keep V identifiers from shadowing TinyCC alloca

* tests: check alloca escaping without changing existing spellings

* tests: compile TinyCC aligned locals with alloca names
2026-10-25 05:14:57 +03:00
Alexander Medvednikov b9dbf3bf65 v: fix remaining macOS SDK and Linux cross-build CI failures (#31103) 2026-10-25 05:13:52 +03:00
Alexander Medvednikov c64467d92a v: fix cached native libc type layouts on macOS (#31056)
* v: distinguish native libc header layouts in cached objects

* v: retain native header context for generic cache hits

* v: cover cached libc layout reuse after pthread ABI fixes
2026-10-25 02:56:55 +03:00
Alexander Medvednikov d1df2de537 v: fix cached builds and local macOS CI regressions (#31040)
* v: fix Darwin ABI and specialization support in cached builds

* v: preserve concrete collection and optional types during lowering

* driver: restore the TinyCC libgc store for macOS comma paths

* tests: honor VTMP and use finite recursive parity fixtures

* tools: fix strict builds, subcommand completion and MCP pagination

* tools: validate wrapped doc summaries and repair documentation examples

* v: preserve callback array types and complete commands after flags
2026-10-23 18:08:27 +03:00
Alexander Medvednikov 2a625df6cf docs: clarify inferred ownership of aggregates (#31007)
* docs: clarify inferred aggregate ownership

* docs: require clone support before copying an inferred owner

* docs: qualify Copy for structs with owning fields
2026-10-23 11:17:49 +03:00
Alexander Medvednikov 4103200a5f checker: accept lowercase C enum initializer constants (#31015)
* checker: allow lowercase C constants in enum initializers

* checker: reject unknown C flag enum bit positions

* checker: preserve V enum selectors in flag initializers

* checker: resolve backed and imported enum flag positions

* checker: evaluate referenced enums in declaration context

* comptime: preserve C-derived enum values symbolically

* fix enum defaults and copied C value provenance

* cgen: preserve forward C enum dependencies

* cgen: preserve symbolic enum integer operator semantics

* docs: preserve C interop paragraph spacing

* checker,cgen: validate and fold symbolic enum calls

* checker: reject partial enum helper evaluation and opaque cast warnings

* checker: evaluate enum helpers in their declaration context

* cgen: use canonical declaration identities for enum initializers
2026-10-23 10:21:29 +03:00
Alexander Medvednikov ebec02a8aa windows: preserve external executable manifests (#31012) 2026-10-23 10:18:49 +03:00
Alexander Medvednikov 9fee04bb68 transform: fix enum alias field string conversion (#31013)
* transform: resolve enum aliases for field string helpers

* transform: inherit custom enum str methods through aliases

* transform: inherit custom str methods through enum alias chains

* transform: preserve inherited alias str in struct fields
2026-10-23 10:18:43 +03:00
Alexander Medvednikov 0975ffd629 transform: avoid double boxing parenthesized optional interfaces (#31014)
* transform: convert parenthesized interface values once

* transform: retain parentheses outside option and interface conversions
2026-10-23 10:18:34 +03:00
Alexander Medvednikov c33398d327 cgen: avoid defining unused C structs (#31017)
* cgen: omit unreferenced C struct layouts

* cgen: retain C layouts referenced by size and offset operators

* cgen: skip fixed array metadata for unused C structs

* cgen: retain C layouts used by fixed-array aliases

* tests: exercise referenced C binding in fixed array folding fixture

* tests: keep C layout opaque in extern declaration fixture

* fix C struct retention for auxiliary declarations

* cgen: omit unused C layouts from interface dispatch

* cgen: omit optional payloads from unused C structs
2026-10-23 10:18:29 +03:00
Alexander Medvednikov 86472f8de1 cgen: omit unreachable cleanup after exiting if branches (#31018) 2026-10-23 10:17:44 +03:00
Alexander Medvednikov 4049be4b5a cgen: use runtime storage for aggregate sum constants (#31019)
* cgen: initialize aggregate sum constants at startup

* cgen: classify canonical sum constants before import resolution
2026-10-23 10:17:38 +03:00
Alexander Medvednikov 3b371cc364 transform: preserve local types in generic field loops (#31020)
* transform: preserve local types in generic field loops

* docs: clarify type identity in generic field loops

* transform: preserve main alias and enum generic arguments
2026-10-23 10:17:32 +03:00
Alexander Medvednikov e47122aebd transform: infer generic arguments before optional destinations (#31021)
* transform: infer generic arguments before optional destinations

* docs: explain generic inference into optional destinations

* transform: retain optional return context for numeric literals
2026-10-23 10:17:26 +03:00
Alexander Medvednikov b3d39a5ab7 transform: restrict join_path lowering to os (#31022)
* transform: restrict join_path lowering to os

* docs: clarify local function names beside library functions

* transform: preserve local join_path bindings and helper reachability
2026-10-23 10:17:19 +03:00