Skip to content

Commit

Permalink
Fixed a bug that led to incorrect type narrowing on assignment in cer…
Browse files Browse the repository at this point in the history
…tain cases. This addresses #5757. (#5761)

Co-authored-by: Eric Traut <[email protected]>
  • Loading branch information
erictraut and msfterictraut authored Aug 18, 2023
1 parent 5543a9f commit b9f4615
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
21 changes: 17 additions & 4 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24385,6 +24385,14 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
}
}

// If the declared and assigned types are the same generic type but the assigned type
// contains one or more unknowns, use the declared type instead.
if (ClassType.isSameGenericClass(declaredType, assignedType)) {
if (containsAnyRecursive(assignedType) && !containsAnyRecursive(declaredType)) {
return declaredType;
}
}

return undefined;
}

Expand All @@ -24404,14 +24412,19 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
return declaredSubtype;
}

// If the source is generic and has unspecified type arguments,
// see if we can determine them based on the declared type.
if (isClass(declaredSubtype) && isClass(assignedSubtype)) {
if (
isClass(declaredSubtype) &&
isClass(assignedSubtype) &&
TypeBase.isInstance(declaredSubtype) === TypeBase.isInstance(assignedSubtype)
) {
const result = replaceTypeArgsWithAny(node, declaredSubtype, assignedSubtype);
if (result) {
assignedSubtype = result;
}
} else if (!isTypeVar(declaredSubtype) && isTypeVar(assignedSubtype)) {
return assignedSubtype;
}

if (!isTypeVar(declaredSubtype) && isTypeVar(assignedSubtype)) {
// If the source is an unsolved TypeVar but the declared type is concrete,
// use the concrete type.
return declaredSubtype;
Expand Down
5 changes: 5 additions & 0 deletions packages/pyright-internal/src/tests/samples/assignment10.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,8 @@ def func4(y: list[Any]):

x3: Iterable[Any] = y
reveal_type(x3, expected_text="list[Any]")


def func5(v1: list[Any | None]):
x1: list[int | None] = v1
reveal_type(x1, expected_text="list[int | None]")

0 comments on commit b9f4615

Please sign in to comment.