test: prove declared package import semantics
This commit is contained in:
@@ -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.6–11.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 436–493](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L493),
|
||||
[`go/build/build.go`, lines 939–1049](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 633–636](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L633-L636),
|
||||
[lines 757–806](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L757-L806),
|
||||
[lines 2024–2047](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 144–203](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L144-L203),
|
||||
[lines 228–293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L228-L293),
|
||||
[lines 421–472](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 26–40](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/package.go#L26-L40),
|
||||
[`go/types/resolver.go`, lines 237–350](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L237-L350),
|
||||
[lines 463–480](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L463-L480),
|
||||
[lines 701–735](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 223–335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L223-L335),
|
||||
[lines 473–486](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L473-L486),
|
||||
[lines 706–740](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 152–196](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/importer/ureader.go#L152-L196),
|
||||
[`go/internal/gcimporter/ureader.go`, lines 224–244](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 437–455](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L455),
|
||||
[lines 628–659](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L659),
|
||||
[`cmd/go/internal/test/test.go`, lines 1133–1226](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.
|
||||
|
||||
22
docs/spec.md
22
docs/spec.md
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user