diff --git a/mypyc/genops.py b/mypyc/genops.py index 9ef1e6f5cc579..f26ff481fbc27 100644 --- a/mypyc/genops.py +++ b/mypyc/genops.py @@ -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, @@ -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, diff --git a/mypyc/ops_misc.py b/mypyc/ops_misc.py index 3defbc5dc62e1..f2b4515af6079 100644 --- a/mypyc/ops_misc.py +++ b/mypyc/ops_misc.py @@ -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], diff --git a/mypyc/test-data/run.test b/mypyc/test-data/run.test index 79ffb6d655777..508371dd692ba 100644 --- a/mypyc/test-data/run.test +++ b/mypyc/test-data/run.test @@ -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] @@ -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