issue 0151 RESOLVED: infer generic $T through generic-struct / pointer / UFCS-pack params
The generic-inference engine could not bind a $T from a generic-struct argument head. Four gaps, all on the inference + UFCS dispatch path: - extractTypeParam / matchTypeParam(Static) gained a parameterized_type_expr arm: recover the arg instance's recorded per-param bindings (struct_instance_bindings + the template's ordered type_params via struct_instance_author) and recurse positionally, so $T binds from Box($T) <=> Box(i64) like it does from []$T <=> []i64. This also fixes the pointer case — *Box($T) recurses into its Box($T) pointee. - The pointer_type_expr arm now falls through to match the pointee against a non-pointer arg (auto-address-of: a *Box($T) param accepts a by-value Box($T), e.g. the UFCS receiver b.m()). - ExprTyper.inferType gained a .lambda arm building the closure type from the lambda's annotations, so the UFCS binder (which types args from the raw AST before they are lowered) can bind a Closure(..) -> $R from the worker's declared return type. - A pack UFCS target (worker: Closure(..) -> $R, ..$args) now routes through the same lowerPackFnCall the direct call uses, with the receiver spliced in as args[0] (lowerPackFnCall reads only call_node.args, never the callee). Regression tests: examples/0214 (direct + UFCS closure-return pack) and examples/0215 (by-value / pointer / multi-param / nested / UFCS-auto-ref generic-struct-head inference). Suite green 728/0.
This commit is contained in:
26
examples/0214-generics-ufcs-closure-return-pack.sx
Normal file
26
examples/0214-generics-ufcs-closure-return-pack.sx
Normal file
@@ -0,0 +1,26 @@
|
||||
// Generic inference where `$R` comes from a worker closure's RETURN type
|
||||
// through a variadic `..$args` pack — both the DIRECT spelling
|
||||
// `mymk(bx, worker, 40, 2)` and the UFCS dot-call `bx.mymk(worker, 40, 2)`
|
||||
// resolve `$R = i64` identically and build `Wrap($R)` correctly.
|
||||
// Regression (issue 0151): the UFCS path used to splice the receiver as
|
||||
// arg 0 without running the direct path's pack/closure-return binding, so
|
||||
// `$R` stayed `.unresolved` and SIGTRAPped at LLVM emission.
|
||||
#import "modules/std.sx";
|
||||
|
||||
Box :: struct { n: i64; }
|
||||
Wrap :: struct ($R: Type) { value: R; }
|
||||
|
||||
mymk :: ufcs (b: Box, worker: Closure(..$args) -> $R, ..$args) -> Wrap($R) {
|
||||
f : Wrap($R) = ---;
|
||||
f.value = worker(..args);
|
||||
return f;
|
||||
}
|
||||
|
||||
main :: () -> i32 {
|
||||
bx : Box = .{ n = 1 };
|
||||
direct := mymk(bx, (a: i64, b: i64) -> i64 => a + b, 40, 2);
|
||||
ufcs := bx.mymk((a: i64, b: i64) -> i64 => a + b, 40, 2);
|
||||
print("direct={}\n", direct.value);
|
||||
print("ufcs={}\n", ufcs.value);
|
||||
return 0;
|
||||
}
|
||||
29
examples/0215-generics-infer-through-pointer.sx
Normal file
29
examples/0215-generics-infer-through-pointer.sx
Normal file
@@ -0,0 +1,29 @@
|
||||
// Generic `$T` inferred through a generic-struct argument head — both
|
||||
// by-value (`Box($T)`) and pointer-wrapped (`*Box($T)`), the latter also
|
||||
// via a UFCS dot-call (auto-address-of receiver). Multi-param heads
|
||||
// (`Pair($A, $B)`) and nested heads (`Box(Box($T))`) bind positionally.
|
||||
// Regression (issue 0151, widened): `extractTypeParam` had no
|
||||
// `parameterized_type_expr` arm, so `$T` never bound from a generic-struct
|
||||
// param — the call failed with "cannot infer generic type parameter 'T'".
|
||||
#import "modules/std.sx";
|
||||
|
||||
Box :: struct ($T: Type) { v: T; }
|
||||
Pair :: struct ($A: Type, $B: Type) { a: A; b: B; }
|
||||
|
||||
unbox :: (b: *Box($T)) -> $T { return b.v; } // infer through `*`
|
||||
byval :: (b: Box($T)) -> $T { return b.v; } // infer through head
|
||||
second :: (p: Pair($A, $B)) -> $B { return p.b; } // 2nd of two params
|
||||
nested :: (b: Box(Box($T))) -> $T { return b.v.v; } // nested head
|
||||
get :: ufcs (b: *Box($T)) -> $T { return b.v; } // UFCS auto-ref
|
||||
|
||||
main :: () -> i32 {
|
||||
b : Box(i64) = .{ v = 42 };
|
||||
p : Pair(i64, f64) = .{ a = 1, b = 2.5 };
|
||||
nb : Box(Box(i64)) = .{ v = .{ v = 9 } };
|
||||
print("unbox={}\n", unbox(@b));
|
||||
print("byval={}\n", byval(b));
|
||||
print("second={}\n", second(p));
|
||||
print("nested={}\n", nested(nb));
|
||||
print("ufcs={}\n", b.get());
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
direct=42
|
||||
ufcs=42
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
unbox=42
|
||||
byval=42
|
||||
second=2.500000
|
||||
nested=9
|
||||
ufcs=42
|
||||
Reference in New Issue
Block a user