lang: generic $R type-arg resolution + receiver-driven ufcs overload (issues 0156, 0157)
0156 Part 1: a single-type generic $R (parsed as comptime_pack_ref) used as a type-arg in a pack-fn body (Box($R), size_of(Box($R))) hit a missing arm in resolveTypeWithBindings -> .unresolved -> LLVM panic. Fix: mirror resolveTypeArg's comptime_pack_ref arm (look up type_bindings, else a loud diagnostic). Regression: examples/generics/0216. (Part 2 -- deferred .. spread crashes -- reframed OPEN/non-blocking.) 0157: a user generic ufcs method whose name collides with a stdlib re-export resolved via last-wins fn_ast_map with no receiver filtering, so the wrong overload won, $R never bound, and .unresolved reached LLVM. Fix: selectUfcsGenericByReceiver enumerates all module authors, keeps the receiver-binding ones, picks the most receiver-specific (concrete > bare $T), dedups re-exports, and flags a genuine tie as a deterministic 'ambiguous -- qualify' diagnostic. Regression: examples/generics/0217.
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
// A user generic ufcs method whose name collides with a stdlib re-export must
|
||||
// resolve by RECEIVER TYPE, not last-wins. `cancel` here is also re-exported by
|
||||
// std.sx (io.sx's `cancel :: ufcs (f: *Future($R))`); calling `(@x).cancel()` on
|
||||
// a `*Box(i64)` must pick the user's `cancel(*Box($R))` and bind `$R := i64`.
|
||||
//
|
||||
// Regression (issue 0157): UFCS dispatch resolved the name via a single
|
||||
// last-wins `fn_ast_map` entry with no receiver filtering, so the stdlib
|
||||
// `*Future($R)` overload won, `$R` never bound, and `.unresolved` reached LLVM
|
||||
// → panic. Fixed by selecting the most receiver-specific binding author across
|
||||
// all module authors (src/ir/lower/call.zig `selectUfcsGenericByReceiver`).
|
||||
#import "modules/std.sx";
|
||||
|
||||
Box :: struct ($R: Type) { value: R; flag: i64; }
|
||||
|
||||
// Same name as std.sx's re-exported `cancel` (generic ufcs over `*Future($R)`),
|
||||
// but a different receiver — the receiver type disambiguates.
|
||||
cancel :: ufcs (b: *Box($R)) { b.flag = 1; }
|
||||
|
||||
main :: () -> i64 {
|
||||
x : Box(i64) = ---; x.value = 7; x.flag = 0;
|
||||
(@x).cancel(); // resolves to the user `cancel` by receiver type
|
||||
print("{}\n", x.flag); // 1
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user