diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index fdc0f94b3997..c4d315365cbd 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -4341,7 +4341,7 @@ def visit_index_with_type( elif isinstance(left_type, FunctionLike) and left_type.is_type_obj(): if left_type.type_object().is_enum: return self.visit_enum_index_expr(left_type.type_object(), e.index, e) - elif left_type.type_object().type_vars: + elif left_type.type_object().type_vars and self.chk.options.python_version >= (3, 9): return self.named_type("types.GenericAlias") elif ( left_type.type_object().fullname == "builtins.type" @@ -4682,7 +4682,7 @@ def visit_type_application(self, tapp: TypeApplication) -> Type: """ if isinstance(tapp.expr, RefExpr) and isinstance(tapp.expr.node, TypeAlias): if tapp.expr.node.python_3_12_type_alias: - return self.named_type("typing.TypeAliasType") + return self.type_alias_type_type() # Subscription of a (generic) alias in runtime context, expand the alias. item = instantiate_type_alias( tapp.expr.node, @@ -4746,7 +4746,7 @@ class LongName(Generic[T]): ... y = cast(A, ...) """ if alias.python_3_12_type_alias: - return self.named_type("typing.TypeAliasType") + return self.type_alias_type_type() if isinstance(alias.target, Instance) and alias.target.invalid: # type: ignore[misc] # An invalid alias, error already has been reported return AnyType(TypeOfAny.from_error) @@ -5862,6 +5862,12 @@ def named_type(self, name: str) -> Instance: """ return self.chk.named_type(name) + def type_alias_type_type(self) -> Instance: + """Returns a `typing.TypeAliasType` or `typing_extensions.TypeAliasType`.""" + if self.chk.options.python_version >= (3, 12): + return self.named_type("typing.TypeAliasType") + return self.named_type("typing_extensions.TypeAliasType") + def is_valid_var_arg(self, typ: Type) -> bool: """Is a type valid as a *args argument?""" typ = get_proper_type(typ) diff --git a/mypy/types.py b/mypy/types.py index 89609e8d0546..3dce98be6cf0 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -2703,6 +2703,8 @@ def simple_name(self) -> str: return self.base_type_name.replace("builtins.", "") def accept(self, visitor: TypeVisitor[T]) -> T: + if self.node is not None: + return self.node.accept(visitor) assert isinstance(visitor, SyntheticTypeVisitor) ret: T = visitor.visit_raw_expression_type(self) return ret @@ -2898,12 +2900,19 @@ def relevant_items(self) -> list[Type]: return [i for i in self.items if not isinstance(get_proper_type(i), NoneType)] def serialize(self) -> JsonDict: - return {".class": "UnionType", "items": [t.serialize() for t in self.items]} + return { + ".class": "UnionType", + "items": [t.serialize() for t in self.items], + "uses_pep604_syntax": self.uses_pep604_syntax, + } @classmethod def deserialize(cls, data: JsonDict) -> UnionType: assert data[".class"] == "UnionType" - return UnionType([deserialize_type(t) for t in data["items"]]) + return UnionType( + [deserialize_type(t) for t in data["items"]], + uses_pep604_syntax=data["uses_pep604_syntax"], + ) class PartialType(ProperType): diff --git a/mypy/version.py b/mypy/version.py index 251b23812568..69ab53ace234 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -8,7 +8,7 @@ # - Release versions have the form "1.2.3". # - Dev versions have the form "1.2.3+dev" (PLUS sign to conform to PEP 440). # - Before 1.0 we had the form "0.NNN". -__version__ = "1.11.0" +__version__ = "1.11.1" base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 93540e203c36..a8b535729059 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -1779,6 +1779,7 @@ def Arg(x, y): pass F = Callable[[Arg(int, 'x')], int] # E: Invalid argument constructor "__main__.Arg" [case testCallableParsingFromExpr] +# flags: --python-version 3.9 from typing import Callable, List from mypy_extensions import Arg, VarArg, KwArg import mypy_extensions @@ -1799,10 +1800,23 @@ L = Callable[[Arg(name='x', type=int)], int] # ok # I have commented out the following test because I don't know how to expect the "defined here" note part of the error. # M = Callable[[Arg(gnome='x', type=int)], int] E: Invalid type alias: expression is not a valid type E: Unexpected keyword argument "gnome" for "Arg" N = Callable[[Arg(name=None, type=int)], int] # ok -O = Callable[[List[Arg(int)]], int] # E: Invalid type alias: expression is not a valid type # E: Value of type "int" is not indexable # E: Type expected within [...] +O = Callable[[List[Arg(int)]], int] # E: Invalid type alias: expression is not a valid type \ + # E: Value of type "int" is not indexable \ + # E: Type expected within [...] P = Callable[[mypy_extensions.VarArg(int)], int] # ok -Q = Callable[[Arg(int, type=int)], int] # E: Invalid type alias: expression is not a valid type # E: Value of type "int" is not indexable # E: "Arg" gets multiple values for keyword argument "type" -R = Callable[[Arg(int, 'x', name='y')], int] # E: Invalid type alias: expression is not a valid type # E: Value of type "int" is not indexable # E: "Arg" gets multiple values for keyword argument "name" +Q = Callable[[Arg(int, type=int)], int] # E: Invalid type alias: expression is not a valid type \ + # E: Value of type "int" is not indexable \ + # E: "Arg" gets multiple values for keyword argument "type" +R = Callable[[Arg(int, 'x', name='y')], int] # E: Invalid type alias: expression is not a valid type \ + # E: Value of type "int" is not indexable \ + # E: "Arg" gets multiple values for keyword argument "name" + + + + + + + [builtins fixtures/dict.pyi] [case testCallableParsing] diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 24292bce3e21..173265e48e6f 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -6726,3 +6726,20 @@ from typing_extensions import TypeIs def guard(x: object) -> TypeIs[int]: pass [builtins fixtures/tuple.pyi] + +[case testStartUsingPEP604Union] +# flags: --python-version 3.10 +import a +[file a.py] +import lib + +[file a.py.2] +from lib import IntOrStr +assert isinstance(1, IntOrStr) + +[file lib.py] +from typing_extensions import TypeAlias + +IntOrStr: TypeAlias = int | str +assert isinstance(1, IntOrStr) +[builtins fixtures/type.pyi] diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 6f9e9eda1d02..c7b9694a9188 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -1074,7 +1074,7 @@ x: TestType = 42 y: TestType = 'a' z: TestType = object() # E: Incompatible types in assignment (expression has type "object", variable has type "Union[int, str]") -reveal_type(TestType) # N: Revealed type is "typing.TypeAliasType" +reveal_type(TestType) # N: Revealed type is "typing_extensions.TypeAliasType" TestType() # E: "TypeAliasType" not callable class A: @@ -1084,6 +1084,15 @@ yc: A.ClassAlias = "" # E: Incompatible types in assignment (expression has typ [builtins fixtures/tuple.pyi] [typing fixtures/typing-full.pyi] +[case testTypeAliasTypePython311] +# flags: --python-version 3.11 +# Pinning to 3.11, because 3.12 has `TypeAliasType` +from typing_extensions import TypeAliasType + +TestType = TypeAliasType("TestType", int) +x: TestType = 1 +[builtins fixtures/tuple.pyi] + [case testTypeAliasTypeInvalid] from typing_extensions import TypeAliasType diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index d35ec8ddd80e..a6a89f14309f 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -1442,6 +1442,18 @@ reveal_type(x) # N: Revealed type is "TypedDict('__main__.X', {'a': TypedDict('_ reveal_type(x['a']['b']) # N: Revealed type is "builtins.int" [builtins fixtures/dict.pyi] +[case testTypedDictForwardReferenceCacheFineGrained] +# flags: --cache-fine-grained +from mypy_extensions import TypedDict +class A(TypedDict): + b: "B" +class B(TypedDict): + c: "C" +class C(TypedDict): + d: "D" +class D: + pass + [case testSelfRecursiveTypedDictInheriting] from mypy_extensions import TypedDict