feat(resolver): complete source-aware nominal-TYPE leaf — bare ns-only types not visible [stdlib E1 attempt-2]
Completes the F1 deliverable the reviewer flagged: the bare TYPE leaf still
returned the global `findByName` match BEFORE any visibility check, so a type
declared only behind a namespaced import leaked bare. Now the registered-type
branch of `selectNominalLeaf` is gated on bare-flat visibility (the type analog
of Phase B's value/function tightening): a bare reference to a namespaced-only
import's TYPE errors ("type 'X' is not visible; #import the module that declares
it") and poisons to `.unresolved` — never the leaked global match, never a
silent empty-struct stub.
Visibility gate is the TRANSITIVE flat-import closure (`typeBareVisible`), not
the single-hop `collectVisibleAuthors`/`isNameVisible`: a flat import is
transitive for resolution, so a type two flat hops away (`CAllocator`, via
`main → std.sx → allocators.sx`) stays bare-visible while a namespaced-only type
(reached solely over a namespace edge) does not. The gate applies ONLY to a
TOP-LEVEL author (`module_decls`) — a LOCAL type / generic-param / fabricated
empty-struct stub is findByName-registered but authored in no module, so it
resolves ungated and byte-identically (its own diagnostics still fire). The
compiler-synthesized default-Context emission falls open (`CAllocator` is
infrastructure, independent of the program's import style). The closure walk
lives in lower.zig, so resolver.zig keeps its single graph-walk.
A namespaced callee's declared return type now resolves in the callee's own
module context (`resolveTypeInSource` over `qualified_fn_source`) — a `Value`
returned by `json.parse` is visible inside `json.sx`, not at the call site
(issue-0100-F1 source-pin analog).
Migrates 0719 (flat-imports `cli` for its types, keeps `cli` namespaced for the
same-name `cli.parse`). Adds 0743 (bare ns-only struct → not visible) and 0744
(bare ns-only enum → not visible) regressions. 0742 (ns-only const) + 0210
(generics stay legacy) unchanged. readme updated.
Gate: zig build / zig build test (LSP sweep, no crash) / run_examples 481/0;
m3te ios-sim exit 0; 0743/0744 fail-before on 7cd12b0 (compiled, no diagnostic)
/ pass-after (clean "not visible").
This commit is contained in:
@@ -12,6 +12,14 @@
|
||||
// independent identities.
|
||||
|
||||
#import "modules/std.sx";
|
||||
// `cli` is imported BOTH flat (so its types — `FlagSpec` / `Command` / `Diag` —
|
||||
// are bare-visible) AND namespaced (so the same-name `cli.parse` stays a
|
||||
// distinct qualified identity from `json.parse`). Post-E1 a bare reference to a
|
||||
// namespaced-ONLY type is a "not visible" error, so the flat import is what makes
|
||||
// the bare type names below resolve; `json` stays namespaced-only (its `Value`
|
||||
// reaches `main` only as `json.parse`'s return type, resolved in `json.sx`'s own
|
||||
// context).
|
||||
#import "modules/std/cli.sx";
|
||||
cli :: #import "modules/std/cli.sx";
|
||||
json :: #import "modules/std/json.sx";
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Bare TYPE visibility under a NAMESPACED-only import — the struct sibling of
|
||||
// 0736 (bare call) and 0742 (bare const), and the core of the source-aware
|
||||
// nominal leaf (Phase E1). `dep.sx` is imported only as `dep :: #import`, so its
|
||||
// top-level `Secret` struct is reachable ONLY as `dep.Secret`. A BARE `Secret`
|
||||
// in a type position must NOT resolve: bare-TYPE visibility joins over the FLAT
|
||||
// import edges (`flat_import_graph`, transitively), and a namespaced alias is not
|
||||
// a flat edge. Before the fix the bare type leaked through the global
|
||||
// `findByName` first-match (the leaf returned it ahead of the visibility check),
|
||||
// so `s.x` compiled and ran. The qualified form `dep.Secret` stays the supported
|
||||
// spelling (its member resolution lands fully in Phase F).
|
||||
dep :: #import "0743-modules-namespaced-only-bare-type-not-visible/dep.sx";
|
||||
|
||||
main :: () -> s32 {
|
||||
s : Secret = .{ x = 5, y = 6 };
|
||||
s.x
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Secret :: struct {
|
||||
x: s32;
|
||||
y: s32;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Bare TYPE visibility under a NAMESPACED-only import — the ENUM sibling of 0743
|
||||
// (struct), covering the second registered nominal kind for the source-aware
|
||||
// nominal leaf (Phase E1). `dep.sx` is imported only as `dep :: #import`, so its
|
||||
// top-level `Color` enum is reachable ONLY as `dep.Color`. A BARE `Color` in a
|
||||
// type position must NOT resolve — bare-TYPE visibility joins over the FLAT
|
||||
// import edges, and a namespaced alias is not a flat edge. Before the fix the
|
||||
// bare enum leaked through the global `findByName` first-match.
|
||||
dep :: #import "0744-modules-namespaced-only-bare-enum-not-visible/dep.sx";
|
||||
|
||||
main :: () -> s32 {
|
||||
c : Color = .green;
|
||||
if c == .green { 0 } else { 9 }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
Color :: enum {
|
||||
red;
|
||||
green;
|
||||
blue;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: type 'Secret' is not visible; #import the module that declares it
|
||||
--> examples/0743-modules-namespaced-only-bare-type-not-visible.sx:14:9
|
||||
|
|
||||
14 | s : Secret = .{ x = 5, y = 6 };
|
||||
| ^^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: type 'Color' is not visible; #import the module that declares it
|
||||
--> examples/0744-modules-namespaced-only-bare-enum-not-visible.sx:11:9
|
||||
|
|
||||
11 | c : Color = .green;
|
||||
| ^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user