Skip to content

Commit

Permalink
Fixed a recent regression that results in false positive errors under…
Browse files Browse the repository at this point in the history
… certain circumstances that involve assignability checks for two callables that involve a `*args: *tuple[]` parameter. This addresses #9238.
  • Loading branch information
erictraut committed Oct 19, 2024
1 parent 2915f5a commit 166c1cd
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 7 deletions.
11 changes: 8 additions & 3 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25711,6 +25711,7 @@ export function createTypeEvaluator(
}
} else if (
destParam.kind !== ParamKind.Positional &&
destParam.kind !== ParamKind.ExpandedArgs &&
srcParam.kind === ParamKind.Positional &&
srcParamDetails.kwargsIndex === undefined &&
!srcParamDetails.params.some(
Expand Down Expand Up @@ -25853,8 +25854,10 @@ export function createTypeEvaluator(
canAssign = false;
}

const destParamKind = destParamDetails.params[paramIndex].kind;
if (
destParamDetails.params[paramIndex].kind !== ParamKind.Positional &&
destParamKind !== ParamKind.Positional &&
destParamKind !== ParamKind.ExpandedArgs &&
srcParamDetails.kwargsIndex === undefined
) {
diag?.addMessage(
Expand Down Expand Up @@ -25966,7 +25969,8 @@ export function createTypeEvaluator(
if (
param.param.name &&
param.param.category === ParamCategory.Simple &&
param.kind !== ParamKind.Positional
param.kind !== ParamKind.Positional &&
param.kind !== ParamKind.ExpandedArgs
) {
destParamMap.set(param.param.name, param);
}
Expand Down Expand Up @@ -26854,7 +26858,8 @@ export function createTypeEvaluator(
) {
if (
!FunctionParam.isNameSynthesized(baseParam) &&
baseParamDetails.params[i].kind !== ParamKind.Positional
baseParamDetails.params[i].kind !== ParamKind.Positional &&
baseParamDetails.params[i].kind !== ParamKind.ExpandedArgs
) {
diag?.addMessage(
LocAddendum.overrideParamNamePositionOnly().format({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2888,7 +2888,11 @@ export class CompletionProvider {
const paramDetails = getParamListDetails(type);

paramDetails.params.forEach((paramInfo) => {
if (paramInfo.param.name && paramInfo.kind !== ParamKind.Positional) {
if (
paramInfo.param.name &&
paramInfo.kind !== ParamKind.Positional &&
paramInfo.kind !== ParamKind.ExpandedArgs
) {
if (!SymbolNameUtils.isPrivateOrProtectedName(paramInfo.param.name)) {
names.add(paramInfo.param.name);
}
Expand Down
3 changes: 0 additions & 3 deletions packages/pyright-internal/src/tests/samples/tupleUnpack2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
# it uses the * syntax instead of the backward compatibility
# "Unpack" form.

from typing import Union


def func1(v1: tuple[int, *tuple[bool, bool], str]):
reveal_type(v1, expected_text="tuple[int, bool, bool, str]")

Expand Down
29 changes: 29 additions & 0 deletions packages/pyright-internal/src/tests/samples/tupleUnpack5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This sample tests cases where an unpacked tuple is used in
# an overload.


from typing import Callable, Concatenate, overload


@overload
def func1[**P, R](func: Callable[P, R], /, *args: *tuple[()]) -> Callable[P, R]: ...
@overload
def func1[**P, R](
func: Callable[Concatenate[int, P], R], /, *args: *tuple[int]
) -> Callable[P, R]: ...
@overload
def func1[**P, R](
func: Callable[Concatenate[int, int, P], R], /, *args: *tuple[int, int]
) -> Callable[P, R]: ...


def func1[**P, R](func: Callable[..., R], /, *args: object) -> Callable[..., R]: ...


@overload
def func2(*args: *tuple[int]) -> int: ...
@overload
def func2(*args: *tuple[int, int, int]) -> int: ...


def func2(*args: *tuple[int, *tuple[int, ...]]) -> int: ...
5 changes: 5 additions & 0 deletions packages/pyright-internal/src/tests/typeEvaluator8.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,11 @@ test('TupleUnpack4', () => {
TestUtils.validateResults(analysisResults1, 2);
});

test('TupleUnpack5', () => {
const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['tupleUnpack5.py']);
TestUtils.validateResults(analysisResults1, 0);
});

test('PseudoGeneric1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['pseudoGeneric1.py']);

Expand Down

0 comments on commit 166c1cd

Please sign in to comment.