Skip to content

Commit

Permalink
[mypyc] Fix generated __ne__ to work if __eq__ returns NotImplemented
Browse files Browse the repository at this point in the history
  • Loading branch information
msullivan committed Nov 2, 2019
1 parent 4b5f33d commit 04e02a9
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 10 deletions.
22 changes: 17 additions & 5 deletions mypyc/genops.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def f(x: int) -> int:
check_stop_op, send_op, yield_from_except_op, coro_op,
py_getattr_op, py_setattr_op, py_delattr_op, py_hasattr_op,
py_call_op, py_call_with_kwargs_op, py_method_call_op,
fast_isinstance_op, bool_op, new_slice_op,
fast_isinstance_op, bool_op, new_slice_op, not_implemented_op,
type_op, pytype_from_template_op, import_op, get_module_dict_op,
ellipsis_op, method_new_op, type_is_op, type_object_op, py_calc_meta_op,
dataclass_sleight_of_hand,
Expand Down Expand Up @@ -1794,12 +1794,24 @@ def gen_glue_ne_method(self, cls: ClassIR, line: int) -> FuncIR:
fake_vars = [(Var(arg.name), arg.type) for arg in rt_args]
args = [self.read(self.environment.add_local_reg(var, type, is_arg=True), line)
for var, type in fake_vars] # type: List[Value]
self.ret_types[-1] = bool_rprimitive

retval = self.add(MethodCall(args[0], '__eq__', [args[1]], line))
retval = self.unary_op(retval, 'not', line)
self.ret_types[-1] = object_rprimitive

not_implemented_block, regular_block = BasicBlock(), BasicBlock()
eqval = self.add(MethodCall(args[0], '__eq__', [args[1]], line))
not_implemented = self.primitive_op(not_implemented_op, [], line)
self.add(Branch(
self.binary_op(eqval, not_implemented, 'is', line),
not_implemented_block,
regular_block,
Branch.BOOL_EXPR))

self.activate_block(regular_block)
retval = self.coerce(self.unary_op(eqval, 'not', line), object_rprimitive, line)
self.add(Return(retval))

self.activate_block(not_implemented_block)
self.add(Return(not_implemented))

blocks, env, ret_type, _ = self.leave()
return FuncIR(
FuncDecl('__ne__', cls.name, self.module_name,
Expand Down
10 changes: 5 additions & 5 deletions mypyc/ops_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
emit=name_emit('Py_Ellipsis'),
is_borrowed=True)

name_ref_op(name='builtins.NotImplemented',
result_type=object_rprimitive,
error_kind=ERR_NEVER,
emit=name_emit('Py_NotImplemented'),
is_borrowed=True)
not_implemented_op = name_ref_op(name='builtins.NotImplemented',
result_type=object_rprimitive,
error_kind=ERR_NEVER,
emit=name_emit('Py_NotImplemented'),
is_borrowed=True)

func_op(name='builtins.id',
arg_types=[object_rprimitive],
Expand Down
6 changes: 6 additions & 0 deletions mypyc/test-data/run.test
Original file line number Diff line number Diff line change
Expand Up @@ -3300,6 +3300,10 @@ class BoxedThing:
class Subclass2(BoxedThing):
pass

class UsesNotImplemented:
def __eq__(self, b: object) -> bool:
return NotImplemented

def index_into(x : Any, y : Any) -> Any:
return x[y]

Expand Down Expand Up @@ -3345,6 +3349,8 @@ assert is_truthy(Item('a'))
assert not is_truthy(Subclass1(''))
assert is_truthy(Subclass1('a'))

assert UsesNotImplemented() != object()

internal_index_into()
[out]
7 7
Expand Down

0 comments on commit 04e02a9

Please sign in to comment.