Files
sx/examples/0764-modules-import-generic-head-non-transitive.sx
agra 4f99fb0d85 fix(stdlib/E4): gate unqualified parameterized type heads non-transitively
attempt-3: extend the E4 single-hop bare-TYPE gate to parameterized type
HEADS (the constructor-head analog of the bare-leaf gate). Before this, the
head lookup hit the global struct_template_map / protocol_ast_map /
fn_ast_map *before* any source-aware visibility check, so a 2-flat-hop
imported generic struct/protocol/type-fn remained bare-visible (e.g.
`Box(s64)` when main imports only b.sx and b.sx imports c.sx).

- headTypeLeak: generic-struct / parameterized-protocol heads use the same
  type-author single-hop model as the bare-leaf gate (moduleTypeAuthor +
  flatTypeAuthorCount + localTypeInSource + nameAuthoredAsTypeAnywhere).
- headFnLeak: type-returning-function heads use single-hop function
  visibility (isNameVisible), exempting scope-local mangled type-fns.
- Gated at every unqualified head site: resolveParameterizedWithBindings,
  resolveTypeCallWithBindings, the scanDecls alias-decl dispatch (poisoning
  the alias with .unresolved on leak), resolveArrayLiteralType, and the
  generic-static-method call path. Namespaced (`ns.Box(..)`) heads are an
  explicit qualified reach and stay exempt. Source-pinned instantiation
  (E3/E4) is preserved, so library-internal heads still resolve where they
  are visible.

Regression: examples/0764-modules-import-generic-head-non-transitive
(2-hop `Box(s64)` -> "type 'Box' is not visible", exit 1; direct #import
resolves). Fails-before on a250964 (printed 3), passes-after.

README: note the non-transitive rule covers parameterized type heads.

Gate: zig build 0, zig build test 0 (LSP 522, 423/423), run_examples
505/0, FFI 12xx/13xx/14xx green, 0706/0763/0544/0105 green & byte-identical,
m3te ios-sim build+launch exit 0.
2026-06-08 12:37:00 +03:00

25 lines
1.1 KiB
Plaintext

// `#import` is non-transitive for a PARAMETERIZED TYPE HEAD (a generic-struct
// constructor like `Box(s64)`), exactly like a bare leaf type (0763) and like
// values/functions (0706): when A imports B and B imports C, A must NOT see C's
// top-level generic type `Box`. This file imports `b.sx` (which imports `c.sx`)
// and instantiates C's generic `Box(s64)` directly — the compiler rejects the
// head with a "type ... is not visible; #import the module that declares it"
// diagnostic, BEFORE instantiating the template.
//
// `b.sx` ↔ `c.sx` together still compile: `b_make`'s `Box(s64)` resolves because
// b.sx directly imports c.sx (the head is one flat hop away there, two from a
// file that imports b.sx).
//
// Regression (Phase E4): before the bare-head gate went single-hop this 2-flat-
// hop generic head was wrongly visible — the head lookup hit the global
// `struct_template_map` before any source-aware visibility check.
#import "modules/std.sx";
#import "0764-modules-import-generic-head-non-transitive/b.sx";
main :: () -> s32 {
x : Box(s64) = .{ v = 3 };
print("{}\n", x.v);
0
}