Skip to content

Commit

Permalink
Enhanced type narrowing logic for "x == <literal>" type guard pattern…
Browse files Browse the repository at this point in the history
… to handle the case where `x` is a type variable with a literal upper bound or value constraints that are literals. This addresses #9300.
  • Loading branch information
erictraut committed Oct 24, 2024
1 parent 4180fa2 commit 78015b9
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/pyright-internal/src/analyzer/typeGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2468,7 +2468,7 @@ function narrowTypeForLiteralComparison(
isPositiveTest: boolean,
isIsOperator: boolean
): Type {
return mapSubtypes(referenceType, (subtype) => {
return evaluator.mapSubtypesExpandTypeVars(referenceType, /* options */ undefined, (subtype) => {
subtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);

if (isAnyOrUnknown(subtype)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This sample tests the type analyzer's type narrowing
# logic for literals.

from typing import Literal, Union
from typing import Literal, TypeVar, Union


def func1(p1: Literal["a", "b", "c"]):
Expand All @@ -28,3 +28,27 @@ def func2(p1: Literal[1, 4, 7]):
def func3(a: Union[int, None]):
if a == 1 or a == 2:
reveal_type(a, expected_text="Literal[1, 2]")


T = TypeVar("T", bound=Literal["a", "b"])


def func4(x: T) -> T:
if x == "a":
reveal_type(x, expected_text="Literal['a']")
return x
else:
reveal_type(x, expected_text="Literal['b']")
return x


S = TypeVar("S", Literal["a"], Literal["b"])


def func5(x: S) -> S:
if x == "a":
reveal_type(x, expected_text="Literal['a']")
return x
else:
reveal_type(x, expected_text="Literal['b']")
return x

0 comments on commit 78015b9

Please sign in to comment.