FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[mypyc] Invalid C for an int-annotated parameter rebound via nonlocal with --allow-redefinition-new · Issue #22221 · python/mypy · GitHub

Repository navigation

[mypyc] Invalid C for an int-annotated parameter rebound via nonlocal with --allow-redefinition-new #22221

Open

Description

Bug Report

With --allow-redefinition-new, mypyc generates invalid C when a nested function rebinds, through nonlocal, a parameter of the enclosing function that is annotated int. The outer function stores the unboxed int parameter straight into the closure environment's PyObject * slot. gcc rejects the C, and an MSVC build compiles with a warning and segfaults at run time.

To Reproduce

def f(n: int):
    def inner():
        nonlocal n
        n = n - 1
        return n
    return inner()

print(f(3))
python -m mypyc --allow-redefinition-new repro.py

Expected Behavior

It builds and prints 2, as it does without --allow-redefinition-new.

Actual Behavior

On Linux (gcc 14.2.0):

build/__native.c:541:49: error: assignment to 'PyObject *' {aka 'struct _object *'} from 'CPyTagged' {aka 'long unsigned int'} makes pointer from integer without a cast [-Wint-conversion]

The generated code, in f:

    CPy_INCREF(cpy_r_n);
    if (((repro___f_envObject *)cpy_r_r0)->_n != NULL) {
        CPy_DECREF(((repro___f_envObject *)cpy_r_r0)->_n);
    }
    ((repro___f_envObject *)cpy_r_r0)->_n = cpy_r_n;

On Windows (MSVC, Python 3.14.6) the build succeeds and importing the module segfaults.

The same happens when the nested function is a generator or an async def. It does not happen when:

  • the variable is a local of the enclosing function (n = 3 in its body) rather than a parameter, even with an unannotated nested function;
  • the parameter is unannotated or annotated Any;
  • the variable is a str rather than an int;
  • --allow-redefinition-new is left off.

Annotating the nested function avoids it only in some cases. def inner() -> int: builds, but this still fails with the nested function annotated:

from typing import Any

def f(n: int, acc: int):
    def inner(k) -> Any:
        nonlocal n, acc
        while n > 0:
            acc = acc + k
            n = n - 1
        return acc
    return inner(2)

print(f(3, 0))

Your Environment

  • Mypy version used: 2.4.0, and master at 9f5e075
  • Mypy command-line flags: --allow-redefinition-new (mypyc)
  • Mypy configuration options: none
  • Python version used: 3.12.13 (Linux), 3.14.6 (Windows)
  • Operating system and version: Debian (the python:3.12 Docker image, gcc 14.2.0); Windows 11 with MSVC

Found while compiling the output of Pyfun, a language that compiles to Python and offers mypyc builds; its generated code relies on --allow-redefinition-new.

Activity

  1. changed the title [-][mypyc] Invalid C for an int rebound via nonlocal in an unannotated nested function with --allow-redefinition-new[/-] [+][mypyc] Invalid C for an int-annotated parameter rebound via nonlocal with --allow-redefinition-new[/+] on Oct 17, 2026
  2. simontreanor commented on Oct 17, 2026

    Author

    I've corrected the description. The trigger is a parameter of the enclosing function annotated int, not an unannotated nested function. A local variable of the enclosing function never reproduced it, and annotating the nested function doesn't reliably avoid it: the description now includes an annotated example that still fails. Checked on 2.4.0 and master at 9f5e075.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL