Summary
After a uloop compile ends with COMPILE_WAIT_TIMEOUT, the next compile in the same project reattaches to that compile. The compile that uloop hot-reload runs as its fallback, and the implicit compile of uloop run-tests, go through the same reattach. If Unity still holds the earlier compile's stored result, they return that result without sending a compile, and report it as a compile that ran in the current command.
Where it happens
Found by reading the code; not reproduced yet.
hotReloadFallbackCompileDefault (cli/project-runner/internal/projectrunner/hot_reload_compile_fallback.go) and runTestsImplicitCompileDefault (run_tests_implicit_compile.go) both call runCompileWithDomainReloadWaitResultWithDeps with empty params.
- That function calls
tryAttachToPendingCompile first (run.go). When the pending record from the earlier timeout exists and get-compile-status reports HasResult, returnAttachedStoredCompileResult returns the stored result and clears the record, and no compile request is sent. Only ForceRecompile skips this, and neither caller passes it.
- The pause-point release recovery already avoids the reattach by calling
runFreshCompileWithDomainReloadWaitWithDeps directly.
Why it matters
- Hot reload: the fallback note describes the stored result as a compile that ran in this command. On success it says "every edit is compiled in, and the domain reload discarded the active hot-reload patches". The stored result belongs to a compile that started before the edits this hot reload left unapplied, and this command sent no compile, so it caused no domain reload and the patches stay active. On failure,
Compile.Errors shows the earlier compile's errors.
- run-tests: the tests run as if the latest edits were compiled, and the compile warning passed to the run comes from the earlier compile.
- The window lasts while Unity keeps the stored result (20 minutes) and the pending record exists. The first command that reattaches clears the record.
Expected
The hot-reload fallback and the run-tests implicit compile report a compile of the current sources, and a stored result of an earlier compile does not stand in for it. For example, they could start a fresh compile as the pause-point recovery does, or discard the stored result as --force-recompile does. When the earlier compile is still running, waiting for it first is fine, but its result alone does not show that later edits are compiled in.
Related: the reattach probe decides a compile is gone from one sample
Also in tryAttachToPendingCompile (compile_attach.go): when the probe's first successful status query reports Ready without HasResult, it clears the pending record and starts a new compile. The attach wait in the same file needs three such samples in a row (compileAttachMissingResultStreak), because "a single Ready&&!HasResult sample can race the completion→store window". A probe that lands in that window drops the record of a compile whose result was about to be stored. No failure from this has been observed.
Environment
Summary
After a
uloop compileends withCOMPILE_WAIT_TIMEOUT, the next compile in the same project reattaches to that compile. The compile thatuloop hot-reloadruns as its fallback, and the implicit compile ofuloop run-tests, go through the same reattach. If Unity still holds the earlier compile's stored result, they return that result without sending a compile, and report it as a compile that ran in the current command.Where it happens
Found by reading the code; not reproduced yet.
hotReloadFallbackCompileDefault(cli/project-runner/internal/projectrunner/hot_reload_compile_fallback.go) andrunTestsImplicitCompileDefault(run_tests_implicit_compile.go) both callrunCompileWithDomainReloadWaitResultWithDepswith empty params.tryAttachToPendingCompilefirst (run.go). When the pending record from the earlier timeout exists andget-compile-statusreportsHasResult,returnAttachedStoredCompileResultreturns the stored result and clears the record, and no compile request is sent. OnlyForceRecompileskips this, and neither caller passes it.runFreshCompileWithDomainReloadWaitWithDepsdirectly.Why it matters
Compile.Errorsshows the earlier compile's errors.Expected
The hot-reload fallback and the run-tests implicit compile report a compile of the current sources, and a stored result of an earlier compile does not stand in for it. For example, they could start a fresh compile as the pause-point recovery does, or discard the stored result as
--force-recompiledoes. When the earlier compile is still running, waiting for it first is fine, but its result alone does not show that later edits are compiled in.Related: the reattach probe decides a compile is gone from one sample
Also in
tryAttachToPendingCompile(compile_attach.go): when the probe's first successful status query reportsReadywithoutHasResult, it clears the pending record and starts a new compile. The attach wait in the same file needs three such samples in a row (compileAttachMissingResultStreak), because "a single Ready&&!HasResult sample can race the completion→store window". A probe that lands in that window drops the record of a compile whose result was about to be stored. No failure from this has been observed.Environment