fix: visibility-aware type resolution for protocol method signatures
`registerProtocolDecl` resolved each method's param/return type NAME
through the flat, visibility-unaware `type_bridge.resolveAstType`, so a
type name colliding across modules bound to the wrong author. In the
repro the user's `Event` enum collides with the stdlib `event.Event`
struct (pulled in by `modules/std.sx`): the protocol grabbed the stdlib
struct, typed an inferred `g_plat.one_event()` as a fieldless struct,
bound the `case .key_up:(e)` payload to `.unresolved`, and emitted
"enum literal '.escape' has no destination type to resolve against".
Resolve both param and return types through
`resolveTypeInSource(pd.source_file, …)` — the visibility-aware resolver
pinned to the protocol's own declaring module, keeping the `Self → *void`
short-circuit. Brings the non-parameterized path to parity with
`instantiateParamProtocol` and concrete-fn signatures. No silent default:
not-visible / ambiguous names still diagnose and poison with `.unresolved`.
Closes issue 0132 — the protocol-return case left open by f13f4ab (which
fixed the enum/union/inline/error-set registration class). Regression
test: examples/0417-protocols-protocol-return-name-collision.sx.
This commit is contained in:
44
examples/0417-protocols-protocol-return-name-collision.sx
Normal file
44
examples/0417-protocols-protocol-return-name-collision.sx
Normal file
@@ -0,0 +1,44 @@
|
||||
// Protocol method signatures resolve their param/return type NAMES in the
|
||||
// protocol's OWN declaring module (own-wins visibility), so a bare type name
|
||||
// that collides with a same-name namespaced import binds to the local author.
|
||||
//
|
||||
// Here the user's `Event` enum shares its name with the stdlib
|
||||
// `std/event.sx` `Event :: struct` (pulled in, namespaced as `event`, by
|
||||
// `#import "modules/std.sx"`). `Plat.one_event` returns the user's `Event`;
|
||||
// `ev := g_plat.one_event()` infers that type, so the `case .key_up:(e)`
|
||||
// payload binds a `KeyData` and `.escape` resolves against `Keycode`.
|
||||
//
|
||||
// Regression (issue 0132): `registerProtocolDecl` used to resolve method
|
||||
// signature types through the flat, visibility-UNAWARE `type_bridge`
|
||||
// resolver, which picked the stdlib `event.Event` struct instead — typing
|
||||
// `ev` as a fieldless struct, binding `.unresolved`, and emitting
|
||||
// "enum literal '.escape' has no destination type to resolve against". The
|
||||
// fix pins resolution to `pd.source_file`, mirroring the parameterized-
|
||||
// protocol and concrete-fn signature paths.
|
||||
//
|
||||
// Expect: prints `escape!`, exit 0.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
Keycode :: enum { unknown; escape; enter; }
|
||||
KeyData :: struct { key: Keycode; }
|
||||
Event :: enum { none; key_up: KeyData; }
|
||||
|
||||
Plat :: protocol { one_event :: () -> Event; }
|
||||
|
||||
Impl :: struct { dummy: i64; }
|
||||
impl Plat for Impl {
|
||||
one_event :: (self: *Impl) -> Event { return .key_up(.{ key = .escape }); }
|
||||
}
|
||||
|
||||
main :: () {
|
||||
impl : Impl = .{ dummy = 0 };
|
||||
g_plat : Plat = xx @impl;
|
||||
ev := g_plat.one_event(); // type INFERRED from protocol return
|
||||
if ev == {
|
||||
case .key_up: (e) {
|
||||
// `e` is KeyData (payload of the user's Event), `.escape` a Keycode
|
||||
if e.key == .escape { print("escape!\n"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
escape!
|
||||
Reference in New Issue
Block a user