Skip to content

all: fix the macOS CI failures after #29162 - #29180

Merged
medvednikov merged 13 commits into
masterfrom
fix/macos-ci-after-29162
Sep 30, 2026
Merged

medvednikov merged 13 commits into
masterfrom
fix/macos-ci-after-29162

Conversation

@medvednikov

Copy link
Copy Markdown
Member

Follow-up to #29162. After it merged, I ran v run ci/macos_ci.vsh ci --reset again on master (00f243c, macOS 26, Apple clang 21). Several recent commits had broken macOS CI; this PR fixes it. Commits are grouped by cause.

Compiler bugs

  • The closure runtime was added to every program (v3: stop seeding the closure runtime into every program)
    • Import discovery seeds builtin.closure for any selector it cannot prove is a field, since it could be a bound method value.
    • The strconv thousands formatting from strconv: add configurable thousands formatting #28797 has three such selectors the scan could not type: s[..n].len, (a + b).len, and a field read on a match that yields the smartcast subject. Builtin imports strconv, so every program got the closure runtime.
    • Literal-only programs are built without that runtime, yet _vinit still initialized its globals with new_map. As a result, v -os linux examples/hello_world.v and tcc builds of hello_world failed with new_map / map_hash_int_8 undeclared.
    • Fix: the scan now types slices, string concatenation, and those match values. Cgen also skips the closure runtime's globals when closure_init is unused.
  • <-ch! did not propagate (parser: propagate a channel receive with <-ch!)
    • The parser rebuilt <-ch? as a propagation of the receive, but left <-ch! as <-(ch!).
    • So a receive from a closed channel returned a zero value instead of the error the channel was closed with, and channel_opt_propagate_test.v looped forever after its migration to results.
  • sizeof(?T) / sizeof(!T) produced invalid C (cgen: emit the typedef of an option or result named only by sizeof)
    • An option or result type named only by sizeof never got a typedef.
  • The evaluator used the old option layout (eval: use the option and result layouts without error storage)
  • The compatibility compiler could not read builtin (builtin: keep the 128-bit integer methods out of the compatibility compiler)
    • The with_check_option checker fixtures run the frozen V1 compiler against the current vlib, and it does not know u128/i128 (addition: add (u/i)128 primitive types #28877).
    • The methods now live in _d_v3_backend.v files, which V3 always selects for builtin.

Code that still read err after an option (#29151)

  • Fixed: x.encoding.asn1, the veb_fullstack example, and tests in ecdsa, json2, net.http, vbugreport, cmd/v, and the tccbin automation.
  • Master fixed gg (a9424eb) and vpm (vpm: fix compilation after err-less options (#29151) #29178) the same way while this was in progress, so the rebase keeps those versions.
  • Compiler fixtures were changed so each keeps testing what it was written for. The err is int fixture now uses a result, which still carries an error.

Smaller follow-ups

Verification

  • All 22 tasks of v run ci/macos_ci.vsh ci --reset pass on this branch on top of 00f243c. It was resumed after each fix, and self_tests was also run once without fail-fast to collect all failures at once.
  • The branch was then rebased onto master twice.
    • After the first rebase (0e9344a), all 19 test files this branch touches pass, including compiler_errors_test.v, the slow_tests/inout suite, and a gg test.
    • After the second rebase (0bf658c), these pass again:
      • the cross and tcc builds of hello_world;
      • vfmt on every changed file;
      • the tests for cmd/v/launcher_test.v, driver.v, and parser.v, which master changed in between (7067143);
      • compiler_errors_test.v and the new regression tests.
  • Regression tests:
    • These fail or hang on the compiler before this branch: closure_runtime_not_seeded_test.v, channel_opt_propagate_test.v, sizeof_option_result_type_test.v, and byte_identifier_test.v.
    • implicit_import_test.v also covers the new import-scan cases.

Import discovery treats a selector it cannot prove to be a field as a possible
bound method value and seeds `builtin.closure`. The new strconv thousands
formatting has `s[..n].len`, `(a + b).len` and a field read on a `match` that
yields a smartcast subject, none of which the scan could type, so every
program got the closure runtime. For a literal-only program, which is built
without it, `_vinit` then initialized the runtime's globals with `new_map`
while the map runtime was never emitted: `-os linux` and tcc builds of
hello_world failed.

Type slices, string concatenation and such `match` values in the scan, and do
not initialize the closure runtime's globals when `closure_init` is unused.
Removing `byte` left `name in ['u8']`, which `v vet` rejects, so the
all_code_is_formatted CI task failed.
Since #29100 the `set stage_vflags=-cc "!tcc_exe!"` assignment is inside an
if block, so the one-line form the test looked for no longer exists.
Since #29151 removed the error from options, the few `or { panic(err) }`
blocks after option-returning calls and `err.msg()` in the else branch of an
option `if` guard that remained no longer compiled: the ecdsa, json2,
net.http, vbugreport and launcher tests failed.
`<-ch?` was rebuilt as a propagation of the receive, but `<-ch!` stayed
`<-(ch!)`: the `!` applied to the channel, where it does nothing, so a
receive from a closed channel returned a zero value instead of the error.

Options no longer carry an error, so channel_opt_propagate_test.v, which
checks the error a channel is closed with, did not compile. It now receives
with `<-ch!`, which looped forever before this fix, and keeps a case for
`<-ch?`.
The same migration as in "all: stop reading err after options, which no
longer carry one", for the sites the checker reports as an undefined
variable: x.encoding.asn1, the veb_fullstack example, and the tccbin
automation test support.
…mpiler

The with_check_option checker fixtures still run the frozen V1 compiler
against the current vlib, and it knows neither u128 nor i128. Since #28877
it reported their methods in builtin/int.v and builtin/string.v instead of
the fixture diagnostics.

V3 always selects `_d_v3_backend` builtin files, so move the methods there.
Keep what each fixture tests: panic with a message, print `none`, return
`none` for the valid `?bool` counterexample, and make the `err is int`
fixture use a result, which still carries an error. The Option struct that
prohibit_redeclaration_of_builtin_types points at moved in #29151.
Since #29151 an option is `{ bool ok; T value; }`, a result keeps its IError
in a union with the value, and IError is 16 bytes. sizeof in the evaluator
still counted a 48 byte IError in every option, so it disagreed with the
compiled program.
Option and result typedefs are collected before function bodies are
generated, from declarations and calls. `sizeof(?u64)` in a program that
uses `?u64` nowhere else referenced a typedef that was never emitted.
V3 now names an option type `__v_option_T` instead of `Optional_T`, so the
test found neither the V1 nor the V3 spelling of the event mapping.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-30T21:44:24.792431Z 5d0b2f1 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@medvednikov
medvednikov merged commit 33e3def into master Sep 30, 2026
31 of 120 checks passed
@JalonSolov
JalonSolov deleted the fix/macos-ci-after-29162 branch September 30, 2026 23:19
MARCROCK22 added a commit to MARCROCK22/v that referenced this pull request Oct 1, 2026
The conflict, in driver.v: master types a slice in the scan for implicit
imports (vlang#29180) where the experiment passes the whole scan index to
implicit_normalize_type; the slice is taken with the experiment's call. The
new implicit_match_type of master is adapted to the experiment's index the
same way, and notes its read of the fields index (index.read), which a
prepared server's replay of the scan needs to see every key a scan asked.
MARCROCK22 added a commit to MARCROCK22/vls that referenced this pull request Oct 1, 2026
V3 sets `v3_backend` for itself, and since vlang/v#29180 vlib/builtin keeps
what only V3 builds in `*_d_v3_backend.v` files: the methods of i128 and
u128 (`str`, `hex`, `hex_full`, `bin`, `str_base`, `char_str`) among them.
VLS judged the files of a module with no define at all, so the completion
of `n.` for an `i128` or a `u128` lost those methods. The files of a module,
saved or not, are now judged with the defines V3 sets for itself
(v3_own_defines): a `_d_v3_backend` file is part of it and a
`_notd_v3_backend` one is not.
medvednikov added a commit to vlang/vls that referenced this pull request Oct 5, 2026
…e, and generic constraints in the editor (#525)

* V3 answers, persistent compilers, rename, import completion and more

Line info and diagnostics:
- V3 answers hover, definition, signature help, completion and inlay hints
  (v3_line_info.v): through the `query` requests of the diagnostics server of
  the V in use, or in a V3 process of its own where it runs none. It answers
  in a copy of the program kept between requests, where each request writes
  only the files that changed. V1 answers what V3 cannot, such as a file that
  does not parse yet. Completion writes a placeholder name after the dot for
  V3. The lookups that references, rename and document highlights make one
  after another are asked in one check per program.
- Diagnostics come from the diagnostics server of the V in use when it runs
  one (diagnostics_server.v): builtin is parsed once, a newer check stops an
  older one, and each check keeps the same paths.
- A file is checked as part of its program: a module from the program that
  imports it, a module that no program imports as a library (`-shared`), and
  the check answers for every open file of that program.
- Inlay hints come from the compiler (`ih^`), cached per buffer.

Editing:
- Rename (F2) edits every occurrence of the symbol under the cursor, which
  the compiler's go-to-definition confirms, or refuses (rename.v).
- Completion offers the modules a file can import, from the project, the
  installed packages and vlib, and adds the `import` line (module_imports.v).
- Completion offers the builtin functions, `dump` included.
- Hover documents the members V gives types (`from`, `zero`, `has`, `str`...).
- Semantic tokens: an unbraced `$name` is text, as V interpolates only `${}`.

The README tells how to work on code behind a compile-time flag (VFLAGS).

* tests: rename asks V3 first, as VLS does

The rename tests asked V1 alone, while VLS asks V3 first and V1 only what
V3 does not answer. Their test app now does the same when the V in use has
a V3 that answers `-line-info`, and ends the V3 servers it started.

Two of them need an answer V1 does not give: where a method reached through
an embedded struct, or a name inside a generic function that another file
calls, is declared. Without such a V3 they are skipped.

Also writes a test constant with single quotes, as vfmt wants.

* rename: refuse interface members and the names they share

V needs no declaration to implement an interface, so the types that
implement one must keep the names of its members, and a rename cannot see
which types those are. With V3 answering where an interface method is
declared, a rename of `area` changed the interface and its calls but not
`Circle.area`, and the program no longer compiled. Before, it was refused
only because nothing answered there.

A rename of a member of an interface of the project, or of a method or a
field with the name of one, or of `msg` and `code`, the methods of
`IError`, is now refused, as the other renames that could break the
program are.

Also tests a field of an embedded struct reached through the struct that
embeds it, declared in another file: from its declaration a rename left
`user.id` behind while V3 did not follow the embedding.

* V3: ask about a test file as a program of its own

V builds a test file with the files of its module, as a program of its
own, and the program of the directory, `.`, leaves it out: V3 had no answer
for a position in a `_test.v` file, and a rename could not verify its
occurrences there. The questions about a test file are now asked with that
file as the program, each in its own check (and its own diagnostics server);
the other questions keep asking `.` together.

* rename: ask nothing prepareRename asked, keep the program's server

A rename asked V3 again where the name at the cursor is declared, right
after prepareRename had asked it, with the files as they were: about a
second of each rename. What a rename finds out is now kept for the next
one while no file changes; a question that got no answer is asked again,
as the compiler may have failed for a moment.

The server of a test file, a program of its own, no longer pushes out the
server of the program of the directory, `.`, which every other question
goes to. And a server that does not end when told to, as one whose child
hangs, is killed after a second: waiting for it froze VLS.

On the code of VLS, the three renames measured take 1.3 s, 2.8 s and
6.1 s, from 2.5 s, 3.9 s and 7.5 s.

* V3: write a buffer into the copy only, never through its links

The copy V3 is asked about links the project's files it was not asked to
write: by a symbolic link to the file, by a hard link to a file of an
imported module, or by a symbolic link to a whole directory. A file opened
after the copy was built was written through such a link: its buffer, not
saved yet, or a completion's placeholder, overwrote the file in the
project. Only a symbolic link to the file itself was replaced.

A write now makes the directories above the file the copy's own (a linked
directory becomes one whose entries link the project's), removes the
file's link, and writes a new file. An empty buffer is written too: a file
the copy never wrote no longer passes for one that already holds it.

* V3: a copy of its own for each editor and each program

The files the persistent compilers check lived in one directory for the
whole VLS process. Over TCP, VLS serves each client with an App of its
own, with its own buffers, servers and record of what it wrote into a
copy: two clients editing one project shared the copy of it, so one could
rebuild or overwrite what the other was checking, and the other, finding
its own buffer recorded as written, asked about the first one's text.
Stopping the servers of either client removed the copies of all of them.
Two programs of one v.mod project shared a copy in the same way within
one App.

Each pool of servers now keeps its files in a directory of its own, and
removes only that one when it stops; a program's questions go to a copy
of that program alone. A session that ends without a shutdown stops its
compilers and removes its files as well.

* V3: take again a module file replaced on disk

The copy V3 is asked about holds the files of the modules that the program
imports from the project by hard links, which show a file written in place
but not one replaced by another: a checkout does that, and so does an
editor that saves by renaming a new file over the old one. No client needs
to say so: the copy went on holding the old file, and what V3 answered
about that module came from it.

Before each question the copy now compares each file it holds by a hard
link, or as a copy where no link could be made, with the project's (inode,
size and time of the last change), takes again one that changed, and
removes one that is gone.

* hover: show a sum type declaration written over several lines

A hover shows the declaration as the source writes it, and of one without a
body it took the first line only: `pub type Number = int`, followed in the
source by `| i8`, `| i16` and more on lines of their own, as vfmt writes a
long sum type, showed `int` as its only variant. The lines after such a
declaration that start with `|` are now part of it: the variants of a sum
type, or the operands of an `|` written over several lines.

* hover: a function shows its declaration where it is declared and used

A hover on the name of a function, a method or a method of an interface
showed its documentation alone where it is declared. Where it is used it
showed the compiler's re-print of its signature, without its receiver, its
type parameters or the type of a static method, or only a documentation
found for its name, which was often another declaration's: the type `map`
for the method `map` of an array, the `first` of arrays for a function named
`first`, the `to_upper` of a rune for that of a string.

VLS now asks V3 in one question where the name is declared and what it says
of it. A function, a method or a method of an interface shows its
declaration as the source writes it, with the documentation written above
it, the same at its declaration and at each use: `fn (b Box[T]) label()
string`, or `pub fn (a array) map(callback fn (voidptr) voidptr) array` with
builtin's documentation of it. Anything else keeps what the compiler says of
it, with the documentation of its own declaration; a local or a parameter
gets none. Without V3, the index says where a function is declared.

On the way:
- the index finds a generic function by its name: it named its symbol
  `first[T]`, which no use matches;
- a declaration without a body, as builtin declares the methods of arrays,
  ends with its line;
- a member of a value whose declaration is not found gets no documentation
  found for its name alone, and the methods of arrays and maps are looked up
  on builtin's `array` and `map`;
- a local shows at its declaration what it shows at its uses, and a method
  named without a call, `g := u.greet`, is a function value, `fn () string`.

* hover: a local is never its statement nor another declaration's documentation

A local that nothing gave a type showed the statement that declares it, as
`lengths := xs.map(it.name.len)`, or the documentation of another declaration
of its name: a local named `value` showed "for cgen", the documentation of the
method `value` of builtin's `DenseArray`.

Where V3 says a name is a local or a parameter and knows no type for it, the
hover is empty: nothing else can tell what it holds. The declaration of a local
is never shown as its hover, and a local gets no documentation found for its
name. A name used alone is never a method either: the search of the
documentation by name, in a file and in the index, skips methods, which are
documented where the type of their value is known.

* tests: rename a local passed to a method named like an array one

A local `a` passed to a user's `s.sort(a)` is that local, not the `a` of an
array's comparator: the rename of `a := 7` must change that use, and leave the
`a` of `sorted.sort(a < b)` alone. It asks V3 where each occurrence is
declared, so it needs a V3 that tells them apart.

* hover: show the `Example:` lines of a doc comment as V code

vlib documents most of its examples as `// Example: <code>`, which `v doc` shows as V code, while the hover showed them as text. Consecutive ones now share a ```v block under `Example:` or `Examples:`, and the lines of a ``` block keep their indentation.

* diagnostics: a question does not wait for the check of another server

The pool held its lock for the whole request, so a hover or a completion waited for a check of the program running on another server. Each server now has a lock of its own, and the pool's covers only its map; a server in use is never stopped: the pool drops it, and the last request to leave stops it.

* diagnostics: a check starts as soon as a change arrives

A check waited 25 ms after each change and the worker slept 5 ms before looking for it: on a small program that was a quarter of the time to its diagnostics. A newer change already stops the check that runs, and a question no longer waits for a check, so the check starts at once. The tests that look at the jobs a change leaves pause the scheduler, which a check started at once would otherwise empty.

* requests: one that asks no compiler does not wait for one that does

After a change an editor asks at once for the semantic tokens and for the highlights, the hover or the inlay hints at the cursor. The loop answered them in order, so the tokens, which come from the text alone, waited for a question to the compiler, which can take a whole check: 100 ms on a small program, 490 ms on a large one. The messages are now read on a thread of their own, and a request that never asks the compiler goes before those that may, among the requests that arrived together; no request moves past a notification or any other request.

* diagnostics: the servers of the diagnostics prepare builtin once

A V3 diagnostics server started with V_DIAGNOSTICS_PREPARE parses and
collects builtin and the modules it imports once, before its first check,
and each check continues from there. The pool of the diagnostics asks for it:
its servers only check. The pool of the questions does not.

* questions: the servers of the questions prepare builtin too

The server that answers hover, highlights and inlay hints re-checks the
program after each edit, as the one of the diagnostics does: it now prepares
builtin and the modules it imports once as well (V_DIAGNOSTICS_PREPARE). Its
answers to 22,000 questions over eight projects are those of an unprepared
server.

* diagnostics: a check and the questions about a program share its check

Each change of a program was checked twice: by the server of the
diagnostics, in a copy of the program rebuilt for each check, and by the
server of the questions (highlights, inlay hints, a hover), in a copy of its
own. The questions now go to the servers of the diagnostics, which run with
V_DIAGNOSTICS_SHARED, and the check writes into the copy the questions use: a
request holds the lock of the copy while it writes what the editor holds and
asks about it. The child of the server that checked a version of the program
answers the check and the questions about it, whichever came first: one
check per change. The questions drop `-w`, which changes no answer of V3, so
that both have one command line, and one server.

* diagnostics: publish the errors a check finds before its slow end

The servers of the diagnostics run with V_DIAGNOSTICS_PARTIAL: a check whose
end is slow (the instances of generic functions above all) sends the errors
it found first, ended by a `partial` line. The client publishes them at once,
while the job is current, and the whole answer replaces them. The errors of
a check are read by split_check_errors now, for both answers. The greeting of
a server is read with its newline, which leaked into the first answer.

* hover: ask the compiler first about a value that a `$if`, `is` or `match` can narrow

VLS answered the hover of a local or a parameter from its index, with the
type its declaration writes: `a A` for `a A` in the branch of
`$if A is f64 {`, and `s Shape` in the branch of `if s is Circle {`, and
never asked the compiler, which knows what the value is there.

When the type of the binding names a type parameter of the generic function
around it, or is a sum type or an interface, the compiler answers first,
`a f64`; the index answers when the compiler cannot, and alone for any other
type, as before.

* index: a sum type written on several lines is a sum type

vfmt writes a long sum type with each type on a line of its own:
`type Shape2 = Circle`, and `| Square` below it. type_declaration read its
first line only and took `Shape2` for an alias of `Circle`: completion
after `s.` offered the fields of `Circle`, which `s` may not have, and the
hover of `s` in the branch of `if s is Circle {` did not ask the compiler,
which knows it is a `Circle` there.

The lines that go on with `|` are read too, past comments between them.

* rename: a type parameter with a constraint is a type parameter

generic_list_names read `T Named` in `fn take[T Named](x T)` as no name at all,
so where the compiler does not answer, a `T` of that function counted as the
type `T` of the module, and a rename of that type went into the function.
It takes the first word of each part now; binding_type_narrows reads the type
parameters of a header with it too.

The rename test needs the compiler that declares a type parameter in its
list (vlang v experiment), which answers first.

* rename: refuse a new name that changes what the program does

A rename edited every occurrence of the symbol and nothing else, but did not
look at the new name: a local renamed to the name of another local, of a
parameter or of a function called there broke the program, and one renamed to
the name of a constant made `if total > limit` compare the local with itself,
with only a warning from V. A type parameter renamed to a name of several
letters broke it too.

The rename now renames in the copy of the program that V answers questions in,
checks it, and asks again where each occurrence of the old and the new name
leads (rename_conflicts.v). It is refused, saying why, when the check reports
an error or a warning that it did not before, or when an occurrence would name
another declaration than it did, or one that the rename makes. Where the rename
already knows where an occurrence led, it does not ask again.

`__global`, `__offsetof`, `_likely_` and `_unlikely_` are keywords too.

* diagnostics: show a redefinition on each declaration it names

V says without a position that a function is declared twice, `builder error:
redefinition of function `f``, and then where each declaration is, as
`file:line:col: conflicting declaration: ...`. VLS placed the first line on the
first declaration it found and read none of the others: the second
declaration, often the one just written, showed no error.

Each `conflicting declaration` line is now that error at its place, and the
line without a position is not placed again on its own. The check of a rename
reads a check's output the same way.

* all: run v fmt -w

CI checks `v fmt -verify vls/` with the latest V, and 17 files failed it;
the same 17 fail on master. This runs `v fmt -w` on them: alignment, line
wrapping and quote style only, no change to the code.

* hover: a local whose value the index cannot type asks the compiler

`pairs := [Pair{ left: 1, right: 2 }]` showed `pairs []Pair` and
`right := Pair{...}.right` showed `right Pair`: the index holds a generic
struct as `Pair[T]`, reads a literal that infers its arguments as the bare
`Pair`, and a field of it as its declared `T`. A type that names a type the
index does not know now goes to the compiler, which writes `[]Pair[int]` and
`int`. The index also reads a value written over several lines to its end:
`r := Point{ ... }.x` was a `Point` because only the first line was typed,
on the declaration and where it is used.

* builtins: recover, which V added to stop a panic from a defer block

vlang/v#29134 added `pub fn recover() ?string` to vlib/builtin. As one of
v_builtins it completes with that signature and inserts `recover()`, it is
colored as a builtin function, and a rename refuses it as a new name. Its
hover, definition, signature and the type of `msg` in
`if msg := recover() {` already come from the compiler.

* hover: a struct literal that a value goes on from is not the type of the value

`head := Host{}.first_of(values)` hovered as `head Host`: where the type of
the value could not be told, the fallback that reads a leading literal as a
constructor took `Host{}` for the whole value. A literal followed by a member
or a call is no constructor of it: the index answers nothing, and the
compiler answers.

* builtins: the types of V now: i128 and u128, and no byte

V's #28877 added `i128` and `u128`, and #29141 removed `byte`, which is a
name like any other now. `i128` and `u128` complete as builtin types, are
colored as types, list the methods vlib/builtin declares for them (`str`,
`hex`...), and are part of V for a rename; a variable named `byte` renames
like any other, and `[]byte` no longer stands for `[]u8`.

* rename: refuse a new name that changes what the program does

A rename edited every occurrence of the symbol and nothing else, without
looking at the new name: a function renamed to the name of another one, a
local to the name of another local, or a function to the name of a parameter
that a call of it would then reach, broke the program or changed what it does
without any error.

The rename now writes the renamed files into the copy of the program that V
answers questions in, checks it, and asks again where each occurrence of the
old and the new name leads (rename_conflicts.v). It is refused, saying why,
when the check reports an error or a warning that it did not before, or when
an occurrence would name another declaration than it did.

`__global`, `__offsetof`, `_likely_` and `_unlikely_` are keywords too.

* rename: rename the variants of the other platforms too

A function declared in a file of each platform, as `platform_name` in
`name_linux.c.v` and `name_windows.c.v`, was renamed only where the build of
this platform sees it: V resolves nothing in the file of another platform, so
its declaration was skipped as another symbol of the same name, and a use there
made the rename fail.

What V does not resolve is now part of the rename when it is in code that V
builds only for some platforms, architectures, backends or defines (a file with
such a suffix, or a `$if` or `$else` branch) and in the module of the target: a
declaration of the same kind, with the same receiver for a method, and a use of
the name that is not a member, a name of another module or a local of its
function. Anything else is refused as before, never skipped.

* inlay hints: without file watchers, a change on disk renews them

The cache of the hints of a document took its stamp from the open documents
and the generation of the project, which only a watched file notification
moves: a client without file watchers kept the old hints when a file that is
not open changed on disk (a checkout, another editor), until an open document
changed. Without watchers the stamp now holds what the .v files of the project
are on disk, their sizes and modification times.

* diagnostics: a read of a server that keeps writing ends in time

read_until and read_until_or_cancel went back to the top of their loop after a
chunk of output, past the deadline and the question whether to cancel: a child
that kept writing without the marker was never timed out or cancelled. They
also searched all they had read for the marker after each chunk. Now the
deadline and the question come after every read, chunk or not, and the marker
is searched only from where it can still start.

* index: the files of a module are the ones V3 builds

V3 sets `v3_backend` for itself, and since vlang/v#29180 vlib/builtin keeps
what only V3 builds in `*_d_v3_backend.v` files: the methods of i128 and
u128 (`str`, `hex`, `hex_full`, `bin`, `str_base`, `char_str`) among them.
VLS judged the files of a module with no define at all, so the completion
of `n.` for an `i128` or a `u128` lost those methods. The files of a module,
saved or not, are now judged with the defines V3 sets for itself
(v3_own_defines): a `_d_v3_backend` file is part of it and a
`_notd_v3_backend` one is not.

* tests: the vlib module offered for JSON is json2

vlang/v#29112 removed the cJSON based `json` module, which the test of the
modules of vlib expected (deprecated); `json2` replaces it and is not
deprecated as a module.

* all: run v fmt -w

The list of the builtin types of V (`i128` and `u128` in it) is wrapped as the
`v fmt` of vlang/v master wraps it; no change to the code.

* Refuse unvalidated renames and match platform members by owning type

* Bound disk traversal when refreshing inlay hints without watchers

* Avoid filesystem-root hint scans and bound non-source traversal

* Probe compiler support before testing constrained generic renames

* fix: retire compiler servers and join client readers on shutdown

* Report a closed compiler pool as unavailable rename validation

* Store the traversal counter in an explicit mutable budget

* Detect same-size disk edits when refreshing cached inlay hints

* Accept compiler builder duplicate-function diagnostics in rename tests

* Reject capture in unresolved inactive rename uses

* fix: join compiler workers and reap them safely on exit

* Keep diagnostics reader and cache copies compatible with V1

* fix: validate compiler child PIDs before cancellation

* Mark the joined reader borrow as safe for V1 stack checks

---------

Co-authored-by: Alexander Medvednikov <alexander@medvednikov.com>
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