Skip to content

Commit f3ab90b

Browse files
authored
Fixed false negative when a keyword parameter in a child class method overrides a method with a **kwargs in the parent and the type is incompatible. This addresses #10815. (#10866)
1 parent c407ded commit f3ab90b

3 files changed

Lines changed: 29 additions & 1 deletion

File tree

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27885,6 +27885,28 @@ export function createTypeEvaluator(
2788527885
);
2788627886
canOverride = false;
2788727887
}
27888+
} else {
27889+
// Base has a **kwargs; ensure the added keyword-only parameter's
27890+
// type is compatible with the base's **kwargs value type.
27891+
const baseKwargsType = baseParamDetails.params[baseParamDetails.kwargsIndex].type;
27892+
if (
27893+
!assignType(
27894+
paramInfo.type,
27895+
baseKwargsType,
27896+
diag?.createAddendum(),
27897+
constraints,
27898+
AssignTypeFlags.Default
27899+
)
27900+
) {
27901+
diag?.addMessage(
27902+
LocAddendum.overrideParamKeywordType().format({
27903+
name: paramInfo.param.name ?? '?',
27904+
baseType: printType(baseKwargsType),
27905+
overrideType: printType(paramInfo.type),
27906+
})
27907+
);
27908+
canOverride = false;
27909+
}
2788827910
}
2788927911
}
2789027912
});

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ def __my_method46__(self, x: int) -> None: ...
146146

147147
def __my_method47__(self, x: int) -> None: ...
148148

149+
def my_method48(self, /, **kwargs: object) -> None: ...
150+
149151

150152
T_ChildClass = TypeVar("T_ChildClass", bound="ChildClass")
151153

@@ -311,6 +313,10 @@ def __my_method46__(self, y: int) -> None: ...
311313
# This should generate an error because of a type mismatch.
312314
def __my_method47__(self, y: str) -> None: ...
313315

316+
# This should generate an error because the keyword-only parameter "x: int"
317+
# is not compatible with the base method's "**kwargs: object".
318+
def my_method48(self, /, *, x: int = 3, **kwargs: object) -> None: ...
319+
314320

315321
class A:
316322
def test(self, t: Sequence[int]) -> Sequence[str]: ...

packages/pyright-internal/src/tests/typeEvaluator3.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ test('MethodOverride1', () => {
946946

947947
configOptions.diagnosticRuleSet.reportIncompatibleMethodOverride = 'error';
948948
analysisResults = TestUtils.typeAnalyzeSampleFiles(['methodOverride1.py'], configOptions);
949-
TestUtils.validateResults(analysisResults, 42);
949+
TestUtils.validateResults(analysisResults, 43);
950950
});
951951

952952
test('MethodOverride2', () => {

0 commit comments

Comments
 (0)