Fixed a bug that results in incorrect type evaluation for a higher-order function involving a ParamSpec. This addresses #5409. (#5469)

Co-authored-by: Eric Traut <erictr@microsoft.com>
This commit is contained in:
Eric Traut 2023-07-12 00:09:23 +02:00 committed by GitHub
parent 9791786314
commit bc89399c9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 1 deletions

View File

@ -807,6 +807,7 @@ function assignTypeToParamSpec(
FunctionType.addParameter(newFunction, param);
});
newFunction.details.typeVarScopeId = srcType.details.typeVarScopeId;
newFunction.details.paramSpecTypeVarScopeId = srcType.details.paramSpecTypeVarScopeId;
newFunction.details.docString = srcType.details.docString;
newFunction.details.paramSpec = srcType.details.paramSpec;
typeVarContext.setTypeVarType(destType, newFunction);

View File

@ -10968,7 +10968,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
const liveTypeVarScopes = ParseTreeUtils.getTypeVarScopesForNode(errorNode);
const srcTypeVarContext = new TypeVarContext(paramSpecType.details.typeVarScopeId);
const srcTypeVarContext = new TypeVarContext(getTypeVarScopeIds(paramSpecType));
let reportedArgError = false;
// Build a map of all named parameters.

View File

@ -0,0 +1,27 @@
# This sample tests the case where a higher-order function involves a ParamSpec.
from typing import TypeVar, Callable, Protocol, ParamSpec
P = ParamSpec("P")
R = TypeVar("R", covariant=True)
T = TypeVar("T")
class Proto1(Protocol[P, R]):
@classmethod
def collect(cls, *args: P.args, **kwargs: P.kwargs) -> R:
...
class Class1:
@classmethod
def collect(cls, n: type[T]) -> Callable[[Callable[[T], int]], None]:
...
def func1(a: Proto1[P, R], *args: P.args, **kwargs: P.kwargs) -> R:
...
reveal_type(func1(Class1, float), expected_text="((float) -> int) -> None")
reveal_type(func1(Class1, int), expected_text="((int) -> int) -> None")

View File

@ -719,6 +719,12 @@ test('SolverHigherOrder7', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('SolverHigherOrder8', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['solverHigherOrder8.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('SolverLiteral1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['solverLiteral1.py']);