From 4042841137191800805d535812845b9c8c698309 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Fri, 29 Nov 2024 13:12:28 +0100 Subject: [PATCH] Fixed bug that causes a false positive overlapping overload error when the overload accepts a `Callable[..., T]` form. This addresses #9514. (#9516) --- .../src/analyzer/typeEvaluator.ts | 10 ++++++ .../src/tests/samples/overloadOverlap1.py | 31 +++++++++++++++++++ .../src/tests/typeEvaluator6.test.ts | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index 823f891fe892..79e0873bda2f 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -26416,6 +26416,16 @@ export function createTypeEvaluator( } } + // If we're checking for full overlapping overloads and the source is + // a gradual form, the dest must also be a gradual form. + if ( + (flags & AssignTypeFlags.OverloadOverlap) !== 0 && + FunctionType.isGradualCallableForm(srcType) && + !FunctionType.isGradualCallableForm(destType) + ) { + canAssign = false; + } + // If the source and the dest are using the same ParamSpec, any additional // concatenated parameters must match. if (targetIncludesParamSpec && srcParamSpec?.priv.nameWithScope === destParamSpec?.priv.nameWithScope) { diff --git a/packages/pyright-internal/src/tests/samples/overloadOverlap1.py b/packages/pyright-internal/src/tests/samples/overloadOverlap1.py index 3c602112f261..2ddf67477564 100644 --- a/packages/pyright-internal/src/tests/samples/overloadOverlap1.py +++ b/packages/pyright-internal/src/tests/samples/overloadOverlap1.py @@ -446,3 +446,34 @@ def func28(a: int, /, b: None = ...) -> None: ... @overload def func28(a: int, /) -> bool: ... def func28(a: int, /, b: bool | None = None) -> bool | None: ... + + +class CBProto29(Protocol): + def __call__(self, *args: Any) -> Any: ... + + +@overload +def func29(func: CBProto29) -> None: ... + + +@overload +def func29(func: Callable[..., Any]) -> None: ... + + +def func29(func: Any) -> None: ... + + +class CBProto30(Protocol): + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + + +@overload +def func30(func: CBProto30) -> None: ... + + +@overload +# This should generate an error because this overload will never be used. +def func30(func: Callable[..., Any]) -> None: ... + + +def func30(func: Any) -> None: ... diff --git a/packages/pyright-internal/src/tests/typeEvaluator6.test.ts b/packages/pyright-internal/src/tests/typeEvaluator6.test.ts index b5c8c98db9ca..491b21a5acb0 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator6.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator6.test.ts @@ -113,7 +113,7 @@ test('OverloadOverlap1', () => { configOptions.diagnosticRuleSet.reportOverlappingOverload = 'error'; analysisResults = TestUtils.typeAnalyzeSampleFiles(['overloadOverlap1.py'], configOptions); - TestUtils.validateResults(analysisResults, 14); + TestUtils.validateResults(analysisResults, 15); }); test('TypeGuard1', () => {