fix(lower): free-fn UFCS auto-address-of + lazy lowering (issue 0063)
A free function called via UFCS (recv.fn(args)) whose first param is *T was passed the receiver by value (LLVM "Call parameter type does not match function signature"), and a function reached only via UFCS was declared but never emitted (undefined symbol at link). The bare-name UFCS fallback now mirrors the qualified-method path: it lazily lowers the target body and calls fixupMethodReceiver + coerceCallArgs, so the value receiver gets the same implicit address-of as a struct-defined method and mutations through *T are visible. Regression: 0039-basic-free-fn-ufcs-pointer-receiver.sx.
This commit is contained in:
@@ -7444,11 +7444,26 @@ pub const Lowering = struct {
|
||||
}
|
||||
}
|
||||
|
||||
// Try to resolve as bare function name (method)
|
||||
// Try to resolve as bare function name (free-function UFCS:
|
||||
// `recv.fn(args)` → `fn(recv, args)`). Lazily lower the body —
|
||||
// a function reached ONLY via UFCS would otherwise be declared
|
||||
// but never emitted (issue 0063: undefined symbol at link).
|
||||
if (self.fn_ast_map.get(fa.field)) |_| {
|
||||
if (!self.lowered_functions.contains(fa.field)) {
|
||||
self.lazyLowerFunction(fa.field);
|
||||
}
|
||||
}
|
||||
if (self.resolveFuncByName(fa.field)) |fid| {
|
||||
const func = &self.module.functions.items[@intFromEnum(fid)];
|
||||
const ret_ty = func.ret;
|
||||
const params = func.params;
|
||||
// Same implicit address-of as a struct-defined method: if the
|
||||
// free function's first param is `*T` and the receiver is a
|
||||
// value `T`, pass its address instead of a by-value copy
|
||||
// (issue 0063).
|
||||
self.fixupMethodReceiver(&method_args, func, effective_obj_node, obj_ty);
|
||||
const final_args = self.prependCtxIfNeeded(func, method_args.items);
|
||||
self.coerceCallArgs(final_args, params);
|
||||
return self.builder.call(fid, final_args, ret_ty);
|
||||
}
|
||||
return self.emitError(fa.field, c.callee.span);
|
||||
|
||||
Reference in New Issue
Block a user