diff --git a/packages/pyright-internal/src/analyzer/checker.ts b/packages/pyright-internal/src/analyzer/checker.ts index 316b1987d..63ae2bf6c 100644 --- a/packages/pyright-internal/src/analyzer/checker.ts +++ b/packages/pyright-internal/src/analyzer/checker.ts @@ -5712,6 +5712,7 @@ export class Checker extends ParseTreeWalker { } /** if it's a dataclass then no further base classes in the MRO can have constructors */ let constructorIsSafe = !this._isDataclassWithGeneratedConstructor(classType); + const uniqueBaseClasses = new Set(); const baseClassesWithPossiblyUncalledConstructors: ClassType[] = []; const isTypedDict = ClassType.isTypedDictClass(classType); const diagAddendum = new DiagnosticAddendum(); @@ -5732,12 +5733,15 @@ export class Checker extends ParseTreeWalker { constructorMethodResult && constructorMethodResult.classType && isClass(constructorMethodResult.classType) && + // prevent the same base class from being checked twice which can happen in diamond inheritance situations + !uniqueBaseClasses.has(constructorMethodResult.classType) && // synthesized dataclass constructors are safe as the runtime machinery seems to account for multiple inheritance moments !( isFunction(constructorMethodResult.type) && FunctionType.isSynthesizedMethod(constructorMethodResult.type) ) ) { + uniqueBaseClasses.add(constructorMethodResult.classType); if (constructorIsSafe) { constructorIsSafe = false; } else { diff --git a/packages/pyright-internal/src/tests/samples/multipleInheritance.py b/packages/pyright-internal/src/tests/samples/multipleInheritance.py index d70efab28..03e58b57d 100644 --- a/packages/pyright-internal/src/tests/samples/multipleInheritance.py +++ b/packages/pyright-internal/src/tests/samples/multipleInheritance.py @@ -57,4 +57,16 @@ class U(A, C): # error @dataclass(init=False) class V(A, C): # no error - ... \ No newline at end of file + ... + +class Up: + def __init__(self): ... + + +class Left(Up): ... + + +class Right(Up): ... + + +class Down(Left, Right): ... # no error \ No newline at end of file