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:
@@ -1033,6 +1033,25 @@ pub fn lowerCall(self: *Lowering, c_in: *const ast.Call) Ref {
|
||||
d.addFmt(.err, c.callee.span, "'{s}' is ambiguous; declared by multiple imported modules — qualify the call", .{fa.field});
|
||||
return Ref.none;
|
||||
}
|
||||
// A pack ufcs target (`worker: Closure(..) -> $R, ..$args`):
|
||||
// route through the SAME pack-call path the direct call uses,
|
||||
// with the receiver spliced in as the first arg so the pack
|
||||
// boundary, the `$R` closure-return binding, and the pack
|
||||
// expansion all line up with `fd.params[0]` (issue 0151).
|
||||
// `lowerPackFnCall` reads only `call_node.args` (never the
|
||||
// callee), so a synthetic spliced-args call is sufficient.
|
||||
if (ufcs_fd) |fd| {
|
||||
if (isPackFn(fd)) {
|
||||
// `lowerPackFnCall` only READS these nodes; the const-cast
|
||||
// back to `*Node` (Call.args' element type) is sound.
|
||||
var syn_args = std.ArrayList(*Node).empty;
|
||||
defer syn_args.deinit(self.alloc);
|
||||
syn_args.append(self.alloc, @constCast(effective_obj_node)) catch unreachable;
|
||||
for (c.args) |a| syn_args.append(self.alloc, a) catch unreachable;
|
||||
const syn_call = ast.Call{ .callee = c.callee, .args = syn_args.items };
|
||||
return self.lowerPackFnCall(fd, &syn_call);
|
||||
}
|
||||
}
|
||||
// Generic ufcs target: monomorphize with the receiver's AST
|
||||
// node prepended so bindings align with fd.params[0].
|
||||
if (ufcs_fd) |fd| {
|
||||
|
||||
Reference in New Issue
Block a user