driver: ignore wrong-suffix files as named sources
This commit is contained in:
@@ -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:2887–2932`, especially 2903–2918,
|
||||
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:3244–3318` before constructing its synthetic package.
|
||||
Build and test call that loader at
|
||||
`cmd/go/internal/work/build.go:459–477` and
|
||||
`cmd/go/internal/test/test.go:684–719`. Run independently consumes only
|
||||
leading `.go` spellings at `cmd/go/internal/run/run.go:73–145`, especially
|
||||
96–123.
|
||||
- **behavior directly implemented or asserted by pinned Go** — official
|
||||
`cmd/go/testdata/script/list_test_non_go_files.txt:1–13` 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:1–10`
|
||||
and `run_set_executable_name.txt:4–17` 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.
|
||||
|
||||
46
docs/spec.md
46
docs/spec.md
@@ -395,6 +395,52 @@ ImportPath = ident { "." ident } .
|
||||
persistence, process, or filesystem owner. Build and all test forms retain
|
||||
their distinct stat-first directory behavior. Build workdir format remains
|
||||
18, test workdir format remains 19, and semantic storage format remains 3.
|
||||
- A public operand is eligible for direct named-source adoption only when its
|
||||
exact requested spelling ends `.ww` and that command's existing file-kind
|
||||
rule admits it. An existing non-directory object with another suffix is not
|
||||
source: its bytes, package clause, imports, syntax, test declarations,
|
||||
runtime behavior, mode, and timestamp are not read as source, and ordinary
|
||||
dotted resolution continues exactly as though the colliding object were
|
||||
absent. Thus request `foo.bar` may resolve `foo/bar.ww` or `foo/bar/` even
|
||||
while a physical non-directory `foo.bar` exists. A wrong-suffix symlink to a
|
||||
non-directory is the same ignored collision; a symlink to a directory remains
|
||||
an ordinary stat-first directory request. A visible `.ww` symlink to a
|
||||
regular source remains eligible, and the established stage-specific handling
|
||||
of visible `.ww` special files is not broadened by this rule.
|
||||
|
||||
A resolved logical single file retains the established `__root` command-line
|
||||
package/action/artifact identity. A resolved logical directory retains its
|
||||
dotted package, import, graph, action, symbol, `.wwi`, initializer, artifact,
|
||||
publication, and persistence identity. The ignored physical pathname/object
|
||||
creates no membership, binding, edge, action, key, or alternate identity.
|
||||
Build and run use only the logical provider's production/import/initializer
|
||||
closure and runtime. Raw running test, its historical second-positional
|
||||
test-name filter, `test -c`, and `test -S` use only the provider's test
|
||||
package, descriptors, support closure, binary, and assembly.
|
||||
|
||||
When no provider exists, collision-present behavior is byte-for-byte the
|
||||
existing collision-absent behavior. An ordinary single target retains its
|
||||
direct build/run/test cannot-find result and creates no producer action. A
|
||||
second positional retains the established package-coordinator route,
|
||||
diagnostics, status, selection lifecycle, and cleanup; this source gate does
|
||||
not reinterpret that positional form. Mutation invariance covers only absent
|
||||
and stat-successful non-directory collision states. A transition to a
|
||||
directory leaves this rule and follows ordinary directory routing, with no
|
||||
new atomic-snapshot guarantee for concurrent kind changes.
|
||||
|
||||
Provider compilation failure preserves the prior public and semantic
|
||||
generation. A retained running-test runtime failure occurs after the complete
|
||||
logical build generation commits: it preserves prior retained public bytes by
|
||||
skipping deferred installation, while that semantic generation remains
|
||||
committed and reusable. Restoring prior source bytes requires a later
|
||||
successful rebuild and commit, not runtime-failure rollback. Controlled-
|
||||
failure cleanup otherwise remains unchanged. External signal
|
||||
interruption after action start is unchanged, including the verified-open
|
||||
fixed `.new` residue and later persistent-request poisoning. Multiple named
|
||||
sources, remaining suffix-first run behavior, finite `.ww` FIFOs, test
|
||||
process topology, and `-run` regular expressions are not completed here.
|
||||
Build workdir format remains 18, test workdir format remains 19, and semantic
|
||||
storage format remains 3.
|
||||
- `import acme.codec;` loads the canonical package `acme.codec`. If that
|
||||
package declares `package wire;`, the importing file sees its exported names
|
||||
as `wire.Name`; `codec.Name` is not an additional binding. An explicit alias
|
||||
|
||||
@@ -302,6 +302,53 @@ multiple named sources, finite FIFOs, and hidden regular sources are not
|
||||
claimed by this existing-directory slice. The general direct-driver `.new`
|
||||
interruption residue also remains open.
|
||||
|
||||
The raw source front also applies one positive requested-spelling gate before
|
||||
physical adoption. An existing non-directory operand whose exact requested
|
||||
spelling does not end `.ww` is not a raw source and cannot hijack its ordinary
|
||||
dotted provider. Build, run, raw test, the historical second-positional raw
|
||||
test filter, `test -c`, and `test -S` therefore resolve and consume the same
|
||||
logical file or directory they consume when the collision is absent. Logical
|
||||
files keep the existing `__root` action/artifact family; logical directories
|
||||
keep dotted package/import/action identity. The ignored object's bytes,
|
||||
package, imports, tests, runtime status, mode, and timestamp supply no package
|
||||
membership, edge, producer input, artifact, publication, or persistence key.
|
||||
|
||||
Requested suffix owns the gate through symlinks. Wrong-suffix links to regular
|
||||
or special non-directories remain logical requests, while a link to a directory
|
||||
retains stat-first direct-directory routing; a visible `.ww` link to a regular
|
||||
source remains raw source. Each stage's existing visible `.ww` special-file
|
||||
handling is outside this slice. Mutation/reuse invariance is limited to absent
|
||||
or stat-successful non-directory collision states. A transition to a directory
|
||||
uses the directory owner and receives no new concurrent-kind snapshot promise.
|
||||
|
||||
No-provider rows deliberately separate the ordinary single-target path from
|
||||
the second-positional compatibility path. The first retains direct cannot-find
|
||||
diagnostics, running-test `FAIL`, and producer/artifact absence. The second
|
||||
retains the existing package-coordinator process, canonicalization or usage
|
||||
diagnostic, status, selection state, and cleanup; the gate does not turn that
|
||||
route into a direct raw-file error. Logical producer failure preserves prior
|
||||
public and semantic bytes. A retained running-test runtime failure instead
|
||||
keeps the complete newly built semantic generation committed and reusable but
|
||||
skips deferred installation, preserving prior retained public bytes; restoring
|
||||
the old source requires a later successful rebuild and commit. Normal and
|
||||
controlled-failure cleanup is unchanged. External driver signals after action
|
||||
start retain the open fixed
|
||||
`.new` leakage and later-request poisoning behavior.
|
||||
|
||||
The focused `wrong_suffix_physical_files_do_not_hijack_dotted_requests`
|
||||
package observer owns this boundary for both driver stages. It compares absent
|
||||
controls with regular, symlinked-regular, and symlinked-special collisions;
|
||||
checks build, run, raw/filter test, `-c`, and `-S` streams, statuses, runtime,
|
||||
public bytes, complete comparable semantic artifacts, `__root` file identity,
|
||||
and dotted directory identity; separates direct and coordinator no-provider
|
||||
rows; exercises warm non-directory mutation, producer-failure rollback,
|
||||
retained-runtime-failure public-byte preservation with committed semantic-
|
||||
generation reuse and later successful restoration, request-local concurrent
|
||||
builds, positive `.ww` and direct-directory controls, and normal residue
|
||||
cleanup. It makes no finite-FIFO or signal-recovery claim.
|
||||
The rule changes no package coordinator, test harness/process topology,
|
||||
test-result caching, or build/test/semantic format (18/19/3).
|
||||
|
||||
List mode uses that same product process and initialization boundary but starts
|
||||
no per-test child. The shared language harness emits only selected qualified
|
||||
test names, one per line in descriptor order. A valid filter selecting no tests
|
||||
|
||||
Reference in New Issue
Block a user