From a5b05b89c6f5cc8214f8a4c2ebfc653ec887dcb2 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Wed, 24 Jan 2024 22:25:51 +0100 Subject: [PATCH 1/4] Empty From 8e867fd8d3e32bcf3e24a1f4616875ead357762b Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:50:46 +0100 Subject: [PATCH 2/4] WIP --- test-data/unit/check-typevar-defaults.test | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/test-data/unit/check-typevar-defaults.test b/test-data/unit/check-typevar-defaults.test index 9ca67376da26..ac77478523e5 100644 --- a/test-data/unit/check-typevar-defaults.test +++ b/test-data/unit/check-typevar-defaults.test @@ -151,7 +151,7 @@ def func_error_alias2( [builtins fixtures/dict.pyi] [case testTypeVarDefaultsFunctions] -from typing import TypeVar, ParamSpec, List, Union, Callable, Tuple +from typing import TypeVar, ParamSpec, List, Union, Callable, Tuple, overload from typing_extensions import TypeVarTuple, Unpack T1 = TypeVar("T1", default=str) @@ -183,6 +183,14 @@ reveal_type(func_b1(2)) # N: Revealed type is "def (builtins.int, builtins.str) def func_c1(x: Union[int, Callable[[Unpack[Ts1]], None]]) -> Tuple[Unpack[Ts1]]: ... # reveal_type(func_c1(callback1)) # Revealed type is "builtins.tuple[str]" # TODO # reveal_type(func_c1(2)) # Revealed type is "builtins.tuple[builtins.int, builtins.str]" # TODO + +@overload +def func_d1(x: int) -> int: ... +@overload +def func_d1(x: Union[float, T1]) -> T1: ... +def func_d1(x): ... +reveal_type(func_d1(2)) # N: Revealed type is "builtins.int" +reveal_type(func_d1(2.1)) # N: Revealed type is "builtins.str" [builtins fixtures/tuple.pyi] [case testTypeVarDefaultsClass1] @@ -417,6 +425,26 @@ def func_c4( reveal_type(m) # N: Revealed type is "__main__.ClassC4[builtins.int, builtins.float]" [builtins fixtures/tuple.pyi] +[case testTypeVarDefaultsClass4] +# flags: --disallow-any-generics +from typing import Dict, Generic, List, TypeVar, Tuple + +T1 = TypeVar("T1", default=str) +T2 = TypeVar("T2", default=T1) +T3 = TypeVar("T3", default=Tuple[T2]) +T4 = TypeVar("T4", default=Tuple[T1, T2]) +T5 = TypeVar("T5", default="T5") + +class ClassD1(Generic[T1, T2]): ... + +# def func_d1(c: ClassD1[int]) -> None: +# a = ClassD1[int]() +# reveal_type(a) # Revealed type is "__main__.ClassD1[builtins.int, builtins.int]" +# b = ClassD1() +# reveal_type(b) # Revealed type is "__main__.ClassD1[builtins.str, builtins.str]" +# reveal_type(c) +[builtins fixtures/tuple.pyi] + [case testTypeVarDefaultsClassRecursive1] # flags: --disallow-any-generics from typing import Generic, TypeVar, List From 322f6272e17b4c27bf70ece806778bb4781180c5 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:10:31 +0100 Subject: [PATCH 3/4] WIP 2 --- mypy/expandtype.py | 8 +++++++ test-data/unit/check-typevar-defaults.test | 26 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/mypy/expandtype.py b/mypy/expandtype.py index f7fa0258f588..0faa85c0fa6c 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -241,6 +241,14 @@ def visit_type_var(self, t: TypeVarType) -> Type: def visit_param_spec(self, t: ParamSpecType) -> Type: # Set prefix to something empty, so we don't duplicate it below. repl = self.variables.get(t.id, t.copy_modified(prefix=Parameters([], [], []))) + if isinstance(repl, ParamSpecType): + if (tvar_id := repl.id) in self.recursive_tvar_guard: + return self.recursive_tvar_guard[tvar_id] or repl + self.recursive_tvar_guard[tvar_id] = None + repl = repl.accept(self) + if isinstance(repl, ParamSpecType): + repl.default = repl.default.accept(self) + self.recursive_tvar_guard[tvar_id] = repl if isinstance(repl, ParamSpecType): return repl.copy_modified( flavor=t.flavor, diff --git a/test-data/unit/check-typevar-defaults.test b/test-data/unit/check-typevar-defaults.test index ac77478523e5..9cced741e248 100644 --- a/test-data/unit/check-typevar-defaults.test +++ b/test-data/unit/check-typevar-defaults.test @@ -512,6 +512,32 @@ def func_d3( m = ClassD3[int, float]() reveal_type(m) # N: Revealed type is "__main__.ClassD3[builtins.int, builtins.float]" +[case testTypeVarDefaultsClassRecursive2] +# flags: --disallow-any-generics +from typing import Generic, ParamSpec + +P1 = ParamSpec("P1", default=[int, str]) +P2 = ParamSpec("P2", default=P1) +P3 = ParamSpec("P3") + +class ClassE1(Generic[P1, P2]): ... + +def func_e1( + a: ClassE1, + b: ClassE1[[float]], + c: ClassE1[[float], [str]], +) -> None: + reveal_type(a) # N: Revealed type is "__main__.ClassE1[[builtins.int, builtins.str], [builtins.int, builtins.str]]" + reveal_type(b) # N: Revealed type is "__main__.ClassE1[[builtins.float], [builtins.float]]" + reveal_type(c) # N: Revealed type is "__main__.ClassE1[[builtins.float], [builtins.str]]" + + k = ClassE1() + # reveal_type(k) # Revealed type is "__main__.ClassE1[[builtins.int, builtins.str], [builtins.int, builtins.str]]" # TODO + l = ClassE1[[float]]() + reveal_type(l) # N: Revealed type is "__main__.ClassE1[[builtins.float], [builtins.float]]" + m = ClassE1[[float], [str]]() + reveal_type(m) # N: Revealed type is "__main__.ClassE1[[builtins.float], [builtins.str]]" + [case testTypeVarDefaultsClassRecursiveMultipleFiles] # flags: --disallow-any-generics from typing import Generic, TypeVar From e3a35289ee40766f882b29aa97dde472141ad7e2 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:39:33 +0100 Subject: [PATCH 4/4] Revert "WIP 2" --- mypy/expandtype.py | 8 ------- test-data/unit/check-typevar-defaults.test | 26 ---------------------- 2 files changed, 34 deletions(-) diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 0faa85c0fa6c..f7fa0258f588 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -241,14 +241,6 @@ def visit_type_var(self, t: TypeVarType) -> Type: def visit_param_spec(self, t: ParamSpecType) -> Type: # Set prefix to something empty, so we don't duplicate it below. repl = self.variables.get(t.id, t.copy_modified(prefix=Parameters([], [], []))) - if isinstance(repl, ParamSpecType): - if (tvar_id := repl.id) in self.recursive_tvar_guard: - return self.recursive_tvar_guard[tvar_id] or repl - self.recursive_tvar_guard[tvar_id] = None - repl = repl.accept(self) - if isinstance(repl, ParamSpecType): - repl.default = repl.default.accept(self) - self.recursive_tvar_guard[tvar_id] = repl if isinstance(repl, ParamSpecType): return repl.copy_modified( flavor=t.flavor, diff --git a/test-data/unit/check-typevar-defaults.test b/test-data/unit/check-typevar-defaults.test index 9cced741e248..ac77478523e5 100644 --- a/test-data/unit/check-typevar-defaults.test +++ b/test-data/unit/check-typevar-defaults.test @@ -512,32 +512,6 @@ def func_d3( m = ClassD3[int, float]() reveal_type(m) # N: Revealed type is "__main__.ClassD3[builtins.int, builtins.float]" -[case testTypeVarDefaultsClassRecursive2] -# flags: --disallow-any-generics -from typing import Generic, ParamSpec - -P1 = ParamSpec("P1", default=[int, str]) -P2 = ParamSpec("P2", default=P1) -P3 = ParamSpec("P3") - -class ClassE1(Generic[P1, P2]): ... - -def func_e1( - a: ClassE1, - b: ClassE1[[float]], - c: ClassE1[[float], [str]], -) -> None: - reveal_type(a) # N: Revealed type is "__main__.ClassE1[[builtins.int, builtins.str], [builtins.int, builtins.str]]" - reveal_type(b) # N: Revealed type is "__main__.ClassE1[[builtins.float], [builtins.float]]" - reveal_type(c) # N: Revealed type is "__main__.ClassE1[[builtins.float], [builtins.str]]" - - k = ClassE1() - # reveal_type(k) # Revealed type is "__main__.ClassE1[[builtins.int, builtins.str], [builtins.int, builtins.str]]" # TODO - l = ClassE1[[float]]() - reveal_type(l) # N: Revealed type is "__main__.ClassE1[[builtins.float], [builtins.float]]" - m = ClassE1[[float], [str]]() - reveal_type(m) # N: Revealed type is "__main__.ClassE1[[builtins.float], [builtins.str]]" - [case testTypeVarDefaultsClassRecursiveMultipleFiles] # flags: --disallow-any-generics from typing import Generic, TypeVar