mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-03 19:37:39 +03:00
Fixed bug that results in a false negative when passing an extra keyword argument to a callable that is parameterized with a ParamSpec. This addresses #8294. (#8299)
This commit is contained in:
parent
280ed52e8c
commit
8a766d59a4
@ -10867,25 +10867,36 @@ export function createTypeEvaluator(
|
||||
paramSpecArgList.push(argList[argIndex]);
|
||||
} else if (paramDetails.kwargsIndex !== undefined) {
|
||||
const paramType = paramDetails.params[paramDetails.kwargsIndex].type;
|
||||
validateArgTypeParams.push({
|
||||
paramCategory: ParameterCategory.KwargsDict,
|
||||
paramType,
|
||||
requiresTypeVarMatching: requiresSpecialization(paramType),
|
||||
argument: argList[argIndex],
|
||||
errorNode: argList[argIndex].valueExpression ?? errorNode,
|
||||
paramName: paramNameValue,
|
||||
});
|
||||
if (isParamSpec(paramType)) {
|
||||
if (!canSkipDiagnosticForNode(errorNode) && !isTypeIncomplete) {
|
||||
addDiagnostic(
|
||||
DiagnosticRule.reportCallIssue,
|
||||
LocMessage.paramNameMissing().format({ name: paramName.value }),
|
||||
paramName
|
||||
);
|
||||
}
|
||||
reportedArgError = true;
|
||||
} else {
|
||||
validateArgTypeParams.push({
|
||||
paramCategory: ParameterCategory.KwargsDict,
|
||||
paramType,
|
||||
requiresTypeVarMatching: requiresSpecialization(paramType),
|
||||
argument: argList[argIndex],
|
||||
errorNode: argList[argIndex].valueExpression ?? errorNode,
|
||||
paramName: paramNameValue,
|
||||
});
|
||||
|
||||
// Remember that this parameter has already received a value.
|
||||
paramMap.set(paramNameValue, {
|
||||
argsNeeded: 1,
|
||||
argsReceived: 1,
|
||||
isPositionalOnly: false,
|
||||
});
|
||||
assert(
|
||||
paramDetails.params[paramDetails.kwargsIndex],
|
||||
'paramDetails.kwargsIndex params entry is undefined'
|
||||
);
|
||||
// Remember that this parameter has already received a value.
|
||||
paramMap.set(paramNameValue, {
|
||||
argsNeeded: 1,
|
||||
argsReceived: 1,
|
||||
isPositionalOnly: false,
|
||||
});
|
||||
assert(
|
||||
paramDetails.params[paramDetails.kwargsIndex],
|
||||
'paramDetails.kwargsIndex params entry is undefined'
|
||||
);
|
||||
}
|
||||
trySetActive(argList[argIndex], paramDetails.params[paramDetails.kwargsIndex].param);
|
||||
} else {
|
||||
if (!canSkipDiagnosticForNode(errorNode) && !isTypeIncomplete) {
|
||||
|
@ -35,11 +35,13 @@ async def func2():
|
||||
|
||||
|
||||
@overload
|
||||
def func3(x: int) -> None: ...
|
||||
def func3(x: int) -> None:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def func3(x: str) -> str: ...
|
||||
def func3(x: str) -> str:
|
||||
...
|
||||
|
||||
|
||||
def func3(x: int | str) -> str | None:
|
||||
@ -73,7 +75,8 @@ def decorator2(f: Callable[P, R]) -> Callable[P, R]:
|
||||
|
||||
|
||||
def func5(f: Callable[[], list[T1]]) -> Callable[[list[T2]], list[T1 | T2]]:
|
||||
def inner(res: list[T2], /) -> list[T1 | T2]: ...
|
||||
def inner(res: list[T2], /) -> list[T1 | T2]:
|
||||
...
|
||||
|
||||
return decorator2(inner)
|
||||
|
||||
@ -87,18 +90,22 @@ def func6(x: Iterable[Callable[P, None]]) -> Callable[P, None]:
|
||||
|
||||
|
||||
class Callback1:
|
||||
def __call__(self, x: int | str, y: int = 3) -> None: ...
|
||||
def __call__(self, x: int | str, y: int = 3) -> None:
|
||||
...
|
||||
|
||||
|
||||
class Callback2:
|
||||
def __call__(self, x: int, /) -> None: ...
|
||||
def __call__(self, x: int, /) -> None:
|
||||
...
|
||||
|
||||
|
||||
class Callback3:
|
||||
def __call__(self, *args, **kwargs) -> None: ...
|
||||
def __call__(self, *args, **kwargs) -> None:
|
||||
...
|
||||
|
||||
|
||||
def func7(f1: Callable[P, R], f2: Callable[P, R]) -> Callable[P, R]: ...
|
||||
def func7(f1: Callable[P, R], f2: Callable[P, R]) -> Callable[P, R]:
|
||||
...
|
||||
|
||||
|
||||
def func8(cb1: Callback1, cb2: Callback2, cb3: Callback3):
|
||||
@ -107,3 +114,8 @@ def func8(cb1: Callback1, cb2: Callback2, cb3: Callback3):
|
||||
|
||||
v2 = func7(cb1, cb3)
|
||||
reveal_type(v2, expected_text="(x: int | str, y: int = 3) -> None")
|
||||
|
||||
|
||||
def func9(f: Callable[P, object], *args: P.args, **kwargs: P.kwargs) -> object:
|
||||
# This should generate an error because "name" doesn't exist.
|
||||
return f(*args, **kwargs, name="")
|
||||
|
@ -558,7 +558,7 @@ test('ParamSpec2', () => {
|
||||
|
||||
test('ParamSpec3', () => {
|
||||
const results = TestUtils.typeAnalyzeSampleFiles(['paramSpec3.py']);
|
||||
TestUtils.validateResults(results, 1);
|
||||
TestUtils.validateResults(results, 2);
|
||||
});
|
||||
|
||||
test('ParamSpec4', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user