test: prove declared package import semantics

This commit is contained in:
2026-08-14 03:08:16 +09:00
parent 6efe9b70d4
commit a841278333
11 changed files with 1001 additions and 131 deletions

View File

@@ -2634,10 +2634,13 @@ commit and are implementation evidence, not requirements for the replacement.
### 11.2 Conflated identities and accidental behavior
This table records the baseline that the implemented slices below replaced;
sections 11.611.18 are authoritative where they conflict with it.
| Concept that must be separate | Current conflation or accident |
|---|---|
| package identity | Dotted import spelling is graph key, module/symbol prefix, artifact basename, and link identity. |
| declared name | A directory's leaf is checked against it for imports, but root directories and literal file roots receive different validation. `.wwi` itself retains only the leaf package name. |
| package identity | Before the local-package slices, dotted import spelling was simultaneously graph key, module/symbol prefix, artifact basename, and link identity. The implemented loader now separates source spelling, expanded canonical identity, physical directory, and storage locator. |
| declared name | Before section 11.18, imported directories required their declared name to equal the import-path leaf and `.wwi` retained only that leaf. The implemented compiler/export path now carries the declaration independently. |
| filesystem location | Ordered search roots silently choose/shadow a location; the same physical directory may be compiled under two import identities, while duplicate locations for one spelling produce no collision diagnostic. Paths are lexical, not content identities. |
| package versus file | Directories create separate-compilation nodes; files disappear into owners. The same `package` syntax means two compilation models. |
| artifact versus identity | `<dotted-path>.wwi/.s/.o/.a` names artifacts; root aliases to `__root`, which can collide with a real import. |
@@ -2802,19 +2805,22 @@ falls back to directory lookup through the entry package's directory, explicit
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
canonical directory actions, and reports self-imports and stable cycle chains
before compilation.
imports-only parser, retains every real import occurrence with its owning
source file and position, byte-sorts and deduplicates the resulting canonical
direct edges, interns canonical directory actions, and reports self-imports and
stable cycle chains before compilation. Occurrence retention makes contextual
`internal` and `vendor` checks run at every import site; it does not duplicate
package actions or compiler inputs.
A directory package consists of its immediate `.ww` entries whose basenames do
not begin `.` or `_`: regular files and symlinks targeting regular files are
included under the entry name, while symlinks targeting directories are
ignored. The production variant excludes `*_test.ww`; each variant retains
byte-sorted filename order. Every selected file must
declare the same package. An ordinary importable directory's declaration must
equal the final component of its import path. A selected command directory
instead declares `package main` to validate command kind while retaining its
complete canonical import identity. A source import of a command package from a
byte-sorted filename order. Every selected production file must declare the
same package name, but that declaration is independent of the directory name
and every component of the canonical import path. A selected command directory
declares `package main` while retaining its complete canonical import identity.
A source import of a command package from a
different directory is rejected; the one same-directory exception is an
external `main_test` variant's canonical import of its production action. Two
ordinary logical identities for one physical directory are rejected rather
@@ -2842,9 +2848,11 @@ path and deduplicated by the loader; a source spelling expanded through
`vendor` additionally receives the non-dependency `--import-map` described in
section 11.16. No transitive `.wwi` is passed.
Origin-tagged facts inside those direct artifacts are compiler data, not source
imports: a source qualifier is visible only when its owning package directly
imports it, and private members, transitive-only qualifiers, bare values, and
bare types remain compiler errors. In `-c` package mode the compiler parses each
imports: a source qualifier is visible only in the source file that directly
imports it. The qualifier is the imported export's declared package name, not
the source spelling or import-path leaf. Private members, transitive-only
qualifiers, bare values, and bare types remain compiler errors. In `-c` package
mode the compiler parses each
export independently, then coalesces repeated exported type/constant facts with
the same origin, kind, and name, preserving one nominal type identity across
diamonds; raw non-package `w6c` retains its existing one-source behavior. The
@@ -2855,8 +2863,9 @@ boundary is live in production Cstage and WWstage compilers and drivers.
A selected production root is one normal package action. Its finalized
canonical import identity tags its owner-only unit; it receives only direct
exports, emits `.wwi`, `.o`, and a deterministic `.a`, and is compiled exactly
once. The declared package name validates the last component of that identity
for ordinary importable packages. After loading and identity finalization, the
once. The declared package name is semantic package content but never validates,
shortens, aliases, or replaces that identity. After loading and identity
finalization, the
declaration also selects the terminal build action: `package main` is a command
and every other valid declaration is a compile-only library. A command root
receives the narrow compiler `--entry` flag, which controls bare `main` codegen,
@@ -2869,8 +2878,8 @@ package declaration to classify and remains a raw command unit; it does not
participate in canonical directory-package interning.
The package driver still uses the parser-only `--command-package` marker for
command test variants that must remain ordinary archive code. Neither marker
changes export identity, and imported interfaces remain under strict leaf
validation. The linkers seed `main` before archive selection, so the existing
changes export identity, and imported interfaces retain independent canonical
owner and declared-name records. The linkers seed `main` before archive selection, so the existing
WWAR member protocol needs no special root object or format change.
Publication is separate from that semantic action choice. `ww build -o lib.a
@@ -2885,7 +2894,7 @@ action identity. The historical action-selecting `-p` exception is removed and
rejected as an unknown build flag. Assembly-only `-S` still stops before object,
archive, publication, or link production. A literal directory is
reverse-resolved through the active source roots or receives the deterministic
local identity described below; its declared leaf can never invent or truncate
local identity described below; its declaration can never invent or truncate
that identity. Two cold builds with identical inputs are required to produce
byte-identical requested products. Compiler intrinsics keep their package-mode
runtime ABI independent of transitive source interfaces (for example, `alloc`
@@ -2918,7 +2927,7 @@ publication spelling, `FILE.wwi.new`, so an incomplete archive/export pair is
never caused by a late path-overflow failure. Package loading, cycle detection,
and closure validation retain diagnostic precedence over this publication-only
check, and `-S` does not validate a publication path it never consumes.
Build workdir format 13 and test workdir format 12 invalidate older unit
Build workdir format 14 and test workdir format 13 invalidate older unit
vouchers before reuse because source binding and vendor-directory identity now
participate in compiler argv and persistent unit semantics. Thereafter
an equivalent warm library build invokes no tools, a private dependency change
@@ -2956,21 +2965,28 @@ package variant:
files followed by byte-sorted matching `package p` test files. It is distinct
from production so its private production declarations and test declarations
remain isolated to that test product.
- The external variant selects only matching `package p_test` files. Its
`import p` is a direct edge to the same ordinary production action used by
- When production sources establish `p`, the external variant selects only
matching `package p_test` files, where `p` is the production declaration
rather than an import-path leaf. A test-only directory may establish its own
one consistent test package name, matching pinned `go/build` classification.
A real source import of the production package uses its canonical import
path and is a direct edge to the same ordinary production action used by
ordinary products and transitive imports; there is no external-production
role or artifact.
- Generated main is a separate package action whose owner-only generated unit
declares `package main` and imports exactly the selected variant and test
support. It consumes those direct `.wwi` files, emits its own `.wwi/.o/.a`,
and alone receives compiler `-T --entry`.
and alone receives compiler `-T --entry`. Its target edge also receives the
compiler-private `--test-target-package <canonical-path>` binding. That
private canonical-path qualifier prevents a tested command declared `main`
from colliding with generated main; it is not user alias syntax.
The authoritative directory-action identity is the triple **(canonical
filesystem directory, canonical ordinary import path, semantic variant)**.
The semantic variants are production, internal production-plus-test, and
external `_test`; generated main and the reserved test-support alias are
explicit non-directory action classes. Source package name validates the leaf
of the bound import path but is not itself a second identity. Requested-root
explicit non-directory action classes. The declared package name is stored
separately and is not part of canonical directory/path interning. Requested-root
state, discovery role, product ordinal, output path, persistent artifact key,
and discovery order never enter the triple.
@@ -2999,17 +3015,19 @@ invocation, each still-unbound directory is finalized by this exact algorithm:
root cannot rename an explicitly resolved package.
4. If no active root can represent the directory, bind the reserved,
non-source-importable identity
`__wwlocal.p<escaped-canonical-absolute-directory>.<declared-leaf>`. The
`__wwlocal.p<escaped-canonical-absolute-directory>`. The
escape is injective and reversible over path bytes: ASCII letters and digits
are copied, `_` becomes `_u`, `/` becomes `_s`, and every other byte becomes
`_xHH` with lowercase hexadecimal. Source imports of `__wwlocal` or any of
its children are rejected, so this command-local identity creates no alias.
The selected full identity's final component is then validated against the
ordinary declared package name (or against the ordinary leaf obtained by
removing `_test` for the external variant). The one command-kind rule is that a
selected command family declares `main`/`main_test` while keeping the finalized
ordinary identity unchanged. A source import of that command from another
The selected full identity is never validated against the ordinary declared
package name. Production and internal variants retain the production
declaration; when production exists, an external variant is admitted only as
`<production-declared-name>_test`. A test-only directory instead establishes
one consistent test package declaration itself. The one command-kind rule is that a selected
command family declares `main`/`main_test` while keeping the finalized ordinary
identity unchanged. A source import of that command from another
directory rejects as a program before tools; a colocated external command test
may reuse the canonical production action. There is no fallback from an empty
import path to a declaration name. Relative, absolute, and symlink spellings
@@ -3027,9 +3045,10 @@ The derivation and diagnostics are implemented symmetrically in
variant descriptors, preserves an explicitly resolved identity only for one
direct request, and forwards a caller's `-w` semantic-action store unchanged.
It never derives identity or persistent layout from a pattern traversal prefix
and does not add that prefix to import search. `w6c` and `wcc` continue to
consume and validate the finalized dotted identity; neither tool performs
directory lookup or introduces a package registry.
and does not add that prefix to import search. `w6c` and `wcc` consume the
finalized dotted identity as export/symbol owner while reading the declared
name independently from export data; neither tool performs directory lookup or
introduces a package registry.
Artifact publication follows the semantic action instead of product order:
production uses the full finalized ordinary identity, internal appends
@@ -3352,11 +3371,13 @@ and any sorted driver-private vendor/import-map voucher comments, but no
dependency body. When exact source spelling differs from a selected expanded
canonical identity, the drivers also pass sorted, unique
`--import-map <source-spelling> <canonical-import-path>` triples. A map must
preserve the import leaf and target an ordinary direct `--import`; it adds no
export input or graph edge. The compilers rewrite only matching imports in the
primary source list before merging interfaces, leaving the source qualifier,
position, imported interface metadata, and generated/synthetic imports
untouched. Executable linking independently walks the full reachable package
target an ordinary direct `--import`; it adds no export input or graph edge.
The compilers rewrite only the matching primary import's canonical semantic key
before merging interfaces. They then obtain that target's declared package name
from its direct export and install it as the default qualifier in the owning
source file. Source spelling and position remain intact; generated/synthetic
imports use their explicit compiler-owned bindings. Executable linking
independently walks the full reachable package
closure and passes archives, never interfaces. The same path handles an
ordinary package, the production-plus-internal-test variant, the external test
package and its reused production package, compiler-generated test main, and
@@ -3533,14 +3554,13 @@ and storage-address derivation. The complete `path`, together with the
semantic `variant` and `role`, is the persisted/compiler owner carried through
source-import edges, module-reset and export ownership, compiler `--import`
arguments, generated-main construction, and symbol qualification; `storage`
participates in none of those identities. The reversible outside-root form
remains
`__wwlocal.p<escaped-canonical-absolute-directory>.<declared-leaf>` and is
participates in none of those identities. The reversible outside-root form is
`__wwlocal.p<escaped-canonical-absolute-directory>` and is
allocated to its exact length. It is neither truncated nor replaced by a
digest, and `__wwlocal` remains unavailable to source imports. Package
declarations continue to validate the selected package kind and leaf; they do
not supply a missing identity and do not alter a command package's canonical
path.
declarations classify package kind and contribute semantic export content; they
do not validate a path leaf, supply a missing identity, or alter a command
package's canonical path.
Short actions retain their established `.unit.ww`, `.wwi`, `.s`, `.o`, and
`.a` basenames when the basename plus `.unit.new` fits the 255-byte supported
@@ -3712,6 +3732,9 @@ The Cstage representation is exact and deliberately small:
`depcap`;
- each `seppkg.context_state` is a lazily extended, zero-filled
`unsigned char *` with `context_cap`;
- each package owns a dynamically grown import-occurrence vector recording
kind, source spelling, source file, line, column, and stable dependency
action index; its separate dependency vector remains sorted/deduplicated;
- parsed `sepproduct` values are a dynamically allocated vector, and each
product stores its support-action index directly; and
- package-load frames and topological-DFS frames are temporary dynamic vectors,
@@ -3720,7 +3743,8 @@ The Cstage representation is exact and deliberately small:
The WWstage representation is isomorphic. `sepgraph.pkg: []seppkg` and
`sepgraph.context: []sepcontext` use allocated slice length as capacity and keep
separate `n`/`ncontext` logical counts. Every `seppkg` owns a dynamically grown
`deps: []i32` with `ndeps` and a lazily zero-extended `contextstate: []u8`.
`bindings: []sepbind`, a dynamically grown `deps: []i32` with `ndeps`, and a
lazily zero-extended `contextstate: []u8`.
Products, load frames, and topological frames use typed dynamically allocated
slices. `internal/wwpackage` continues to construct one union command for all
selected directory-test groups, but now checks the complete
@@ -4051,7 +4075,9 @@ directory, rather than falling through.
Source retains only the effective spelling, such as `lib.math`. Selection
assigns the target the complete expanded canonical identity, such as
`domain.app.vendor.lib.math`, and separately canonicalizes its physical
directory. The action key is that expanded identity and canonical directory,
directory. The target's declared name independently supplies the default
qualifier in each importing source file. The action key is that expanded
identity and canonical directory,
plus the existing variant/role. Different physical vendor copies are distinct;
different expanded vendor routes remain distinct even when symlinks converge
on one physical directory; repeated resolutions of the same pair reuse one
@@ -4110,12 +4136,13 @@ unique auxiliary mapping:
```
Both compilers require the map target to be an existing direct `--import`,
require source keys to be sorted and unique, require the final import leaf to
remain unchanged, and require a matching import in the primary source input.
After parsing only that primary input and before prepending imported interfaces,
the compiler replaces its semantic import key while preserving its source leaf,
position, and spelling bytes. Imported `.wwi` nodes and synthetic sources are
never rewritten. Thus the map adds no dependency or export input, expanded
require source keys to be sorted and unique, and require a matching import in
the primary source input. No leaf-equality condition exists. After parsing the
primary input and before prepending imported interfaces, the compiler replaces
its semantic import key while preserving source position and spelling. It then
reads the expanded target's declared name from the direct `.wwi` and installs
that name only in the declaring source file. Thus the map adds no dependency or
export input, expanded
identity flows into self-contained `.wwi` ownership and symbols, and direct
exports still have no transitive leakage. Linking remains independent: each
executable consumes its root archive and complete reachable archive closure,
@@ -4132,7 +4159,7 @@ Hex encoding keeps arbitrary legal filesystem bytes inside one comment. The
metadata makes ordinary-to-vendor changes and vendor symlink retargeting
invalidate the importer even when its source bytes and both already-warm export
bytes happen to match. It contains no dependency body and does not alter source
positions. The current workdir formats are build 13 and test 12. An equivalent
positions. The current workdir formats are build 14 and test 13. An equivalent
warm request remains a package-production no-op; an export change propagates
only through ordinary direct-export comparison.
@@ -4320,7 +4347,8 @@ and cannot make one variant visible to another.
Vendor selection remains distinct from vendor import resolution. Selecting a
directory below `vendor`, literally or through an explicitly vendor-rooted
pattern, keeps its complete canonical local identity; it is never shortened to
the suffix after `vendor`. A generic recursive pattern does not expose vendored
the suffix after `vendor`, and its declaration never renames it. A generic
recursive pattern does not expose vendored
descendants as ordinary short command roots. Independently, an allowed real
source import still searches nearest-first below local `vendor`, creates the
expanded identity described in section 11.16, supplies the required
@@ -4355,8 +4383,8 @@ files. A compiler receives exactly the sorted, deduplicated `.wwi` exports of
direct source dependencies and any required vendor import-map binding. Each
executable link receives its root archive and complete reachable archive
closure, never a `.wwi`. Canonical duplicate roots reuse the same action; the
pattern text and the product receiving an output do not affect semantic or
persistent identity.
pattern text, declared qualifier, and product receiving an output do not affect
canonical or persistent action ownership.
Selection and package-clause validation finish before the coordinator creates
its removable temporary plan, and the coordinator never creates persistent
@@ -4457,6 +4485,208 @@ rejection-state preservation. The existing
diamond and long-closure observers independently prove sorted/deduplicated
direct `.wwi` cardinality and archive-only reachable link closures.
### 11.18 Implemented canonical identity, declared-name, and file-import-scope slice
Directory-package identity and source naming are now independent throughout
local build and test. For example:
```ww
// canonical import identity: acme.codec
package wire;
```
is imported with the existing dotted syntax:
```ww
package main;
import acme.codec;
export fn main() i32 = { return wire.value(); };
```
The package action, exports, symbols, archives, dependency edges, persistent
storage ownership, and link closure remain owned by `acme.codec`. Only the
source-file binding is named `wire`. The path leaf `codec` is not installed as
another qualifier, and a sibling source file receives no `wire` binding unless
that file has its own import.
The implemented representation keeps five facts distinct:
1. source import spelling, including its source file, line, and column;
2. contextually expanded canonical import identity;
3. canonical physical directory;
4. the one declared package name read from eligible source clauses and `.wwi`
package markers; and
5. the source-file-local default qualifier binding from that declaration to
the canonical target.
Both drivers retain one dynamically allocated `sepbind` occurrence for every
real import site. The occurrence stores the source spelling and position plus a
stable action index. Contextual `internal` and vendor resolution is therefore
rechecked for every source import even if its target action already exists. A
separate package dependency vector unions those occurrences, deduplicates by
canonical action, and sorts by complete canonical identity/variant/role. That
vector alone supplies dependency traversal and compiler `--import` arguments.
Patterns, qualifiers, declared names, export closure facts, and generated edges
never create source dependency edges.
The owner-only composed unit preserves byte-sorted source boundaries with one
`//ww:module-reset <canonical-owner>` separator per file. Parser nodes carry a
source-section ID as well as canonical owner and declared package name. Each
real `N_USE` therefore belongs to one source section. `.wwi` emission repeats
canonical-owner/package markers as needed for contributing source sections and
retains imports only with the declarations from the file that owned them.
Interfaces remain source-like transitional data, but canonical owner and
declared name are no longer collapsed into one token.
`w6c` and `w6c_ww` validate every direct export's leading canonical owner
against its paired `--import` path. After all direct exports are parsed, they
build canonical-path-to-declared-name metadata from those interfaces, apply any
vendor `--import-map` only to canonical identity, and bind the imported
declaration as the default qualifier of each primary source import. The
checkers and code generators select bindings by source-section ID and canonical
owner. Qualified and retained bare-import lookups mark only that file's binding
used. Two files may consequently bind the same name to different canonical
packages, while the graph still contains one edge/action for each target.
Within one file, two imports that produce the same default qualifier are a
redeclared binding; the later unused binding is also reported. An unused import
is reported at its own import position even if a sibling file uses the same
qualifier or canonical dependency. A package-scope declaration collides with
an equal import binding from any contributing file, matching Go's reconciliation
of package and file scopes. Conflicting production package clauses remain a
loader-owned deterministic error before producers. Compiler-owned scope or use
errors may invoke the compiler, but the driver removes that action's staged
`.new` unit/export/assembly/object/archive files instead of renaming them. No
completion/status marker is written, and no publication occurs after a failed
compile.
Package kind follows the declaration. `package main`, not a path component,
marks a command. A path ending in `main` remains importable when it declares a
different name. Any ordinary source import of a package declared `main` is
rejected as `package <canonical-path> is a program, not an importable package`,
regardless of its path leaf. The one pinned loader exception is an external
test's exact same-directory import of the command production: it is rewired to
the forced-library test copy. WW admits only that canonical colocated edge.
Test naming is likewise declaration-based. Production and internal-test
variants use the production declared name. When production files exist,
external files must declare `<production-declared-name>_test`; a test-only
directory may establish one consistent package name from its test files, as in
pinned `go/build`. External action identity remains the canonical production
identity plus the existing external variant suffix where that production
exists. Imports found only in internal or external test files belong only to
that variant. Support and generated-main actions retain their isolated
identities and archive closures. A generated dispatcher privately binds its
tested target through
`--test-target-package <canonical-path>` so a command variant declared `main`
does not collide with the dispatcher's own synthesized `main`; this is
compiler-generated wiring, not source alias syntax. Zero-test dispatchers mark
their compiler-owned target/support metadata imports consumed.
Vendor expansion changes only canonical identity and physical selection. A
source spelling such as `lib.codec` can resolve to
`domain.app.vendor.lib.codec`, while the vendored package's declaration, for
example `package wire`, supplies the file-local qualifier. The driver emits one
sorted semantic `--import-map lib.codec domain.app.vendor.lib.codec` and one
direct export input despite repeated import occurrences in separate files.
The expanded identity continues to own symbols, `.wwi`, archive, voucher, and
link inputs.
Canonical action interning remains the directory/path/variant model of sections
11.7 and 11.14. Independent file bindings never clone an action, and a declared
name never enters an artifact basename or storage locator. The name is semantic
content in the owner unit and export. Changing only a dependency's declaration
therefore keeps the same action identity but changes its export bytes, causes
each direct importer to be reconsidered, and stops propagation after an
importer's regenerated export is unchanged. An identical warm request remains
a producer no-op. Build workdir format 14 and test format 13 prevent reuse of
older vouchers that lack these semantics.
Compiler argv still contains exactly the sorted, deduplicated `.wwi` exports of
direct canonical dependencies; no transitive `.wwi` and no qualifier-derived
path appears. Linker argv still contains only the executable root archive and
complete reachable archive closure plus runtime/native inputs. Publication and
completion occur only after the corresponding action/product succeeds.
Responsibility is intentionally split as follows:
- `internal/wwpackage` classifies production, internal, and external test files
from their declarations, derives the allowed external name from the
production declaration, expands request patterns, and submits variant roots.
It does not resolve imports, choose qualifiers, or create dependency edges.
- `cmd/ww/main.c` and `selfhost/cmd/ww/main.ww` own per-site parsing and
contextual resolution, canonical directory/action interning, declared-name
consistency, imported-command rejection, sorted dependency union, exact tool
argv, variant/generated-main construction, persistence, linking, and
publication. Their storage, diagnostics, call positions, and allocation
failures are isomorphic.
- `cmd/w6c`/`cmd/wcc` and `selfhost/cmd/w6c`/`selfhost/cmd/wcc` own export
owner/name reading and writing, file-local binding installation, collision
and unused-import diagnostics, name/type lookup, canonical symbol ownership,
and generated-dispatcher private qualification. Cstage and WWstage emit
byte-identical applicable interfaces, assembly, archives, and binaries.
- `cmd/wwtest` remains only the test-command dispatcher.
The behavior follows pinned official Go 1.26.5 source at commit
`c19862e5f8415b4f24b189d065ed739517c548ba`:
- `go/build.Package` stores `Dir`, `Name`, `ImportPath`, production files, and
test files independently, while package-clause consistency is checked during
file classification
([`go/build/build.go`, lines 436493](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L493),
[`go/build/build.go`, lines 9391049](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L939-L1049)).
- The loader interns by resolved `ImportPath`, keeps `ImportPath` and `Name`
separate, constructs edges from source imports, and rejects an imported
package whose `Name == "main"` except for the exact same-directory test case
([`cmd/go/internal/load/pkg.go`, lines 633636](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L633-L636),
[lines 757806](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L757-L806),
[lines 20242047](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2024-L2047)).
- The test loader builds distinct production/internal/external/generated-main
packages, derives external `Name` from `p.Name + "_test"`, handles the
same-directory command self-import, and rewrites it to the library-form test
copy
([`cmd/go/internal/load/test.go`, lines 144203](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L144-L203),
[lines 228293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L228-L293),
[lines 421472](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L421-L472)).
- `go/types.Package` stores independent path and name. The resolver creates one
child scope per source file, uses the imported package's declared name when
no alias is present, inserts imports into that file scope, reconciles them
with package declarations, and reports unused imports
([`go/types/package.go`, lines 2640](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/package.go#L26-L40),
[`go/types/resolver.go`, lines 237350](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L237-L350),
[lines 463480](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L463-L480),
[lines 701735](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L701-L735)).
The production compiler mirrors those rules
([`cmd/compile/internal/types2/resolver.go`, lines 223335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L223-L335),
[lines 473486](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L473-L486),
[lines 706740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)).
- Compiler export import reconstructs and interns package descriptors by
canonical path while restoring their independently encoded package names and
imports
([`cmd/compile/internal/importer/ureader.go`, lines 152196](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/importer/ureader.go#L152-L196),
[`go/internal/gcimporter/ureader.go`, lines 224244](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/internal/gcimporter/ureader.go#L224-L244)).
- Work actions consume cached canonical package objects and direct imports,
while test execution builds and links the isolated test action graph
([`cmd/go/internal/work/action.go`, lines 437455](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L455),
[lines 628659](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L659),
[`cmd/go/internal/test/test.go`, lines 11331226](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1226)).
The deliberately retained source grammar is `import dotted.path;`. Quoted Go
imports, explicit aliases, dot imports, and blank imports are not implemented.
Because bindings already retain source ownership and position separately from
canonical identity and declared name, adding explicit aliases later will not
require another package-wide namespace redesign.
The focused native observer
`declared_name_identity_and_file_import_scope` generates every tree
temporarily and exercises both stages from independent cold roots. It proves
the identity/name/qualifier split, file-local collision and unused behavior,
one-edge/action reuse, command and imported-command rules, all test variants,
vendor expansion, recursive/direct selection, owner-only units, exact direct
exports and archive-only links, warm no-op behavior, declared-name invalidation,
rejection-state preservation, normalized argv, artifact/binary identity,
allocation-bearing runtime behavior, and request/product-order independence.
## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins.

View File

@@ -249,13 +249,25 @@ PackageClause = "package" ident ";" .
ImportDecl = "import" ident ";" .
```
- Every source file begins with a package clause. A directory of `.ww`
files sharing one package name compiles as a single module.
- `import foo;` makes module `foo`'s exported names available as
`foo.Name`. Self-import is rejected.
- An executable's entry module is `package main;` with a `fn main`.
- Every source file begins with a package clause. A directory of eligible
`.ww` files sharing one declared package name compiles as one package. The
declared name need not equal the directory name or the final component of its
canonical import identity.
- `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. The import binding
is scoped to that source file. A sibling file must declare its own import.
The package dependency graph is the sorted, deduplicated union of the real
imports in all eligible files. Self-import is rejected.
- An executable package is one declared `package main` and containing a
`fn main`; path and directory spelling do not classify commands. An ordinary
import of a package declared `main` is rejected, except for the toolchain's
colocated external-test wiring.
- Only names marked `export` (§5) are visible across module boundaries.
The implemented grammar remains dotted and unaliased. Quoted import paths,
explicit aliases, dot imports, and blank imports are not currently accepted.
---
## 5. Declarations

View File

@@ -227,6 +227,20 @@ owns individual `@test` functions.
Separate compilation is the only driver build path; no compatibility mode
switch remains.
`test/package/package_test.ww` also owns the dual-stage
`declared_name_identity_and_file_import_scope` observer. It generates temporary
directory trees proving that canonical import identity, physical directory,
declared package name, and source-file default qualifier remain distinct;
imports are file-scoped while dependency edges are the package-wide sorted
union; command and production/internal/external/generated-main variants retain
canonical action ownership; vendor expansion changes identity but not the
declared qualifier; compiler argv contains only direct `.wwi` inputs; and its
named rejected actions leave neither committed nor staged action artifacts or a
published binary. Together with the existing directory, recursive, vendor,
exact-argv, command, and persistent-workdir observers, the package suite proves
archive-only link argv and exact warm/rejection-state behavior without
duplicating those broader mechanisms in this observer.
`ww build`, an explicit single-file `ww test -o <stem>`, and each successful
directory-package `ww test -c` build publish `<stem>.sepwork` as a caller-owned
artifact directory. The driver acquires it with one fresh `mkdir` and refuses