Skip to content

Commit bbca30b

Browse files
authored
[mypyc] Fix spilling values with overlapping error values (#18961)
Update spilling transform for async and generator functions to not require a defined attribute bitfield. We now treat temporary spilled values with overlapping error values as always defined. I'm not sure if this would be safe to do for reference counted values, so we only do this in cases where it's clearly fine.
1 parent 281ee30 commit bbca30b

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

mypyc/test-data/run-async.test

+93
Original file line numberDiff line numberDiff line change
@@ -455,3 +455,96 @@ def test_stolen() -> None:
455455
[file asyncio/__init__.pyi]
456456
def run(x: object) -> object: ...
457457
async def sleep(t: float) -> None: ...
458+
459+
[case testRunAsyncMiscTypesInEnvironment]
460+
import asyncio
461+
462+
from mypy_extensions import i64, i32, i16, u8
463+
464+
async def inc_float(x: float) -> float:
465+
return x + 1.0
466+
467+
async def inc_i64(x: i64) -> i64:
468+
return x + 1
469+
470+
async def inc_i32(x: i32) -> i32:
471+
return x + 1
472+
473+
async def inc_i16(x: i16) -> i16:
474+
return x + 1
475+
476+
async def inc_u8(x: u8) -> u8:
477+
return x + 1
478+
479+
async def inc_tuple(x: tuple[i64, float]) -> tuple[i64, float]:
480+
return x[0] + 1, x[1] + 1.5
481+
482+
async def neg_bool(b: bool) -> bool:
483+
return not b
484+
485+
async def float_ops(x: float) -> float:
486+
n = x
487+
n = await inc_float(n)
488+
n = float("0.5") + await inc_float(n)
489+
return n
490+
491+
def test_float() -> None:
492+
assert asyncio.run(float_ops(2.5)) == 5.0
493+
494+
async def i64_ops(x: i64) -> i64:
495+
n = x
496+
n = await inc_i64(n)
497+
n = i64("1") + await inc_i64(n)
498+
return n
499+
500+
def test_i64() -> None:
501+
assert asyncio.run(i64_ops(2)) == 5
502+
503+
async def i32_ops(x: i32) -> i32:
504+
n = x
505+
n = await inc_i32(n)
506+
n = i32("1") + await inc_i32(n)
507+
return n
508+
509+
def test_i32() -> None:
510+
assert asyncio.run(i32_ops(3)) == 6
511+
512+
async def i16_ops(x: i16) -> i16:
513+
n = x
514+
n = await inc_i16(n)
515+
n = i16("1") + await inc_i16(n)
516+
return n
517+
518+
def test_i16() -> None:
519+
assert asyncio.run(i16_ops(4)) == 7
520+
521+
async def u8_ops(x: u8) -> u8:
522+
n = x
523+
n = await inc_u8(n)
524+
n = u8("1") + await inc_u8(n)
525+
return n
526+
527+
def test_u8() -> None:
528+
assert asyncio.run(u8_ops(5)) == 8
529+
530+
async def tuple_ops(x: tuple[i64, float]) -> tuple[i64, float]:
531+
n = x
532+
n = await inc_tuple(n)
533+
m = ((i64("1"), float("0.5")), await inc_tuple(n))
534+
return m[1]
535+
536+
def test_tuple() -> None:
537+
assert asyncio.run(tuple_ops((1, 2.5))) == (3, 5.5)
538+
539+
async def bool_ops(x: bool) -> bool:
540+
n = x
541+
n = await neg_bool(n)
542+
m = (bool("1"), await neg_bool(n))
543+
return m[0] and m[1]
544+
545+
def test_bool() -> None:
546+
assert asyncio.run(bool_ops(True)) is True
547+
assert asyncio.run(bool_ops(False)) is False
548+
549+
[file asyncio/__init__.pyi]
550+
def run(x: object) -> object: ...

mypyc/transform/spill.py

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def spill_regs(
4545
for i, val in enumerate(to_spill):
4646
name = f"{TEMP_ATTR_NAME}2_{i}"
4747
env.attributes[name] = val.type
48+
if val.type.error_overlap:
49+
# We can safely treat as always initialized, since the type has no pointers.
50+
# This way we also don't need to manage the defined attribute bitfield.
51+
env._always_initialized_attrs.add(name)
4852
spill_locs[val] = name
4953

5054
for block in blocks:

0 commit comments

Comments
 (0)