Skip to content

Commit

Permalink
[mypyc] Fix compilation of unreachable expressions (#10228)
Browse files Browse the repository at this point in the history
Unreachable generator expressions are still failing, but most others work.

Fixes mypyc/mypyc#761.
  • Loading branch information
JukkaL authored Mar 20, 2021
1 parent d3ba896 commit 8aa385e
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 2 deletions.
10 changes: 8 additions & 2 deletions mypyc/irbuild/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
from mypy.types import TupleType, get_proper_type, Instance

from mypyc.common import MAX_SHORT_INT
from mypyc.ir.ops import Value, Register, TupleGet, TupleSet, BasicBlock, Assign, LoadAddress
from mypyc.ir.ops import (
Value, Register, TupleGet, TupleSet, BasicBlock, Assign, LoadAddress, RaiseStandardError
)
from mypyc.ir.rtypes import (
RTuple, object_rprimitive, is_none_rprimitive, int_rprimitive, is_int_rprimitive
)
Expand All @@ -40,7 +42,11 @@


def transform_name_expr(builder: IRBuilder, expr: NameExpr) -> Value:
assert expr.node, "RefExpr not resolved"
if expr.node is None:
builder.add(RaiseStandardError(RaiseStandardError.RUNTIME_ERROR,
"mypyc internal error: should be unreachable",
expr.line))
return builder.none()
fullname = expr.node.fullname
if fullname in builtin_names:
typ, src = builtin_names[fullname]
Expand Down
106 changes: 106 additions & 0 deletions mypyc/test-data/irbuild-unreachable.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Test cases for unreachable expressions

[case testUnreachableMemberExpr]
import sys

def f() -> None:
y = sys.platform == "x" and sys.version_info > (3, 5)
[out]
def f():
r0 :: object
r1 :: str
r2 :: object
r3, r4 :: str
r5 :: int32
r6 :: bit
r7 :: object
r8, r9, r10 :: bit
r11, r12 :: bool
r13 :: object
r14 :: str
r15 :: object
r16 :: tuple[int, int]
r17, r18 :: object
r19, y :: bool
L0:
r0 = sys :: module
r1 = 'platform'
r2 = CPyObject_GetAttr(r0, r1)
r3 = cast(str, r2)
r4 = 'x'
r5 = PyUnicode_Compare(r3, r4)
r6 = r5 == -1
if r6 goto L1 else goto L3 :: bool
L1:
r7 = PyErr_Occurred()
r8 = r7 != 0
if r8 goto L2 else goto L3 :: bool
L2:
r9 = CPy_KeepPropagating()
L3:
r10 = r5 == 0
if r10 goto L5 else goto L4 :: bool
L4:
r11 = r10
goto L6
L5:
r12 = raise RuntimeError('mypyc internal error: should be unreachable')
r13 = box(None, 1)
r14 = 'version_info'
r15 = CPyObject_GetAttr(r13, r14)
r16 = (6, 10)
r17 = box(tuple[int, int], r16)
r18 = PyObject_RichCompare(r15, r17, 4)
r19 = unbox(bool, r18)
r11 = r19
L6:
y = r11
return 1

[case testUnreachableNameExpr]
import sys

def f() -> None:
y = sys.platform == 'x' and foobar
[out]
def f():
r0 :: object
r1 :: str
r2 :: object
r3, r4 :: str
r5 :: int32
r6 :: bit
r7 :: object
r8, r9, r10 :: bit
r11, r12 :: bool
r13 :: object
r14, y :: bool
L0:
r0 = sys :: module
r1 = 'platform'
r2 = CPyObject_GetAttr(r0, r1)
r3 = cast(str, r2)
r4 = 'x'
r5 = PyUnicode_Compare(r3, r4)
r6 = r5 == -1
if r6 goto L1 else goto L3 :: bool
L1:
r7 = PyErr_Occurred()
r8 = r7 != 0
if r8 goto L2 else goto L3 :: bool
L2:
r9 = CPy_KeepPropagating()
L3:
r10 = r5 == 0
if r10 goto L5 else goto L4 :: bool
L4:
r11 = r10
goto L6
L5:
r12 = raise RuntimeError('mypyc internal error: should be unreachable')
r13 = box(None, 1)
r14 = unbox(bool, r13)
r11 = r14
L6:
y = r11
return 1
16 changes: 16 additions & 0 deletions mypyc/test-data/run-misc.test
Original file line number Diff line number Diff line change
Expand Up @@ -1057,3 +1057,19 @@ def test_complex() -> None:
assert 2.5e1000j == eval('2.5e1000j')
assert 2.5e1000j + 3.5e2000 == eval('3.5e2000 + 2.5e1000j')
assert -2.5e1000j == eval('-2.5e1000j')

[case testUnreachableExpressions]
from typing import cast
import sys

A = sys.platform == 'x' and foobar
B = sys.platform == 'x' and sys.foobar
C = sys.platform == 'x' and f(a, -b, 'y') > [c + e, g(y=2)]
C = sys.platform == 'x' and cast(a, b[c])
C = sys.platform == 'x' and (lambda x: y + x)
# TODO: This still doesn't work
# C = sys.platform == 'x' and (x for y in z)

assert not A
assert not B
assert not C
1 change: 1 addition & 0 deletions mypyc/test/test_irbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
'irbuild-strip-asserts.test',
'irbuild-int.test',
'irbuild-vectorcall.test',
'irbuild-unreachable.test',
]


Expand Down

0 comments on commit 8aa385e

Please sign in to comment.