Handle mixed and omitted forwarded arguments - #434
Conversation
|
Thanks! Overall it looks good to me, but it's a fairly large change, so I'd like a bit more time to review it properly. Please give me a few days. I'll try to get to it within this week. |
Differentiate `...` calls from bare `super` forwarding so we can drop omitted placeholders without breaking full-argument forwarding. Also add scenarios for mixed forwarding, `super(...)`, and the no-diagnostic case, and move the extra-positional forwarding case out of known issues. Co-authored-by: Codex <codex@openai.com>
ca95ac7 to
a78023d
Compare
|
Sorry for sitting on this for so long! I have to admit I couldn't get my head around the whole thing, but overall it looks good. One thing though: class B
def foo(a, b: 1) = [a, b]
end
class C < B
def foo(a, b: 2) = super
end
C.new.foo(1, b: "s")I have a fix for this locally, so let me merge this first and then send that as a separate PR. Again, I'm really sorry for saying I'd look at it within the week and then leaving it for four months! |
Follow-up to #434. `build_keyword_args` dropped an optional keyword whose vertex was empty, but it runs during install, when every vertex is still empty and no dependency edge is registered, so the keyword was never forwarded at all. The reject was there to keep the named keywords out of the `**rest` hash; do that in a box instead, which also keeps the rest's own fields. class B def foo(a, b: 1) = [a, b] end class C < B def foo(a, b: 2) = super end C.new.foo(1, b: "s") # B#foo's b: Integer -> Integer | String
Follow-up to #434. `build_keyword_args` dropped an optional keyword whose vertex was empty, but it runs during install, when every vertex is still empty and no dependency edge is registered, so the keyword was never forwarded at all. The reject was there to keep the named keywords out of the `**rest` hash; do that in a box instead, which also keeps the rest's own fields. class B def foo(a, b: 1) = [a, b] end class C < B def foo(a, b: 2) = super end C.new.foo(1, b: "s") # B#foo's b: Integer -> Integer | String
Summary
This updates forwarding argument handling for omitted and mixed
...calls.The main issue was that omitted forwarded arguments were still represented by placeholder values early enough to participate in method-call resolution. That had two effects:
...calls could produce false arity diagnostics before the forwarding site was activated by actual argumentsfoo(x, ...)andsuper(x, ...)were hard to model correctly, because the forwarded remainder was not clearly separated from explicit leading argumentsApproach
This keeps the existing
ForwardingArgumentsmodel, but refines how forwarded arguments are materialized at call sites.There are now two distinct forwarding modes:
supercontinues to forward the full argument set...calls materialize only the forwarded remainder, and only after activation from actual argumentsWith that split, explicit leading arguments can still be prepended at the call site, while omitted placeholders no longer leak into method-call resolution too early.
This is intended to be a local refinement of forwarding behavior, not a redesign of the overall forwarding model.
Implementation Notes
A few parts of the diff are larger than they may look at first glance:
@forwarding_arguments = :restis used to distinguish omitted...forwarding from the existing full-forwarding behavior used by baresuperast/method.rbnow prepares dedicated forwarding placeholders for optional/rest/keyword/block forwarding, instead of reusing the method's formal argument vertices directlyForwardingActualArgumentsexists to represent forwarded actual arguments that may still be omitted until activation, and to normalize them before method-call resolutionThat extra structure is mainly there to avoid encoding the behavior as scattered special cases at call sites.
Changes
...calls from baresuperforwardingsuperfoo(x, ...)andsuper(x, ...)super(...)Notes
The intent here is to keep the current forwarding design intact as much as possible, while making omitted forwarding behave like "forward the remaining arguments" at the call site.
In particular, this change tries to make the mixed cases work without changing the overall role of
ForwardingArgumentsin method definition and argument propagation.