Skip to content

Commit e7b1c7a

Browse files
committed
Fixed a bug that led to a false negative when determining whether two base classes that are combined using multiple inheritance implement the same method in an incompatible way. The bug caused the check to be skipped if the child class also implemented the same method as the two base classes. This addresses python/mypy#15790.
1 parent 567bbc2 commit e7b1c7a

File tree

3 files changed

+9
-5
lines changed

3 files changed

+9
-5
lines changed

packages/pyright-internal/src/analyzer/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5177,7 +5177,7 @@ export class Checker extends ParseTreeWalker {
51775177
return getClassFieldsRecursive(specializedBaseClass);
51785178
});
51795179

5180-
const childClassSymbolMap = getClassFieldsRecursive(classType);
5180+
const childClassSymbolMap = getClassFieldsRecursive(classType, /* skipInitialClass */ true);
51815181

51825182
for (let symbolMapBaseIndex = 1; symbolMapBaseIndex < baseClassSymbolMaps.length; symbolMapBaseIndex++) {
51835183
const baseSymbolMap = baseClassSymbolMaps[symbolMapBaseIndex];

packages/pyright-internal/src/analyzer/typeUtils.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1464,11 +1464,15 @@ export function* getClassIterator(classType: Type, flags = ClassIteratorFlags.De
14641464
return undefined;
14651465
}
14661466

1467-
export function getClassFieldsRecursive(classType: ClassType): Map<string, ClassMember> {
1467+
export function getClassFieldsRecursive(classType: ClassType, skipInitialClass = false): Map<string, ClassMember> {
14681468
const memberMap = new Map<string, ClassMember>();
14691469

14701470
// Evaluate the types of members from the end of the MRO to the beginning.
14711471
ClassType.getReverseMro(classType).forEach((mroClass) => {
1472+
if (skipInitialClass && isClass(mroClass) && ClassType.isSameGenericClass(mroClass, classType)) {
1473+
return;
1474+
}
1475+
14721476
const specializedMroClass = partiallySpecializeType(mroClass, classType);
14731477

14741478
if (isClass(specializedMroClass)) {

packages/pyright-internal/src/tests/samples/methodOverride3.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
# This functionality is controlled by the reportIncompatibleMethodOverride
33
# diagnostic rule.
44

5-
6-
from typing import Generic, Iterable, ParamSpec, TypeVar
5+
from typing import Any, Generic, Iterable, ParamSpec, TypeVar
76

87

98
class A1:
@@ -18,7 +17,8 @@ def func1(self, a: int, b: int = 3) -> str:
1817

1918
# This should generate an error because func1 is incompatible.
2019
class ASub(A1, A2):
21-
...
20+
def func1(self, *args: Any, **kwargs: Any) -> str:
21+
...
2222

2323

2424
class B1:

0 commit comments

Comments
 (0)