From b562f53110cf112eaa6f9642e9bae11a46f84e17 Mon Sep 17 00:00:00 2001 From: Stas Ilinskiy Date: Thu, 9 Feb 2023 09:13:09 -0800 Subject: [PATCH 1/7] bump version to 1.0.1+dev --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index e0c07b82c7f5..ac0237fad5d8 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.0.0" +__version__ = "1.0.1+dev" base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) From 0c9958583cf7c2b9ba568b19853aa63aa9d6e670 Mon Sep 17 00:00:00 2001 From: Stas Ilinskiy Date: Thu, 9 Feb 2023 09:15:17 -0800 Subject: [PATCH 2/7] [backport] Fix crash on deferred value constrained TypeVar (#14642) (#14655) Fixes #14631 Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- mypy/types.py | 8 ++++++-- test-data/unit/check-typevar-values.test | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index b4710a95164c..60145cf44527 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -587,12 +587,16 @@ def accept(self, visitor: TypeVisitor[T]) -> T: return visitor.visit_type_var(self) def __hash__(self) -> int: - return hash((self.id, self.upper_bound)) + return hash((self.id, self.upper_bound, tuple(self.values))) def __eq__(self, other: object) -> bool: if not isinstance(other, TypeVarType): return NotImplemented - return self.id == other.id and self.upper_bound == other.upper_bound + return ( + self.id == other.id + and self.upper_bound == other.upper_bound + and self.values == other.values + ) def serialize(self) -> JsonDict: assert not self.id.is_meta_var() diff --git a/test-data/unit/check-typevar-values.test b/test-data/unit/check-typevar-values.test index d5a94f96fae7..a4a4d68bd9fe 100644 --- a/test-data/unit/check-typevar-values.test +++ b/test-data/unit/check-typevar-values.test @@ -702,3 +702,12 @@ class Indexable: [builtins fixtures/tuple.pyi] [builtins fixtures/classmethod.pyi] + +[case testTypeVarWithValueDeferral] +from typing import TypeVar, Callable + +T = TypeVar("T", "A", "B") +Func = Callable[[], T] + +class A: ... +class B: ... From c090ca2a55ef2343cc39222ffb6e503432cfe9f4 Mon Sep 17 00:00:00 2001 From: Stas Ilinskiy Date: Thu, 9 Feb 2023 09:16:08 -0800 Subject: [PATCH 3/7] [backport] [used before def] correctly handle walrus operator (#14646) (#14654) Fixes #14626. I believe changing the way that we analyze call expression makes sense (first, we analyze the callee, then we analyze the arguments). --- mypy/traverser.py | 2 +- test-data/unit/check-python38.test | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mypy/traverser.py b/mypy/traverser.py index 378d44c67f47..038d948522f0 100644 --- a/mypy/traverser.py +++ b/mypy/traverser.py @@ -253,9 +253,9 @@ def visit_yield_expr(self, o: YieldExpr) -> None: o.expr.accept(self) def visit_call_expr(self, o: CallExpr) -> None: + o.callee.accept(self) for a in o.args: a.accept(self) - o.callee.accept(self) if o.analyzed: o.analyzed.accept(self) diff --git a/test-data/unit/check-python38.test b/test-data/unit/check-python38.test index c8fb1eb5aac8..bb88fcc3cff7 100644 --- a/test-data/unit/check-python38.test +++ b/test-data/unit/check-python38.test @@ -573,6 +573,14 @@ def foo() -> None: [x := x + y for y in [1, 2, 3]] [builtins fixtures/dict.pyi] +[case testWalrusUsedBeforeDef] +# flags: --python-version 3.8 +class C: + def f(self, c: 'C') -> None: pass + +(x := C()).f(y) # E: Cannot determine type of "y" # E: Name "y" is used before definition +(y := C()).f(y) + [case testOverloadWithPositionalOnlySelf] # flags: --python-version 3.8 from typing import overload, Optional From 83db0856e2680fcdd84841a5e3ddb66508f533f8 Mon Sep 17 00:00:00 2001 From: Stas Ilinskiy Date: Mon, 13 Feb 2023 07:26:05 -0800 Subject: [PATCH 4/7] [backport] [used before def] handle walrus declaration in match subject correctly (#14672) Backport of #14665. --- mypy/partially_defined.py | 2 +- test-data/unit/check-python310.test | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mypy/partially_defined.py b/mypy/partially_defined.py index af09493c9cae..9b8238eff83f 100644 --- a/mypy/partially_defined.py +++ b/mypy/partially_defined.py @@ -396,8 +396,8 @@ def visit_if_stmt(self, o: IfStmt) -> None: self.tracker.end_branch_statement() def visit_match_stmt(self, o: MatchStmt) -> None: - self.tracker.start_branch_statement() o.subject.accept(self) + self.tracker.start_branch_statement() for i in range(len(o.patterns)): pattern = o.patterns[i] pattern.accept(self) diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 12fd2b43c80a..7a934348aaf2 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -1813,6 +1813,19 @@ def f1(x: int) -> int: [typing fixtures/typing-medium.pyi] +[case testUsedBeforeDefMatchWalrus] +# flags: --enable-error-code used-before-def +import typing + +def f0(x: int) -> None: + a = y # E: Cannot determine type of "y" # E: Name "y" is used before definition + match y := x: + case 1: + b = y + case 2: + c = y + d = y + [case testTypeAliasWithNewUnionSyntaxAndNoneLeftOperand] from typing import overload class C: From a9051d26711905a01382587b1ab3ee7acdae090e Mon Sep 17 00:00:00 2001 From: Stas Ilinskiy Date: Wed, 15 Feb 2023 03:41:04 -0800 Subject: [PATCH 5/7] [backport] [mypyc] Fix test case testI64Cast on 32-bit architectures (#14700) Backport of #14691. Co-authored-by: Jukka Lehtosalo --- mypyc/test-data/irbuild-i64.test | 35 +++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/mypyc/test-data/irbuild-i64.test b/mypyc/test-data/irbuild-i64.test index 47802d8e0c97..8257cfd1dbae 100644 --- a/mypyc/test-data/irbuild-i64.test +++ b/mypyc/test-data/irbuild-i64.test @@ -1731,7 +1731,7 @@ def f5(): L0: return 4 -[case testI64Cast] +[case testI64Cast_64bit] from typing import cast from mypy_extensions import i64 @@ -1772,6 +1772,39 @@ L2: L3: return r3 +[case testI64Cast_32bit] +from typing import cast +from mypy_extensions import i64 + +def cast_int(x: int) -> i64: + return cast(i64, x) +[out] +def cast_int(x): + x :: int + r0 :: native_int + r1 :: bit + r2, r3, r4 :: int64 + r5 :: ptr + r6 :: c_ptr + r7 :: int64 +L0: + r0 = x & 1 + r1 = r0 == 0 + if r1 goto L1 else goto L2 :: bool +L1: + r2 = extend signed x: builtins.int to int64 + r3 = r2 >> 1 + r4 = r3 + goto L3 +L2: + r5 = x ^ 1 + r6 = r5 + r7 = CPyLong_AsInt64(r6) + r4 = r7 + keep_alive x +L3: + return r4 + [case testI64ExplicitConversionFromVariousTypes] from mypy_extensions import i64 From 18c46938e77a3ab01e6e38b57c0b3f1286966109 Mon Sep 17 00:00:00 2001 From: Stas Ilinskiy Date: Wed, 15 Feb 2023 08:41:49 -0800 Subject: [PATCH 6/7] [Backport] Fix generic TypedDict/NamedTuple fixup (#14701) Backport of #14675. --------- Co-authored-by: Ivan Levkivskyi --- mypy/fixup.py | 4 ++++ mypy/nodes.py | 14 ++++++++++-- test-data/unit/check-incremental.test | 31 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/mypy/fixup.py b/mypy/fixup.py index 3593e4faa184..af6d3f3d7b07 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -80,9 +80,13 @@ def visit_type_info(self, info: TypeInfo) -> None: if info.tuple_type: info.tuple_type.accept(self.type_fixer) info.update_tuple_type(info.tuple_type) + if info.special_alias: + info.special_alias.alias_tvars = list(info.defn.type_vars) if info.typeddict_type: info.typeddict_type.accept(self.type_fixer) info.update_typeddict_type(info.typeddict_type) + if info.special_alias: + info.special_alias.alias_tvars = list(info.defn.type_vars) if info.declared_metaclass: info.declared_metaclass.accept(self.type_fixer) if info.metaclass_type: diff --git a/mypy/nodes.py b/mypy/nodes.py index 98976f4fe56a..b1c12cde9981 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -3473,8 +3473,13 @@ def __init__( @classmethod def from_tuple_type(cls, info: TypeInfo) -> TypeAlias: - """Generate an alias to the tuple type described by a given TypeInfo.""" + """Generate an alias to the tuple type described by a given TypeInfo. + + NOTE: this doesn't set type alias type variables (for generic tuple types), + they must be set by the caller (when fully analyzed). + """ assert info.tuple_type + # TODO: is it possible to refactor this to set the correct type vars here? return TypeAlias( info.tuple_type.copy_modified(fallback=mypy.types.Instance(info, info.defn.type_vars)), info.fullname, @@ -3484,8 +3489,13 @@ def from_tuple_type(cls, info: TypeInfo) -> TypeAlias: @classmethod def from_typeddict_type(cls, info: TypeInfo) -> TypeAlias: - """Generate an alias to the TypedDict type described by a given TypeInfo.""" + """Generate an alias to the TypedDict type described by a given TypeInfo. + + NOTE: this doesn't set type alias type variables (for generic TypedDicts), + they must be set by the caller (when fully analyzed). + """ assert info.typeddict_type + # TODO: is it possible to refactor this to set the correct type vars here? return TypeAlias( info.typeddict_type.copy_modified( fallback=mypy.types.Instance(info, info.defn.type_vars) diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 1aff1ba2862f..2897e895a394 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -6359,3 +6359,34 @@ from m import Foo [file m.py] from missing_module import Meta # type: ignore[import] class Foo(metaclass=Meta): ... + +[case testGenericTypedDictWithError] +import b +[file a.py] +from typing import Generic, TypeVar +from typing_extensions import TypedDict + +TValue = TypeVar("TValue") +class Dict(TypedDict, Generic[TValue]): + value: TValue + +[file b.py] +from a import Dict, TValue + +def f(d: Dict[TValue]) -> TValue: + return d["value"] +def g(d: Dict[TValue]) -> TValue: + return d["x"] + +[file b.py.2] +from a import Dict, TValue + +def f(d: Dict[TValue]) -> TValue: + return d["value"] +def g(d: Dict[TValue]) -> TValue: + return d["y"] +[builtins fixtures/dict.pyi] +[out] +tmp/b.py:6: error: TypedDict "a.Dict[TValue]" has no key "x" +[out2] +tmp/b.py:6: error: TypedDict "a.Dict[TValue]" has no key "y" From ecf05e6388eb5c3c0c5d7ea963817c0f81b65618 Mon Sep 17 00:00:00 2001 From: Stas Ilinskiy Date: Thu, 16 Feb 2023 21:16:59 -0800 Subject: [PATCH 7/7] bump version to 1.0.1 --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index ac0237fad5d8..2f519543cd44 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.0.1+dev" +__version__ = "1.0.1" base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))