GeezerVison is showing github.com — Multiple inheritance considers callable objects as subtypes of functi… · python/mypy@a7a995a
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: mypy/checker.py +8-1Lines changed: 8 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -2485,7 +2485,14 @@ class C(B, A[int]): ... # this is unsafe because... | 2485 | 2485 | first_type = get_proper_type(self.determine_type_of_member(first)) | 2486 | 2486 | second_type = get_proper_type(self.determine_type_of_member(second)) | 2487 | 2487 |
| 2488 | | - if isinstance(first_type, FunctionLike) and isinstance(second_type, FunctionLike): | | 2488 | + # start with the special case that Instance can be a subtype of FunctionLike | | 2489 | + call = None | | 2490 | + if isinstance(first_type, Instance): | | 2491 | + call = find_member("__call__", first_type, first_type, is_operator=True) | | 2492 | + if call and isinstance(second_type, FunctionLike): | | 2493 | + second_sig = self.bind_and_map_method(second, second_type, ctx, base2) | | 2494 | + ok = is_subtype(call, second_sig, ignore_pos_arg_names=True) | | 2495 | + elif isinstance(first_type, FunctionLike) and isinstance(second_type, FunctionLike): | 2489 | 2496 | if first_type.is_type_obj() and second_type.is_type_obj(): | 2490 | 2497 | # For class objects only check the subtype relationship of the classes, | 2491 | 2498 | # since we allow incompatible overrides of '__init__'/'__new__' | |
Collapse file Copy file name to clipboardExpand all lines: test-data/unit/check-multiple-inheritance.test +38Lines changed: 38 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -668,3 +668,41 @@ class D1(B[str], C1): ... | 668 | 668 | class D2(B[Union[int, str]], C2): ... | 669 | 669 | class D3(C2, B[str]): ... | 670 | 670 | class D4(B[str], C2): ... # E: Definition of "foo" in base class "A" is incompatible with definition in base class "C2" | | 671 | + | | 672 | + | | 673 | +[case testMultipleInheritanceOverridingOfFunctionsWithCallableInstances] | | 674 | +from typing import Any, Callable | | 675 | + | | 676 | +def dec1(f: Callable[[Any, int], None]) -> Callable[[Any, int], None]: ... | | 677 | + | | 678 | +class F: | | 679 | + def __call__(self, x: int) -> None: ... | | 680 | + | | 681 | +def dec2(f: Callable[[Any, int], None]) -> F: ... | | 682 | + | | 683 | +class B1: | | 684 | + def f(self, x: int) -> None: ... | | 685 | + | | 686 | +class B2: | | 687 | + @dec1 | | 688 | + def f(self, x: int) -> None: ... | | 689 | + | | 690 | +class B3: | | 691 | + @dec2 | | 692 | + def f(self, x: int) -> None: ... | | 693 | + | | 694 | +class B4: | | 695 | + f = F() | | 696 | + | | 697 | +class C12(B1, B2): ... | | 698 | +class C13(B1, B3): ... # E: Definition of "f" in base class "B1" is incompatible with definition in base class "B3" | | 699 | +class C14(B1, B4): ... # E: Definition of "f" in base class "B1" is incompatible with definition in base class "B4" | | 700 | +class C21(B2, B1): ... | | 701 | +class C23(B2, B3): ... # E: Definition of "f" in base class "B2" is incompatible with definition in base class "B3" | | 702 | +class C24(B2, B4): ... # E: Definition of "f" in base class "B2" is incompatible with definition in base class "B4" | | 703 | +class C31(B3, B1): ... | | 704 | +class C32(B3, B2): ... | | 705 | +class C34(B3, B4): ... | | 706 | +class C41(B4, B1): ... | | 707 | +class C42(B4, B2): ... | | 708 | +class C43(B4, B3): ... |
|