driver: ignore wrong-suffix files as named sources

This commit is contained in:
2026-08-23 03:18:19 +09:00
parent 59fc76964c
commit f6fabfc6ac
6 changed files with 1325 additions and 28 deletions

View File

@@ -10511,6 +10511,150 @@ serialized representation changes: build workdir format remains `18`, test
workdir format remains `19`, semantic storage format remains `3`, and no cache
or result record is added.
### 11.54 Implemented wrong-suffix physical-source exclusion
One public operand is a local named source only when its exact requested
spelling ends `.ww` and the command's existing file-kind rule admits it. An
existing non-directory object with any other suffix does not become source and
does not preempt the same operand's ordinary dotted lookup. Thus a physical
`foo.bar` is ignored as a source while request `foo.bar` continues to
`foo/bar.ww` or `foo/bar/`. An existing directory, including a symlink whose
target is a directory, remains a stat-first directory package regardless of
suffix.
#### Pinned authority and applicability
- **behavior directly implemented or asserted by pinned Go** — official Go
1.26.5 commit `c19862e5f8415b4f24b189d065ed739517c548ba` enters named-file
mode in `cmd/go/internal/load/pkg.go:28872932`, especially 29032918,
only when a requested spelling ends `.go`, `Stat` succeeds, and the result
is not a directory. `GoFilesPackage` independently rejects every non-`.go`
member at `pkg.go:32443318` before constructing its synthetic package.
Build and test call that loader at
`cmd/go/internal/work/build.go:459477` and
`cmd/go/internal/test/test.go:684719`. Run independently consumes only
leading `.go` spellings at `cmd/go/internal/run/run.go:73145`, especially
96123.
- **behavior directly implemented or asserted by pinned Go** — official
`cmd/go/testdata/script/list_test_non_go_files.txt:113` directly tests a
mixed named-file list: after a `.go` member selects named-file mode,
`GoFilesPackage` rejects the non-`.go` member. Official `run_hello.txt:110`
and `run_set_executable_name.txt:417` anchor ordinary named-file and package
run fronts. None directly tests one existing wrong-suffix object colliding
with a package request, and the official tree contains no such singular
build/run/test script.
- **behavior derived from the pinned implementation** — the singular
collision result follows from the pinned suffix-before-`Stat` build/test
gate and run's suffix-only scan. WW's honest local adaptation applies the
same positive spelling decision to `.ww` named sources before its existing
dotted search. It requires no module, manifest, registry, network lookup,
generalized import syntax, cache, database, CAS, lock, or source expression.
#### Ownership, selection, and identity
- **directly measured WW behavior** — before this change, both stages adopted
an existing physical `foo.bar` as a raw source. Build and run therefore used
its package, imports, main, and runtime status instead of `foo/bar.ww`;
raw, compile-only, and assembly-only test used its test descriptors and
retained its semantic/public bytes. Removing only `foo.bar` selected the
logical provider and changed all of those observations.
- **behavior derived from the pinned implementation** — the true shared
owners are `cmd/ww/main.c::resolve_module` and
`selfhost/cmd/ww/main.ww::resolvemodule`. Their direct non-directory adoption
now requires the exact `.ww` requested spelling. The mirrored spelling
predicate also owns build/run requested-literal bookkeeping and raw test's
second-positional classifier plus main stat/resolution branch. These command
fronts distinguish direct directory, eligible direct source, and logical
resolution without moving the rule into the compiler, enumerator, graph,
coordinator, producer, or runtime.
- **directly measured WW behavior** — a resolved logical single-file provider
retains the established command-line-file root family `__root.*`; selection
by a dotted request does not invent a dotted storage identity. A resolved
logical directory retains its dotted package/import/action family such as
`foo.bar.*`. The ignored physical pathname, object kind, containing
directory, bytes, mode, and timestamp create no package member, qualifier,
graph node or edge, action, symbol, `.wwi`, initializer, artifact,
publication destination, or persistence key. The logical requested spelling
remains canonical request identity where the existing directory route uses
it.
- **directly measured WW behavior** — requested suffix, not a symlink target's
basename, owns the positive gate. A wrong-suffix symlink to a regular or
non-directory special object is ignored as source; a wrong-suffix symlink to
a directory follows ordinary directory routing. A visible `.ww` symlink to a
regular source remains eligible. Each stage retains its prior visible `.ww`
special-file kind handling; this slice does not make FIFO/device loading a
shared new contract.
#### Build, test, package, and import effects
- **directly measured WW behavior** — with a logical provider, build produces
the same source set, import closure, initializer graph, producer calls,
runtime result, public output, and persistent artifacts whether the
wrong-suffix object is absent or present. Run executes that same provider.
Raw/running test, the historical second-positional test-name filter,
`test -c`, and `test -S` select the same logical test package, descriptors,
support closure, binary, and assembly. Cstage and WWstage outputs and every
comparable semantic artifact are byte-identical.
- **directly measured WW behavior** — the ignored object's package clause,
imports, malformed bytes, checker failures, abort/nonzero behavior, and
timestamps are not source input and cannot displace logical-provider
diagnostics. Package membership and import edges are exactly those of the
provider. A logical directory retains its dotted identity and a logical file
retains `__root`; physical collision state supplies neither.
- **directly measured WW behavior** — when no logical provider exists, a
collision matches the absent-physical control. An ordinary build or run
emits its existing `cannot find module` diagnostic; raw test emits its
existing `cannot find` diagnostic plus `FAIL` only when running; `-c` and
`-S` omit that marker. A second positional deliberately retains the historic
package-coordinator route and its exact canonicalization or usage result,
rather than being silently redefined as a direct cannot-find path. Existing
flag, output, tree, package-option, hidden-source, named `_test.ww`, and
`.ww` run-directory precedence remains unchanged.
- **behavior derived from the pinned implementation** — all four permanent
axes meet at this one source-eligibility decision. Build no longer constructs
or publishes the wrong action; test no longer constructs or runs the wrong
test package; package membership is not stolen by an ineligible physical
filename; and import binding/initialization comes only from the logical
provider. No axis receives a compatibility bypass or new identity model.
#### Lifecycle, parity, formats, and scope
- **directly measured WW behavior** — changing the collision among absent and
stat-successful non-directory states does not invalidate semantic actions or
alter semantic bytes or producer inputs. An unchanged warm command still
performs the established final link and success publication, producing the
same public bytes while its inode and mtime may change. Replacing the
collision with a directory, or retargeting a symlink to a directory, leaves
this case and follows ordinary stat-first directory behavior; no new atomic
snapshot promise is made for a concurrent kind change.
- **directly measured WW behavior** — logical producer failure preserves the
prior public and semantic generation. A retained running-test runtime failure
occurs after the complete logical build generation commits: deferred public
installation is skipped, so prior retained public bytes survive while the
newly built semantic generation remains committed and reusable. Restoring the
prior source requires a later successful rebuild and commit, not rollback of
the runtime-failing generation. Normal completion and controlled failures
remove request-owned scratch and transaction fragments. The spelling gate is
request-local and allocates no state before logical action or coordinator
start; concurrent requests use separate destinations and the existing
logical-action synchronization.
- **directly measured WW behavior** — external signal interruption after an
action starts is unchanged. In particular, the verified direct-driver fixed
`.new` leakage and later persistent-request poisoning remain open. This
source classifier neither prevents nor recovers that residue and makes no
signal-cleanup claim.
- **behavior derived from the pinned implementation** — the rule does not
complete the remaining suffix-first run front, multiple named sources,
finite `.ww` FIFO capture, shared test-process state/failure topology,
Go-compatible `-run` regular expressions, or `package documentation`
suppression. Existing `.ww` directory slices, hidden-source exclusion,
named `_test.ww` build omission, recursive/multiple-root coordination,
package syntax, and import syntax remain intact.
Build workdir format remains `18`, test workdir format remains `19`, and
semantic storage format remains `3`. No schema, action descriptor, cache/result
record, manifest, transaction protocol, or lock changes.
## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins.