Skip to content

fix: recognize a launcher that cannot reach the V1 compatibility compiler - #529

Open
metif12 wants to merge 2 commits into
vlang:masterfrom
metif12:fix/recognize-missing-compat-compiler
Open

metif12 wants to merge 2 commits into
vlang:masterfrom
metif12:fix/recognize-missing-compat-compiler

Conversation

@metif12

@metif12 metif12 commented Oct 3, 2026 •

Copy link
Copy Markdown

Problem

Hover, completion, signature help, and go to definition all go through the V
compiler:

return ['-w', '-check', '-nocolor', '-vls-mode', '-line-info', '${file_to_check}:${line_info}',
	compile_target]

-vls-mode and -line-info are served by V's V1 compatibility compiler. When
that compiler is missing, the V launcher refuses and exits without compiling
anything:

`-vls-mode` requires the compatibility compiler, but no usable V 0.5.2 fallback was
found and make is unavailable. Install make, then run `make v1` in `C:\Users\me\v`.

VLS did not recognise this refusal.

compiler_rejects_line_info only matches a whole line reading
unknown option `-line-info` , and compiler_refused_and_stopped requires
every non-empty line to start with unknown option ` . The message above is
neither, so both return false, line_info_mode stays .direct, and VLS goes on
spawning v once per request for an answer that can never arrive. Every one of
those lookups resolves to an empty result.

The result for the user is a VLS that starts, highlights code, and otherwise
does nothing — completion, hover, signature help, and go to definition all stay
empty — with no message explaining why. That is the shape of
#495 ("V Language Server is starting"
and nothing else; popup functionality never appears).

This is most likely to be hit on Windows, where the V1 fallback is a separate
build step rather than something make produces automatically.

Fix

Recognise the refusal, retire the lookups, and say what to do about it.

compiler_lacks_compatibility_compiler matches each refusal ensure_v1_fallback
can produce in the launcher:

launcher output meaning
`-vls-mode` requires the compatibility compiler, but no usable V x.y.z fallback was found and make is unavailable make is not installed
`-vls-mode` requires the compatibility compiler, but the V source tree could not be found no V checkout next to v
`-old-compiler` was requested, but ... the selector could not be honoured
`make v1` failed with exit code N the automatic build failed
`make v1` completed without installing a usable V x.y.z fallback the automatic build produced nothing usable

It then joins the existing dead-end branch in run_v_line_info:

if (compiler_rejects_line_info(x.output) && compiler_refused_and_stopped(x.output))
		|| compiler_lacks_compatibility_compiler(x.output) {
	log('no compiler serves -line-info; falling back to the index')
	app.line_info_mode = .missing
	app.report_missing_compatibility_compiler()
	cleanup_compilation_temp(temp_project_dir, singlefile_tmppath)
	return app.line_info_unavailable_result(method, path, line_info)
}

so the lookups stop spawning a process and are answered from VLS's own index, and
the user gets one window/showMessage naming the repair.

Once per session, with no flag

An earlier draft of this PR added an App field to suppress repeats. It is
unnecessary: the caller sets line_info_mode to .missing first, and from then
on run_v_line_info returns from its early .missing check without reaching this
point. So the notice is structurally sent at most once, and no new struct field —
and no re-alignment of the whole App comment column — is needed.

The case this must not break

A launcher that can build the fallback itself announces that and then answers:

`-vls-mode` requires the compatibility compiler, but no usable V 0.5.2 fallback was
found; running `make v1` now...
{"contents":{"kind":"markdown","value":"fn f()"}}

Retiring the lookups here would cost the session every compiler-backed hover,
signature, and receiver definition — exactly what the existing
compiler_refused_and_stopped comment warns about for the analogous
"recovering launcher". running ``make v1`` now therefore returns false
immediately. My first draft got this wrong and its own test caught it.

Tests

  • test_compiler_lacks_compatibility_compiler_detects_every_launcher_refusal —
    all five refusal forms verbatim, plus the recovering launcher, an ordinary
    diagnostic, a normal payload, and empty output. Platform-independent.
  • test_run_v_line_info_retires_lookups_when_the_compatibility_compiler_is_missing
    — end to end against a stub launcher: mode becomes .missing. Skips on
    Windows, like the two sibling launcher tests.
  • test_report_missing_compatibility_compiler_names_the_repair — the message is
    a window/showMessage that names make v1. Platform-independent.
  • test_a_retired_lookup_never_reports_the_missing_compiler_again — with
    VLS_V_COMMAND pointing at a compiler that cannot be spawned, a retired lookup
    still answers from the index and sends nothing, which is the structural
    once-per-session guarantee. Platform-independent.

Validation

V 0137eb5 (the vlang/v revision CI builds from), Windows.

interop_test.v: OK.

All six of these PRs merged onto master in order, then run as CI would:

v fmt -verify .   ->  exit 0
OK    compilation_test.v     OK    index_test.v      OK    interop_test.v
OK    integration_test.v     OK    handlers_test.v   OK    lsp_test.v
Summary for all V _test.v files: 6 passed, 6 total.

The notice also really does fire against a real compiler, captured from a full
suite run with v1_fallback.exe removed — the #495 condition:

{"jsonrpc":"2.0","method":"window/showMessage","params":{"type":2,"message":"vls: the V
compiler on PATH cannot serve completion, hover, signature help, or go to definition,
because its V1 compatibility compiler is missing. Install `make`, then run `make v1`
in your V source directory, or point `v.vls.command` at a V that has it. Diagnostics
and formatting are unaffected."}}

main.v is untouched, so this branch merges cleanly after
#528.

@metif12

metif12 commented Oct 3, 2026

Copy link
Copy Markdown
Author

Verification update

I got a V1 compatibility compiler working locally afterwards, so this is now
verified against a real compiler rather than only against the stub.

With a working v1_fallback.exe, all four of these PRs together are green on
Windows:

OK    [1/6] compilation_test.v
OK    [2/6] index_test.v
OK    [3/6] interop_test.v
OK    [4/6] integration_test.v
OK    [5/6] handlers_test.v
OK    [6/6] lsp_test.v
Summary for all V _test.v files: 6 passed, 6 total.

That also settles the three handlers_test.v failures I flagged as unverified
above — test_conditional_methods_request_receiver_completion_fallback,
test_handle_rename_returns_complete_workspace_edit and
test_operator_overloads_are_not_offered_as_completions all pass once a
compatibility compiler is present. They were failing purely because this machine
had no v1_fallback.exe.

The #495 condition, reproduced on Windows

To exercise this fix rather than just the unit tests, I removed the fallback
again and ran the suite. That is exactly the state #495 describes — the V
launcher refuses:

`-vls-mode` requires the compatibility compiler, but no usable V 0.5.2 fallback was
found and make is unavailable. Install make, then run `make v1` in `C:\Users\me\v`.

Before this PR that produced silence. After it, handlers_test.v emits the notice
once, from a real run_v_line_info call against a real compiler:

{"jsonrpc":"2.0","method":"window/showMessage","params":{"type":2,"message":"vls: the V
compiler on PATH cannot serve completion, hover, signature help, or go to definition,
because its V1 compatibility compiler is missing. Install `make`, then run `make v1`
in your V source directory, or point `v.vls.command` at a V that has it. Diagnostics
and formatting are unaffected."}}

and line_info_mode retires to .missing, so the lookups stop respawning a
process per keystroke.

The three compiler-dependent handlers_test.v tests fail in that state, which is
correct — they assert real compiler output, and there is none. They pass again
once the fallback is restored.

…iler

Hover, completion, signature help, and go to definition all go through
`v -vls-mode -line-info`, which the V launcher routes to the V1
compatibility compiler. When that compiler is missing, the launcher
refuses with a single line and exits:

    `-vls-mode` requires the compatibility compiler, but no usable V
    0.5.2 fallback was found and make is unavailable. Install make,
    then run `make v1` in `C:\Users\me\v`.

That refusal is not an "unknown option" line, so neither
`compiler_rejects_line_info` nor `compiler_refused_and_stopped`
recognized it. `line_info_mode` stayed `.direct`, so VLS kept spawning
the compiler once per request for an answer that can never arrive, and
every one of those lookups resolved to empty with nothing said about why.

Recognize the refusal, retire the lookups as `.missing` so they are
answered from VLS's own index instead of paying a process launch each,
and tell the user what to install. A launcher that can build the
fallback itself announces "running `make v1` now" and then answers, so
that form is explicitly not a dead end.

The notice needs no "already warned" flag: the caller sets
`line_info_mode` to `.missing` first, and from then on `run_v_line_info`
returns from its early `.missing` check without reaching this point, so
it is sent at most once per session.
@metif12
metif12 force-pushed the fix/recognize-missing-compat-compiler branch from f2fe59d to 289eb5a Compare October 3, 2026 11:46
medvednikov added a commit to vlang/v that referenced this pull request Oct 3, 2026
* cmd/v: let the V1 fallback find MSYS2's make on Windows

`-vls-mode` is answered by the V 0.5.2 compatibility compiler, so `v
-check -vls-mode ...` first has to have that fallback. When it is missing,
`ensure_v1_fallback` builds it with `make v1`, and `find_make` only ever looked
for `make` and `gmake`.

A stock Windows install of V has neither on PATH: the supported Windows build
goes through `makev.bat`, and a machine that installs MSYS2 gets GNU make under
its Windows name, `mingw32-make`. Both `v1:` targets are POSIX shell recipes, so
MSYS2 is the toolchain that can actually run them. The result on such a host was
a hard refusal with empty stdout, which the VLS reports as `failed to parse
json`: no completion, no hover, no diagnostics. That is what
vlang/vscode-vlang#543 reports from Windows.

`find_make` now also looks for `mingw32-make`, on Windows only. On a Unix host
that name is a Windows cross-make, and using it here would cross-compile the
compatibility compiler instead of running it.

The "make is unavailable" diagnostic now says where to get make on this
platform, because "install make" is not actionable advice for a Windows user.
vlang/vls#529 asserts the previous wording and needs the matching update.

Verified: `cmd/v/find_make_test.v` (4 tests, including that `mingw32-make` is
found on Windows and deliberately not consulted elsewhere) and
`cmd/v/v3_fallback_diagnostics_test.v` (8 tests). The fallback build itself was
not run here, so the fix is covered by unit tests and not by an end-to-end
`mingw32-make v1` build.

* cmd/v: clarify MSYS2 make and shell setup

---------

Co-authored-by: office <office@local>
Co-authored-by: Alexander Medvednikov <alexander@medvednikov.com>
vlang/v#29369 (merged as 76d88b9) rewrites the tail of the launcher's refusal:
the sentence after "make is unavailable" is now a platform-specific hint, and
the comma became a period. On Windows the clause reads

    On Windows, install GNU make in MSYS2 (`make` or `mingw32-make`) and put
    its tools, including `sh`, on PATH.

and elsewhere it is still "Install make.".

`compiler_lacks_compatibility_compiler` keys on "requires the compatibility
compiler", which both spellings contain, so detection is unaffected. This test
pinned the old wording verbatim, so it now asserts both: green before the
compiler change and after it, and the coupling is written down instead of being
rediscovered the next time the wording shifts.

Validated against V 0.5.2 76d88b9, the merged compiler: the Windows sample above
is its output verbatim. `interop_test.v` passes; the module suite reports the
same 3 failures with and without this change - `index_test.v`, `handlers_test.v`
and `integration_test.v`, none of them in this file. `integration_test.v` fails
on an empty completion list, which is the symptom of the missing V1 fallback
this refusal describes, and is what vlang/v#29369 and vlang/vscode-vlang#543 are
about.
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