mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-05 12:27:30 +03:00
Fixed regression that results in a false positive when a traditional type alias (not using PEP 695 syntax) defines a union and is then used as a second argument to an isinstance
or issubclass
call. This addresses #8302. (#8303)
This commit is contained in:
parent
93ac52f0b2
commit
d7c5d0691a
@ -4617,6 +4617,14 @@ export function createTypeEvaluator(
|
||||
return type;
|
||||
}
|
||||
|
||||
// Isinstance treats traditional (non-PEP 695) type aliases that are unions
|
||||
// as tuples of classes rather than unions.
|
||||
if ((flags & EvalFlags.IsinstanceParam) !== 0) {
|
||||
if (isUnion(type) && type.typeAliasInfo && !type.typeAliasInfo.isPep695Syntax) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return type.specialForm ?? type;
|
||||
}
|
||||
|
||||
@ -12055,7 +12063,8 @@ export function createTypeEvaluator(
|
||||
EvalFlags.NoParamSpec |
|
||||
EvalFlags.NoTypeVarTuple |
|
||||
EvalFlags.NoFinal |
|
||||
EvalFlags.NoSpecialize
|
||||
EvalFlags.NoSpecialize |
|
||||
EvalFlags.IsinstanceParam
|
||||
: EvalFlags.NoFinal | EvalFlags.NoSpecialize;
|
||||
const exprTypeResult = getTypeOfExpression(
|
||||
argParam.argument.valueExpression,
|
||||
|
@ -158,6 +158,10 @@ export const enum EvalFlags {
|
||||
// other container classes).
|
||||
StripTupleLiterals = 1 << 28,
|
||||
|
||||
// Interpret the expression using the specialized behaviors associated
|
||||
// with the second argument to isinstance and issubclass calls.
|
||||
IsinstanceParam = 1 << 29,
|
||||
|
||||
// Defaults used for evaluating the LHS of a call expression.
|
||||
CallBaseDefaults = NoSpecialize,
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This sample exercises the type analyzer's isinstance type narrowing logic.
|
||||
|
||||
from types import NoneType
|
||||
from typing import Generic, Protocol, Sized, TypeVar, Union, Any, runtime_checkable
|
||||
from typing import Any, Generic, Protocol, Sized, TypeVar, Union, runtime_checkable
|
||||
|
||||
S = TypeVar("S")
|
||||
T = TypeVar("T")
|
||||
@ -151,11 +151,25 @@ def handler(node: Base1) -> Any:
|
||||
reveal_type(node.value, expected_text="Sub1_1")
|
||||
|
||||
|
||||
def func8(a: int | list[int] | dict[str, int] | None):
|
||||
if isinstance(
|
||||
a,
|
||||
(str, (int, list, type(None))),
|
||||
):
|
||||
def func8a(a: int | list[int] | dict[str, int] | None):
|
||||
if isinstance(a, (str, (int, list, type(None)))):
|
||||
reveal_type(a, expected_text="int | list[int] | None")
|
||||
else:
|
||||
reveal_type(a, expected_text="dict[str, int]")
|
||||
|
||||
|
||||
def func8b(a: int | list[int] | dict[str, int] | None):
|
||||
if isinstance(a, str | int | list | type(None)):
|
||||
reveal_type(a, expected_text="int | list[int] | None")
|
||||
else:
|
||||
reveal_type(a, expected_text="dict[str, int]")
|
||||
|
||||
|
||||
TA1 = str | int | list | None
|
||||
|
||||
|
||||
def func8c(a: int | list[int] | dict[str, int] | None):
|
||||
if isinstance(a, TA1):
|
||||
reveal_type(a, expected_text="int | list[int] | None")
|
||||
else:
|
||||
reveal_type(a, expected_text="dict[str, int]")
|
||||
@ -200,12 +214,12 @@ def func11(x: Proto1):
|
||||
reveal_type(x, expected_text="Proto1")
|
||||
|
||||
|
||||
TA1 = list["TA2"] | dict[str, "TA2"]
|
||||
TA2 = str | TA1
|
||||
TA2 = list["TA3"] | dict[str, "TA3"]
|
||||
TA3 = str | TA2
|
||||
|
||||
|
||||
def func12(x: TA2) -> None:
|
||||
def func12(x: TA3) -> None:
|
||||
if isinstance(x, dict):
|
||||
reveal_type(x, expected_text="dict[str, str | list[TA2] | dict[str, TA2]]")
|
||||
reveal_type(x, expected_text="dict[str, str | list[TA3] | dict[str, TA3]]")
|
||||
else:
|
||||
reveal_type(x, expected_text="str | list[str | list[TA2] | dict[str, TA2]]")
|
||||
reveal_type(x, expected_text="str | list[str | list[TA3] | dict[str, TA3]]")
|
||||
|
Loading…
Reference in New Issue
Block a user