From 162c74d2af77070c6983e0f97fcb593eda4d29d1 Mon Sep 17 00:00:00 2001 From: Richard Si Date: Wed, 28 Feb 2024 11:52:42 -0500 Subject: [PATCH] [mypyc] Remangle redefined names produced by async with (#16408) Fixes mypyc/mypyc#1001. --------- Co-authored-by: Jelle Zijlstra --- mypyc/irbuild/builder.py | 7 ++++--- mypyc/test-data/run-async.test | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 9d160b08505d..69f3ad9c495f 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -1246,14 +1246,15 @@ def add_var_to_env_class( ) -> AssignmentTarget: # First, define the variable name as an attribute of the environment class, and then # construct a target for that attribute. - self.fn_info.env_class.attributes[var.name] = rtype - attr_target = AssignmentTargetAttr(base.curr_env_reg, var.name) + name = remangle_redefinition_name(var.name) + self.fn_info.env_class.attributes[name] = rtype + attr_target = AssignmentTargetAttr(base.curr_env_reg, name) if reassign: # Read the local definition of the variable, and set the corresponding attribute of # the environment class' variable to be that value. reg = self.read(self.lookup(var), self.fn_info.fitem.line) - self.add(SetAttr(base.curr_env_reg, var.name, reg, self.fn_info.fitem.line)) + self.add(SetAttr(base.curr_env_reg, name, reg, self.fn_info.fitem.line)) # Override the local definition of the variable to instead point at the variable in # the environment class. diff --git a/mypyc/test-data/run-async.test b/mypyc/test-data/run-async.test index 85ad172d61df..8488632e6574 100644 --- a/mypyc/test-data/run-async.test +++ b/mypyc/test-data/run-async.test @@ -143,3 +143,31 @@ async def foo() -> AsyncIterable[int]: yields, val = run_generator(async_iter(foo())) assert yields == (0,1,2), yields assert val == 'lol no', val + +[case testAsyncWithVarReuse] +class ConMan: + async def __aenter__(self) -> int: + return 1 + async def __aexit__(self, *exc: object): + pass + +class ConManB: + async def __aenter__(self) -> int: + return 2 + async def __aexit__(self, *exc: object): + pass + +async def x() -> None: + value = 2 + async with ConMan() as f: + value += f + assert value == 3, value + async with ConManB() as f: + value += f + assert value == 5, value + +[typing fixtures/typing-full.pyi] +[file driver.py] +import asyncio +import native +asyncio.run(native.x())