Skip to content

[mypyc] Fix spilling values with overlapping error values #18961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions mypyc/test-data/run-async.test
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,96 @@ def test_stolen() -> None:
[file asyncio/__init__.pyi]
def run(x: object) -> object: ...
async def sleep(t: float) -> None: ...

[case testRunAsyncMiscTypesInEnvironment]
import asyncio

from mypy_extensions import i64, i32, i16, u8

async def inc_float(x: float) -> float:
return x + 1.0

async def inc_i64(x: i64) -> i64:
return x + 1

async def inc_i32(x: i32) -> i32:
return x + 1

async def inc_i16(x: i16) -> i16:
return x + 1

async def inc_u8(x: u8) -> u8:
return x + 1

async def inc_tuple(x: tuple[i64, float]) -> tuple[i64, float]:
return x[0] + 1, x[1] + 1.5

async def neg_bool(b: bool) -> bool:
return not b

async def float_ops(x: float) -> float:
n = x
n = await inc_float(n)
n = float("0.5") + await inc_float(n)
return n

def test_float() -> None:
assert asyncio.run(float_ops(2.5)) == 5.0

async def i64_ops(x: i64) -> i64:
n = x
n = await inc_i64(n)
n = i64("1") + await inc_i64(n)
return n

def test_i64() -> None:
assert asyncio.run(i64_ops(2)) == 5

async def i32_ops(x: i32) -> i32:
n = x
n = await inc_i32(n)
n = i32("1") + await inc_i32(n)
return n

def test_i32() -> None:
assert asyncio.run(i32_ops(3)) == 6

async def i16_ops(x: i16) -> i16:
n = x
n = await inc_i16(n)
n = i16("1") + await inc_i16(n)
return n

def test_i16() -> None:
assert asyncio.run(i16_ops(4)) == 7

async def u8_ops(x: u8) -> u8:
n = x
n = await inc_u8(n)
n = u8("1") + await inc_u8(n)
return n

def test_u8() -> None:
assert asyncio.run(u8_ops(5)) == 8

async def tuple_ops(x: tuple[i64, float]) -> tuple[i64, float]:
n = x
n = await inc_tuple(n)
m = ((i64("1"), float("0.5")), await inc_tuple(n))
return m[1]

def test_tuple() -> None:
assert asyncio.run(tuple_ops((1, 2.5))) == (3, 5.5)

async def bool_ops(x: bool) -> bool:
n = x
n = await neg_bool(n)
m = (bool("1"), await neg_bool(n))
return m[0] and m[1]

def test_bool() -> None:
assert asyncio.run(bool_ops(True)) is True
assert asyncio.run(bool_ops(False)) is False

[file asyncio/__init__.pyi]
def run(x: object) -> object: ...
4 changes: 4 additions & 0 deletions mypyc/transform/spill.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ def spill_regs(
for i, val in enumerate(to_spill):
name = f"{TEMP_ATTR_NAME}2_{i}"
env.attributes[name] = val.type
if val.type.error_overlap:
# We can safely treat as always initialized, since the type has no pointers.
# This way we also don't need to manage the defined attribute bitfield.
env._always_initialized_attrs.add(name)
spill_locs[val] = name

for block in blocks:
Expand Down