From 8750ac28f9298ebbd29297622fe5e60ec79c2436 Mon Sep 17 00:00:00 2001 From: Charan Rathore <180254320+charan-rathore@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:10:49 +0530 Subject: [PATCH 1/3] mypyc: use widened param types for native signatures Updated argument type retrieval in fdef_to_sig to use variable types instead of declared types, addressing issue #22221. --- mypyc/irbuild/mapper.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index 523c718c9b867..b0e535dd8757b 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -181,9 +181,15 @@ def get_arg_rtype(self, typ: Type, kind: ArgKind) -> RType: def fdef_to_sig(self, fdef: FuncDef, strict_dunders_typing: bool) -> FuncSignature: if isinstance(fdef.type, CallableType): + # Use the parameter variable's type rather than the declared Callable arg + # type: under --allow-redefinition-new the variable type is widened to the + # join of the declaration and every redefinition, and the local register + # (and any closure environment attribute) is created with that wider type. + # Keeping the declared type here would make the native signature narrower + # than the register that actually receives the argument (#22221). arg_types = [ - self.get_arg_rtype(typ, kind) - for typ, kind in zip(fdef.type.arg_types, fdef.type.arg_kinds) + self.get_arg_rtype(arg.variable.type or typ, kind) + for arg, typ, kind in zip(fdef.arguments, fdef.type.arg_types, fdef.type.arg_kinds) ] arg_pos_onlys = [name is None for name in fdef.type.arg_names] ret = self.type_to_rtype(fdef.type.ret_type) From 268939441d425628a04057ce70cbe2563ce71003 Mon Sep 17 00:00:00 2001 From: Charan Rathore <180254320+charan-rathore@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:11:51 +0530 Subject: [PATCH 2/3] mypyc: test native signature of a redefined param Add a test case to verify widening of native signatures under redefinition. --- mypyc/test/test_irbuild.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/mypyc/test/test_irbuild.py b/mypyc/test/test_irbuild.py index 0dc19b62a60fb..8d4bf1d7f590f 100644 --- a/mypyc/test/test_irbuild.py +++ b/mypyc/test/test_irbuild.py @@ -4,17 +4,20 @@ import os.path import sys +import unittest from mypy.errors import CompileError from mypy.test.config import test_temp_dir from mypy.test.data import DataDrivenTestCase from mypyc.common import TOP_LEVEL_NAME from mypyc.ir.pprint import format_func +from mypy.nodes import FuncDef from mypyc.test.testutil import ( ICODE_GEN_BUILTINS, MypycDataSuite, assert_test_output, build_ir_for_single_file, + build_ir_for_single_file2, infer_ir_build_options_from_test_name, remove_comment_lines, replace_word_size, @@ -104,3 +107,30 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: actual.extend(format_func(fn)) assert_test_output(testcase, actual, "Invalid source code output", expected_output) + + +class TestRedefinedParamSignature(unittest.TestCase): + def test_widens_native_signature(self) -> None: + """The native signature must use the (possibly widened) parameter variable type. + + Under --allow-redefinition the variable's type is the join of the + declaration and every redefinition. The local argument register and any + closure environment attribute use that wider type, so a narrower + signature derived from the declared Callable type generates invalid C + when the argument is stored (https://github.com/python/mypy/issues/22221). + """ + source = [ + "# flags: --allow-redefinition", + "def f(n: int):", + " def inner():", + " nonlocal n", + " n = n - 1", + " return n", + " return inner()", + ] + module, tree, _, mapper = build_ir_for_single_file2(source) + fdef = tree.defs[0] + assert isinstance(fdef, FuncDef) + sig = mapper.func_to_decl[fdef].sig + assert sig.args[0].name == "n" + assert str(sig.args[0].type) == "union[int, object]" From ec7ddf3836394a9fd47c046eb8b4a641c1114718 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2026 14:45:55 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypyc/test/test_irbuild.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/test/test_irbuild.py b/mypyc/test/test_irbuild.py index 8d4bf1d7f590f..f91ded9a675fe 100644 --- a/mypyc/test/test_irbuild.py +++ b/mypyc/test/test_irbuild.py @@ -7,11 +7,11 @@ import unittest from mypy.errors import CompileError +from mypy.nodes import FuncDef from mypy.test.config import test_temp_dir from mypy.test.data import DataDrivenTestCase from mypyc.common import TOP_LEVEL_NAME from mypyc.ir.pprint import format_func -from mypy.nodes import FuncDef from mypyc.test.testutil import ( ICODE_GEN_BUILTINS, MypycDataSuite,