Fixed bug that results in false positive error under certain circumstances that involve unions of TypeVars in an invariant context. This addresses #6957. (#7709)

This commit is contained in:
Eric Traut 2024-04-15 23:09:21 -07:00 committed by GitHub
parent 8a7aed5983
commit 8912c884ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 23 deletions

View File

@ -24187,22 +24187,36 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
} else if (remainingDestSubtypes.length === remainingSrcSubtypes.length) {
// If the number of remaining source subtypes is the same as the number
// of dest TypeVars, try to assign each source subtype to its own dest TypeVar.
remainingDestSubtypes.forEach((destSubtype, index) => {
const srcSubtype = remainingSrcSubtypes[index];
if (
!assignType(
destSubtype,
srcSubtype,
diag?.createAddendum(),
destTypeVarContext,
srcTypeVarContext,
flags,
recursionCount
)
) {
canUseFastPath = false;
const reorderedDestSubtypes = [...remainingDestSubtypes];
for (let srcIndex = 0; srcIndex < remainingSrcSubtypes.length; srcIndex++) {
let foundMatchForSrc = false;
for (let destIndex = 0; destIndex < reorderedDestSubtypes.length; destIndex++) {
if (
assignType(
reorderedDestSubtypes[destIndex],
remainingSrcSubtypes[srcIndex],
diag?.createAddendum(),
destTypeVarContext,
srcTypeVarContext,
flags,
recursionCount
)
) {
foundMatchForSrc = true;
// Move the matched dest TypeVar to the end of the list so the other
// dest TypeVars have a better chance of being assigned to.
reorderedDestSubtypes.push(...reorderedDestSubtypes.splice(destIndex, 1));
break;
}
}
});
if (!foundMatchForSrc) {
canUseFastPath = false;
break;
}
}
// We can avoid checking the source subtypes that have already been checked.
sortedSrcTypes = remainingSrcSubtypes;

View File

@ -6,6 +6,7 @@ from typing import AnyStr, Generic, Iterable, Iterator, Protocol, TypeAlias, Typ
V = TypeVar("V")
V_co = TypeVar("V_co", covariant=True)
T = TypeVar("T")
U = TypeVar("U")
@ -30,24 +31,28 @@ def func1(a: ClassA[V], b: ClassA[U], c: bool) -> ClassB[V | U]:
return r
class ClassC(Generic[AnyStr]):
...
class ClassC(Generic[AnyStr]): ...
class ClassD(Iterator[ClassC[AnyStr]], Protocol):
...
class ClassD(Iterator[ClassC[AnyStr]], Protocol): ...
GenericPath: TypeAlias = AnyStr | PathLike[AnyStr]
def func2(iter: Iterable[object]) -> bool:
...
def func2(iter: Iterable[object]) -> bool: ...
def func3(path: GenericPath[AnyStr]) -> ClassD[AnyStr]:
...
def func3(path: GenericPath[AnyStr]) -> ClassD[AnyStr]: ...
def func4(val: str):
func2(func3(val))
def func5(a: dict[T, U], b: list[T | U]):
pass
def func6(a: dict[str, int], b: list[str | int]):
func5(a, b)