CallPlan collapsed two different field-access dispatches onto namespace_fn: a true namespace call (`pkg.fn()`, no receiver) and free-function UFCS (`c.bump()`, receiver prepended + `*T` fixup). Return typing was preserved either way, but sub-step 3 could not consume the plan — it would have had to re-classify the AST to decide whether to prepend the receiver. Add a distinct `free_fn_ufcs` kind and a plan(c) branch, inserted after the struct-method block and gated on `objectIsValue` (the negation of lowerCall's `is_namespace`: a non-identifier receiver is always a value; an identifier/type_expr is a value iff it names a local or a global). The branch sets prepends_receiver = true and reads prepends_ctx from the resolved FuncId (best-effort, like direct_fn). namespace_fn now means strictly "receiver is a namespace/type prefix". New test `plan: free-function UFCS prepends receiver, distinct from namespace_fn` covers a scope-bound `c.bump()` against a lowered free fn: asserts free_fn_ufcs kind, func target, prepends_receiver, prepends_ctx, and preserved s32 return type. zig build, zig build test, tests/run_examples.sh (357/0) all green; return typing unchanged.
22 KiB
22 KiB