Skip to content

Commit 20fa54a

Browse files
authored
[mypyc] Remangle names produced by allow-redefinition (#11175)
Fixes mypyc/mypyc#702 by replacing "'" with "__redef__", although this assumes nothing else will ever use demangling for now. Only locals need any fix; a run testcase was added to verify that it works already for globals, and since the fix for locals is on the ir level only an ir testcase is added.
1 parent 904e4c0 commit 20fa54a

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

mypyc/irbuild/builder.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,12 @@ def add_local(self, symbol: SymbolNode, typ: RType, is_arg: bool = False) -> 'Re
10661066
is_arg: is this a function argument
10671067
"""
10681068
assert isinstance(symbol, SymbolNode)
1069-
reg = Register(typ, symbol.name, is_arg=is_arg, line=symbol.line)
1069+
reg = Register(
1070+
typ,
1071+
remangle_redefinition_name(symbol.name),
1072+
is_arg=is_arg,
1073+
line=symbol.line,
1074+
)
10701075
self.symtables[-1][symbol] = AssignmentTargetRegister(reg)
10711076
if is_arg:
10721077
self.builder.args.append(reg)
@@ -1203,3 +1208,14 @@ def get_default() -> Value:
12031208
GetAttr(builder.fn_info.callable_class.self_reg, name, arg.line))
12041209
assert isinstance(target, AssignmentTargetRegister)
12051210
builder.assign_if_null(target.register, get_default, arg.initializer.line)
1211+
1212+
1213+
def remangle_redefinition_name(name: str) -> str:
1214+
"""Remangle names produced by mypy when allow-redefinition is used and a name
1215+
is used with multiple types within a single block.
1216+
1217+
We only need to do this for locals, because the name is used as the name of the register;
1218+
for globals, the name itself is stored in a register for the purpose of doing dict
1219+
lookups.
1220+
"""
1221+
return name.replace("'", "__redef__")

mypyc/test-data/irbuild-basic.test

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3745,3 +3745,27 @@ L3:
37453745
goto L1
37463746
L4:
37473747
return 1
3748+
[case testLocalRedefinition]
3749+
# mypy: allow-redefinition
3750+
def f() -> None:
3751+
i = 0
3752+
i += 1
3753+
i = "foo"
3754+
i += i
3755+
i = 0.0
3756+
[out]
3757+
def f():
3758+
i, r0 :: int
3759+
r1, i__redef__, r2 :: str
3760+
r3, i__redef____redef__ :: float
3761+
L0:
3762+
i = 0
3763+
r0 = CPyTagged_Add(i, 2)
3764+
i = r0
3765+
r1 = 'foo'
3766+
i__redef__ = r1
3767+
r2 = CPyStr_Append(i__redef__, i__redef__)
3768+
i__redef__ = r2
3769+
r3 = 0.0
3770+
i__redef____redef__ = r3
3771+
return 1

mypyc/test-data/run-misc.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,3 +1089,14 @@ class A:
10891089
class B(A):
10901090
def _(arg): pass
10911091
def _(arg): pass
1092+
1093+
[case testGlobalRedefinition_toplevel]
1094+
# mypy: allow-redefinition
1095+
i = 0
1096+
i += 1
1097+
i = "foo"
1098+
i += i
1099+
i = b"foo"
1100+
1101+
def test_redefinition() -> None:
1102+
assert i == b"foo"

0 commit comments

Comments
 (0)