cmd: resolve source imports only as directories

Separate import lookup from raw CLI target compatibility in both production drivers. Package scans and test-support edges now create directory nodes only, while unit composition emits only the owning package's sorted sources after direct export data. Document the Go 1.26.5 ownership evidence and retained single-file root boundary.
This commit is contained in:
2026-08-12 17:12:49 +09:00
parent c7d9dc92de
commit 0af13ea501
3 changed files with 272 additions and 339 deletions

View File

@@ -2792,13 +2792,16 @@ package main;
import lib.math;
```
An import is translated from dots to path separators and resolved, with
directory packages preferred, through the entry package's directory, explicit
`-I` roots in command order, and the toolchain source-library root. There is no
network or manifest fallback. The loader uses the compiler frontend's
imports-only parser, unions duplicate imports, byte-sorts direct edges, interns
resolved directories by filesystem identity, and reports self-imports and
stable cycle chains before compilation.
An import is translated from dots to path separators and resolved only as a
directory package through the entry package's directory, explicit `-I` roots in
command order, and the toolchain source-library root. A same-named `.ww` file is
neither a match nor a shadow for an import, so a later root containing the
directory wins over an earlier file decoy. There is no network, manifest, or
imported-file fallback. Explicit single-file CLI roots retain their raw-unit
compatibility path. The loader uses the compiler frontend's imports-only parser,
unions duplicate imports, byte-sorts direct edges, interns resolved directories
by filesystem identity, and reports self-imports and stable cycle chains before
compilation.
A directory package consists of its immediate regular non-symlink `.ww` files,
excluding `*_test.ww`, in byte-sorted filename order. Every selected file must
@@ -2896,10 +2899,10 @@ context from the local package slice: its directory, explicit `-I` roots in
command order, then the toolchain source root. Same and external variants of
one directory share that context; unrelated directory roots never acquire
lookup precedence from their request order. When multiple contexts reach one
canonical production package, the loader verifies that every directory,
folded-file, and inline import binding is identical before reusing its compile
action. A different binding is a deterministic package-resolution failure for
the roots that reach it, rather than a first-root-wins build.
canonical production package, the loader verifies that every directory import
binding is identical before reusing its compile action. A different binding is
a deterministic package-resolution failure for the roots that reach it, rather
than a first-root-wins build.
A production action failure blocks exactly the roots that reach it. A
root-local compile or link failure does not suppress a successfully built
@@ -3123,6 +3126,72 @@ WW adopts only the correctness boundary in its existing inspectable `cmp`-based
workdir. It does not add build IDs, hashes, a CAS, an action graph, a scheduler,
or a manifest.
### 11.11 Implemented directory-only source-import slice
Cstage and WWstage now use a directory-only locator for every parsed source
import, including imports selected only by a package-test variant and the
compiler-generated test-support edge. The loader makes one ordered pass for
`<root>/<import-path>/`; it never probes `<root>/<import-path>.ww`. Unit
composition consequently writes only the owning package's byte-sorted source
files after its direct dependency interfaces and never recursively folds an
imported source body. Missing imports retain the importing source position and
the same stable diagnostic in both stages.
Root selection remains a separate compatibility boundary. A literal `.ww` CLI
target, or a bare CLI target found as `<root>/<name>.ww` after the global
directory search, can still create one raw single-file root. Its historical
inline package clauses may satisfy compiler-fixture bindings inside that raw
unit. Directory roots cannot use that exemption, and no filesystem source
import can reach it. This preserves low-level compiler fixtures without
weakening package-graph identity.
The self-hosted tools no longer depend on the removed behavior. `w6a/` and
`w6l/` are executable `package main` directories whose sorted source sets are
compiled once. The compiler backend is one `wcc/` directory package with a
narrow exported check/codegen façade; `w6c` and `wwdump` import that package
from its parent search root instead of importing its implementation files.
Legacy test fixtures were converted to directories, except for one intentional
compiler leaf-collision probe that now invokes `w6c` on an explicitly composed
raw unit. The Lisp example likewise imports a `lispcore/` directory package.
The focused native regression puts only `example/foo.ww` in an earlier import
root and a two-source `example/foo/` package in a later root. Both stages select
the directory, emit the exact sorted package-owned unit, consume its direct
dependency export, produce byte-identical deterministic `.wwi` and `.a`
artifacts, link and run a transitive archive closure, and repeat the resolution
through a real directory-package test. With only the file root present, both
stages reject the import with byte-identical package-attributed stderr. The
existing exact-tool observer remains the non-duplicated proof that each
canonical production action compiles once, compiler units contain only direct
`.wwi` inputs, and linker argument vectors contain the complete reachable `.a`
closure and no `.wwi` path.
This follows Go 1.26.5's concrete directory ownership. `ImportDir` is defined
as importing the package in a named directory; import lookup accepts directory
candidates, then reads and sorts that directory's immediate entries
([`go/build/build.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/go/build/build.go#521),
[`go/build/build.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/go/build/build.go#725),
[`go/build/build.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/go/build/build.go#859)).
Repeated loads reuse the canonical package object, and `PackageList` performs a
pointer-deduplicated postorder walk
([`cmd/go/internal/load/pkg.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/pkg.go#633),
[`cmd/go/internal/load/pkg.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/pkg.go#2776)).
Go's build action is interned by mode and package identity and receives only
the package's direct imports, while linking explicitly expands all transitive
link dependencies
([`cmd/go/internal/work/action.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/action.go#437),
[`cmd/go/internal/work/action.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/action.go#646),
[`cmd/go/internal/work/action.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/action.go#1034)).
Its compiler export writer finalizes self-contained public data in sorted index
order, which is why direct compiler artifacts suffice
([`cmd/compile/internal/noder/unified.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/compile/internal/noder/unified.go#463)).
Finally, Go constructs distinct ordinary, internal-test, external-test, and
generated-main package variants through the same import loader
([`cmd/go/internal/load/test.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/test.go#85)).
WW adopts these package-ownership boundaries without adding modules, manifests,
network lookup, a generalized action graph, or a cache protocol.
## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins.