Skip to content

Argument Clinic: generated code contains redundant gotos #113367

Description

@eltoder

Bug report

Bug description:

Generated code for argument parsing contains redundant gotos when there are both positional and keyword-only arguments with default values. Take this example:

/*[clinic input]
test.func -> int

    x: object
    y: object = None
    *
    z: object = None

Test function
[clinic start generated code]*/

This produces

    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
    if (!args) {
        goto exit;
    }
    x = args[0];
    if (!noptargs) {
        goto skip_optional_pos;
    }
    if (args[1]) {
        y = args[1];
        if (!--noptargs) {
            goto skip_optional_pos;
        }
    }
skip_optional_pos:
    if (!noptargs) {
        goto skip_optional_kwonly;
    }
    z = args[2];
skip_optional_kwonly:
    _return_value = test_func_impl(module, x, y, z);

Note that all gotos to skip_optional_pos happen only when !noptargs, but skip_optional_pos first checks the exact same condition and immediately jumps to skip_optional_kwonly. We can remove this double jump and extra check and instead generate simpler code:

    x = args[0];
    if (!noptargs) {
        goto skip_optional;
    }
    if (args[1]) {
        y = args[1];
        if (!--noptargs) {
            goto skip_optional;
        }
    }
    z = args[2];
skip_optional:

This code is generated if z is not keyword-only but a regular positional argument.

In general, it does not seem to make sense to have separate skip_optional_pos and skip_optional_kwonly, since there is no way to tell them apart. We only have the combined number of optional arguments (noptargs), which includes both positional and keyword only. (This is unlike positional-only arguments, where we can also check nargs.)

CC @erlend-aasland @AlexWaygood @serhiy-storchaka

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions