Skip to content

Commit

Permalink
Fixed bug that results in a false positive error under certain circum…
Browse files Browse the repository at this point in the history
…stances involving a call to a higher-order generic function with another function that involves a class with a contravariant type variable. This addresses #7212.
  • Loading branch information
erictraut committed May 31, 2024
1 parent 0e42a7e commit e69974c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
9 changes: 6 additions & 3 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23480,7 +23480,10 @@ export function createTypeEvaluator(
// rather than dest. If the type variable is not in the scope of the
// provided TypeVarContext, simply verify that the concrete types are
// compatible.
if (!srcTypeVarContext || !srcTypeVarContext.hasSolveForScope(getTypeVarScopeId(srcType))) {
if (
(flags & AssignTypeFlags.IgnoreTypeVarScope) === 0 &&
(!srcTypeVarContext || !srcTypeVarContext.hasSolveForScope(getTypeVarScopeId(srcType)))
) {
return assignType(
makeTopLevelTypeVarsConcrete(destType),
makeTopLevelTypeVarsConcrete(srcType),
Expand All @@ -23497,7 +23500,7 @@ export function createTypeEvaluator(
srcType,
destType,
diag,
srcTypeVarContext,
srcTypeVarContext ?? new TypeVarContext(),
originalFlags,
recursionCount
)
Expand All @@ -23515,7 +23518,7 @@ export function createTypeEvaluator(
srcType as TypeVarType,
destSubtype,
diag,
srcTypeVarContext,
srcTypeVarContext ?? new TypeVarContext(),
originalFlags,
recursionCount
)
Expand Down
26 changes: 26 additions & 0 deletions packages/pyright-internal/src/tests/samples/solverHigherOrder12.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This sample tests the case involving a higher-order function and a
# class that uses a contravariant type variable.

from collections.abc import Callable
from typing import TypeVar, Generic

T = TypeVar("T", contravariant=True)
A = TypeVar("A")
B = TypeVar("B")
C = TypeVar("C")


class ClassA(Generic[T]):
pass


def func1(c: Callable[[A], None], v: A):
pass


def func2(c: ClassA[B]) -> None:
pass


def func3(c: ClassA[int]):
func1(func2, c)
6 changes: 6 additions & 0 deletions packages/pyright-internal/src/tests/typeEvaluator2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,12 @@ test('SolverHigherOrder11', () => {
TestUtils.validateResults(analysisResults, 0);
});

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

TestUtils.validateResults(analysisResults, 0);
});

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

Expand Down

0 comments on commit e69974c

Please sign in to comment.