|
33 | 33 | Type, AnyType, CallableType, FunctionLike, Overloaded, TupleType, TypedDictType, |
34 | 34 | Instance, NoneTyp, strip_type, TypeType, |
35 | 35 | UnionType, TypeVarId, TypeVarType, PartialType, DeletedType, UninhabitedType, TypeVarDef, |
36 | | - true_only, false_only, function_type, is_named_instance |
| 36 | + true_only, false_only, function_type, is_named_instance, union_items |
37 | 37 | ) |
38 | 38 | from mypy.sametypes import is_same_type, is_same_types |
39 | 39 | from mypy.messages import MessageBuilder |
@@ -817,44 +817,45 @@ def check_overlapping_op_methods(self, |
817 | 817 | # of x in __radd__ would not be A, the methods could be |
818 | 818 | # non-overlapping. |
819 | 819 |
|
820 | | - if isinstance(forward_type, CallableType): |
821 | | - # TODO check argument kinds |
822 | | - if len(forward_type.arg_types) < 1: |
823 | | - # Not a valid operator method -- can't succeed anyway. |
824 | | - return |
| 820 | + for forward_item in union_items(forward_type): |
| 821 | + if isinstance(forward_item, CallableType): |
| 822 | + # TODO check argument kinds |
| 823 | + if len(forward_item.arg_types) < 1: |
| 824 | + # Not a valid operator method -- can't succeed anyway. |
| 825 | + return |
825 | 826 |
|
826 | | - # Construct normalized function signatures corresponding to the |
827 | | - # operator methods. The first argument is the left operand and the |
828 | | - # second operand is the right argument -- we switch the order of |
829 | | - # the arguments of the reverse method. |
830 | | - forward_tweaked = CallableType( |
831 | | - [forward_base, forward_type.arg_types[0]], |
832 | | - [nodes.ARG_POS] * 2, |
833 | | - [None] * 2, |
834 | | - forward_type.ret_type, |
835 | | - forward_type.fallback, |
836 | | - name=forward_type.name) |
837 | | - reverse_args = reverse_type.arg_types |
838 | | - reverse_tweaked = CallableType( |
839 | | - [reverse_args[1], reverse_args[0]], |
840 | | - [nodes.ARG_POS] * 2, |
841 | | - [None] * 2, |
842 | | - reverse_type.ret_type, |
843 | | - fallback=self.named_type('builtins.function'), |
844 | | - name=reverse_type.name) |
845 | | - |
846 | | - if is_unsafe_overlapping_signatures(forward_tweaked, |
847 | | - reverse_tweaked): |
848 | | - self.msg.operator_method_signatures_overlap( |
849 | | - reverse_class.name(), reverse_name, |
850 | | - forward_base.type.name(), forward_name, context) |
851 | | - elif isinstance(forward_type, Overloaded): |
852 | | - for item in forward_type.items(): |
853 | | - self.check_overlapping_op_methods( |
854 | | - reverse_type, reverse_name, reverse_class, |
855 | | - item, forward_name, forward_base, context) |
856 | | - elif not isinstance(forward_type, AnyType): |
857 | | - self.msg.forward_operator_not_callable(forward_name, context) |
| 827 | + # Construct normalized function signatures corresponding to the |
| 828 | + # operator methods. The first argument is the left operand and the |
| 829 | + # second operand is the right argument -- we switch the order of |
| 830 | + # the arguments of the reverse method. |
| 831 | + forward_tweaked = CallableType( |
| 832 | + [forward_base, forward_item.arg_types[0]], |
| 833 | + [nodes.ARG_POS] * 2, |
| 834 | + [None] * 2, |
| 835 | + forward_item.ret_type, |
| 836 | + forward_item.fallback, |
| 837 | + name=forward_item.name) |
| 838 | + reverse_args = reverse_type.arg_types |
| 839 | + reverse_tweaked = CallableType( |
| 840 | + [reverse_args[1], reverse_args[0]], |
| 841 | + [nodes.ARG_POS] * 2, |
| 842 | + [None] * 2, |
| 843 | + reverse_type.ret_type, |
| 844 | + fallback=self.named_type('builtins.function'), |
| 845 | + name=reverse_type.name) |
| 846 | + |
| 847 | + if is_unsafe_overlapping_signatures(forward_tweaked, |
| 848 | + reverse_tweaked): |
| 849 | + self.msg.operator_method_signatures_overlap( |
| 850 | + reverse_class.name(), reverse_name, |
| 851 | + forward_base.type.name(), forward_name, context) |
| 852 | + elif isinstance(forward_item, Overloaded): |
| 853 | + for item in forward_item.items(): |
| 854 | + self.check_overlapping_op_methods( |
| 855 | + reverse_type, reverse_name, reverse_class, |
| 856 | + item, forward_name, forward_base, context) |
| 857 | + elif not isinstance(forward_item, AnyType): |
| 858 | + self.msg.forward_operator_not_callable(forward_name, context) |
858 | 859 |
|
859 | 860 | def check_inplace_operator_method(self, defn: FuncBase) -> None: |
860 | 861 | """Check an inplace operator method such as __iadd__. |
|
0 commit comments