fix(stdlib/E4): kind-aware type-fn head gate (non-fn must not vouch)
The type-fn head visibility check (`headFnLeak`) used the module-scope NAME predicate `isNameVisible`, so a same-name 1-hop NON-function (a value const `Make :: 123`) reported the name "visible" and let the global `fn_ast_map` type-fn — whose real author is 2 flat hops away — silently instantiate. `size_of(Make(s64))` printed 8 at exit 0 instead of a visibility diagnostic. Decide visibility from the ELIGIBLE FUNCTION authors directly reachable from the use site (`flatFnAuthorVisible`, mirroring `flatFnAuthorAmbiguous`'s fn-only author view): visible iff the own author or a 1-hop flat-import author is a `fn_decl`. A non-function does not vouch. Guarded to fall open when the import facts aren't wired (comptime / directory imports), mirroring `headTypeGate`. Own / scope-local / 1-hop / directly-imported type-fn heads still resolve; 0769 ambiguity unchanged. Regression: examples/0770-modules-type-fn-head-non-transitive (main → b [`Make :: 123` + flat-imports c] → c [`Make :: ($T) -> Type`]); the bare `Make(s64)` head emits "type 'Make' is not visible", exit 1.
This commit is contained in:
23
examples/0770-modules-type-fn-head-non-transitive.sx
Normal file
23
examples/0770-modules-type-fn-head-non-transitive.sx
Normal file
@@ -0,0 +1,23 @@
|
||||
// A type-returning FUNCTION head (`Make(s64)` where `Make :: ($T) -> Type`) is
|
||||
// NON-transitive even when a DIRECT flat import authors the same name as a
|
||||
// NON-function. `main` flat-imports `b.sx`; `b.sx` declares `Make :: 123` (a
|
||||
// value const, not a type-fn) AND flat-imports `c.sx`, whose `Make` IS the
|
||||
// type-returning function. The only TYPE-FN author of `Make` is two flat hops
|
||||
// away (main → b → c), so the bare `Make(s64)` head must emit the
|
||||
// "type 'Make' is not visible" diagnostic and poison — the visible 1-hop
|
||||
// `Make :: 123` const must NOT vouch for it.
|
||||
//
|
||||
// Regression (Phase E4 attempt-7, finding E4-type-fn-head-hidden-by-visible-
|
||||
// nonfn): before `headFnLeak` decided visibility from the ELIGIBLE FUNCTION
|
||||
// authors it used the module-scope NAME predicate (`isNameVisible`), which the
|
||||
// visible non-fn `Make :: 123` satisfied — so the global `fn_ast_map` type-fn
|
||||
// silently instantiated and `size_of(Make(s64))` printed 8 at exit 0 instead of
|
||||
// the visibility diagnostic.
|
||||
|
||||
#import "modules/std.sx";
|
||||
#import "0770-modules-type-fn-head-non-transitive/b.sx";
|
||||
|
||||
main :: () -> s32 {
|
||||
print("size={}\n", size_of(Make(s64)));
|
||||
0
|
||||
}
|
||||
6
examples/0770-modules-type-fn-head-non-transitive/b.sx
Normal file
6
examples/0770-modules-type-fn-head-non-transitive/b.sx
Normal file
@@ -0,0 +1,6 @@
|
||||
// The directly-imported (1-hop) author of the NAME `Make` — but as a value
|
||||
// const, NOT a type-returning function. It flat-imports c.sx (where the real
|
||||
// `Make` type-fn lives, two hops from a file that imports b.sx). A same-name
|
||||
// non-function must not vouch for the 2-hop type-fn head.
|
||||
#import "c.sx";
|
||||
Make :: 123;
|
||||
5
examples/0770-modules-type-fn-head-non-transitive/c.sx
Normal file
5
examples/0770-modules-type-fn-head-non-transitive/c.sx
Normal file
@@ -0,0 +1,5 @@
|
||||
// The real type-returning function `Make`, two flat hops from a file that
|
||||
// imports b.sx. A file importing only b.sx must NOT see this head.
|
||||
Make :: ($T: Type) -> Type {
|
||||
return struct { x: T; };
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: type 'Make' is not visible; #import the module that declares it
|
||||
--> examples/0770-modules-type-fn-head-non-transitive.sx:21:32
|
||||
|
|
||||
21 | print("size={}\n", size_of(Make(s64)));
|
||||
| ^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user