From 2c6e5988dc3b85ec2afa8a7bfb472f0527c9961f Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Thu, 21 Apr 2022 11:28:35 +0200 Subject: [PATCH] Revert "Use class name as namespace for type variables (#12590)" This reverts commit 20b0b9b460cd11a4755f70ae08823fa6a8f5fbd4. --- mypy/checkpattern.py | 3 +- mypy/semanal.py | 3 +- mypy/tvar_scope.py | 21 +++------ mypy/types.py | 16 ++----- test-data/unit/check-selftype.test | 73 +----------------------------- 5 files changed, 14 insertions(+), 102 deletions(-) diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index e1d4f9fe285e7..0fedec24cc372 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -396,7 +396,8 @@ def visit_mapping_pattern(self, o: MappingPattern) -> PatternType: if is_subtype(current_type, mapping) and isinstance(current_type, Instance): mapping_inst = map_instance_to_supertype(current_type, mapping.type) dict_typeinfo = self.chk.lookup_typeinfo("builtins.dict") - rest_type = Instance(dict_typeinfo, mapping_inst.args) + dict_type = fill_typevars(dict_typeinfo) + rest_type = expand_type_by_instance(dict_type, mapping_inst) else: object_type = self.chk.named_type("builtins.object") rest_type = self.chk.named_generic_type("builtins.dict", diff --git a/mypy/semanal.py b/mypy/semanal.py index 985d5217cc08a..0d3e84b05ef78 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1116,8 +1116,7 @@ def check_decorated_function_is_method(self, decorator: str, def visit_class_def(self, defn: ClassDef) -> None: self.statement = defn self.incomplete_type_stack.append(not defn.info) - namespace = self.qualified_name(defn.name) - with self.tvar_scope_frame(self.tvar_scope.class_frame(namespace)): + with self.tvar_scope_frame(self.tvar_scope.class_frame()): self.analyze_class(defn) self.incomplete_type_stack.pop() diff --git a/mypy/tvar_scope.py b/mypy/tvar_scope.py index c1fe1cd6be356..82e321cd82cac 100644 --- a/mypy/tvar_scope.py +++ b/mypy/tvar_scope.py @@ -1,10 +1,6 @@ from typing import Optional, Dict, Union -from mypy.types import ( - TypeVarLikeType, TypeVarType, ParamSpecType, ParamSpecFlavor, TypeVarId, TypeVarTupleType, -) -from mypy.nodes import ( - ParamSpecExpr, TypeVarExpr, TypeVarLikeExpr, SymbolTableNode, TypeVarTupleExpr, -) +from mypy.types import TypeVarLikeType, TypeVarType, ParamSpecType, ParamSpecFlavor, TypeVarTupleType +from mypy.nodes import ParamSpecExpr, TypeVarExpr, TypeVarLikeExpr, SymbolTableNode, TypeVarTupleExpr class TypeVarLikeScope: @@ -16,8 +12,7 @@ class TypeVarLikeScope: def __init__(self, parent: 'Optional[TypeVarLikeScope]' = None, is_class_scope: bool = False, - prohibited: 'Optional[TypeVarLikeScope]' = None, - namespace: str = '') -> None: + prohibited: 'Optional[TypeVarLikeScope]' = None) -> None: """Initializer for TypeVarLikeScope Parameters: @@ -32,7 +27,6 @@ def __init__(self, self.class_id = 0 self.is_class_scope = is_class_scope self.prohibited = prohibited - self.namespace = namespace if parent is not None: self.func_id = parent.func_id self.class_id = parent.class_id @@ -57,25 +51,22 @@ def method_frame(self) -> 'TypeVarLikeScope': """A new scope frame for binding a method""" return TypeVarLikeScope(self, False, None) - def class_frame(self, namespace: str) -> 'TypeVarLikeScope': + def class_frame(self) -> 'TypeVarLikeScope': """A new scope frame for binding a class. Prohibits *this* class's tvars""" - return TypeVarLikeScope(self.get_function_scope(), True, self, namespace=namespace) + return TypeVarLikeScope(self.get_function_scope(), True, self) def bind_new(self, name: str, tvar_expr: TypeVarLikeExpr) -> TypeVarLikeType: if self.is_class_scope: self.class_id += 1 i = self.class_id - namespace = self.namespace else: self.func_id -= 1 i = self.func_id - # TODO: Consider also using namespaces for functions - namespace = '' if isinstance(tvar_expr, TypeVarExpr): tvar_def: TypeVarLikeType = TypeVarType( name, tvar_expr.fullname, - TypeVarId(i, namespace=namespace), + i, values=tvar_expr.values, upper_bound=tvar_expr.upper_bound, variance=tvar_expr.variance, diff --git a/mypy/types.py b/mypy/types.py index e43b73f093b89..72c9d54eddad1 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -426,15 +426,9 @@ class TypeVarId: # Class variable used for allocating fresh ids for metavariables. next_raw_id: ClassVar[int] = 1 - # Fullname of class (or potentially function in the future) which - # declares this type variable (not the fullname of the TypeVar - # definition!), or '' - namespace: str - - def __init__(self, raw_id: int, meta_level: int = 0, *, namespace: str = '') -> None: + def __init__(self, raw_id: int, meta_level: int = 0) -> None: self.raw_id = raw_id self.meta_level = meta_level - self.namespace = namespace @staticmethod def new(meta_level: int) -> 'TypeVarId': @@ -448,8 +442,7 @@ def __repr__(self) -> str: def __eq__(self, other: object) -> bool: if isinstance(other, TypeVarId): return (self.raw_id == other.raw_id and - self.meta_level == other.meta_level and - self.namespace == other.namespace) + self.meta_level == other.meta_level) else: return False @@ -457,7 +450,7 @@ def __ne__(self, other: object) -> bool: return not (self == other) def __hash__(self) -> int: - return hash((self.raw_id, self.meta_level, self.namespace)) + return hash((self.raw_id, self.meta_level)) def is_meta_var(self) -> bool: return self.meta_level > 0 @@ -531,7 +524,6 @@ def serialize(self) -> JsonDict: 'name': self.name, 'fullname': self.fullname, 'id': self.id.raw_id, - 'namespace': self.id.namespace, 'values': [v.serialize() for v in self.values], 'upper_bound': self.upper_bound.serialize(), 'variance': self.variance, @@ -543,7 +535,7 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarType': return TypeVarType( data['name'], data['fullname'], - TypeVarId(data['id'], namespace=data['namespace']), + data['id'], [deserialize_type(v) for v in data['values']], deserialize_type(data['upper_bound']), data['variance'], diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index f86e32905752b..b59c22dfae062 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -893,14 +893,11 @@ from typing import Generic, TypeVar, Tuple T = TypeVar('T') S = TypeVar('S') U = TypeVar('U') -V = TypeVar('V') class C(Generic[T]): def magic(self: C[Tuple[S, U]]) -> Tuple[T, S, U]: ... -class D(Generic[V]): - def f(self) -> None: - reveal_type(C[Tuple[V, str]]().magic()) # N: Revealed type is "Tuple[Tuple[V`1, builtins.str], V`1, builtins.str]" +reveal_type(C[Tuple[int, str]]().magic()) # N: Revealed type is "Tuple[Tuple[builtins.int, builtins.str], builtins.int, builtins.str]" [builtins fixtures/tuple.pyi] [case testSelfTypeOnUnion] @@ -1170,71 +1167,3 @@ def build_wrapper_non_gen(descriptor: Descriptor[int]) -> BaseWrapper[str]: def build_sub_wrapper_non_gen(descriptor: Descriptor[int]) -> SubWrapper[str]: return SubWrapper.create_wrapper(descriptor) # E: Argument 1 to "create_wrapper" of "BaseWrapper" has incompatible type "Descriptor[int]"; expected "Descriptor[str]" [builtins fixtures/classmethod.pyi] - -[case testSelfTypeInGenericClassUsedFromAnotherGenericClass1] -from typing import TypeVar, Generic, Iterator, List, Tuple - -_T_co = TypeVar("_T_co", covariant=True) -_T1 = TypeVar("_T1") -_T2 = TypeVar("_T2") -S = TypeVar("S") - -class Z(Iterator[_T_co]): - def __new__(cls, - __iter1: List[_T1], - __iter2: List[_T2]) -> Z[Tuple[_T1, _T2]]: ... - def __iter__(self: S) -> S: ... - def __next__(self) -> _T_co: ... - -T = TypeVar('T') - -class C(Generic[T]): - a: List[T] - b: List[str] - - def f(self) -> None: - for x, y in Z(self.a, self.b): - reveal_type((x, y)) # N: Revealed type is "Tuple[T`1, builtins.str]" -[builtins fixtures/tuple.pyi] - -[case testEnumerateReturningSelfFromIter] -from typing import Generic, Iterable, Iterator, TypeVar, Tuple - -T = TypeVar("T") -KT = TypeVar("KT") -VT = TypeVar("VT") -Self = TypeVar("Self") - -class enumerate(Iterator[Tuple[int, T]], Generic[T]): - def __init__(self, iterable: Iterable[T]) -> None: ... - def __iter__(self: Self) -> Self: ... - def __next__(self) -> Tuple[int, T]: ... - -class Dict(Generic[KT, VT]): - def update(self, __m: Iterable[Tuple[KT, VT]]) -> None: ... - -class ThingCollection(Generic[T]): - collection: Iterable[Tuple[float, T]] - index: Dict[int, T] - - def do_thing(self) -> None: - self.index.update((idx, c) for idx, (k, c) in enumerate(self.collection)) -[builtins fixtures/tuple.pyi] - -[case testDequeReturningSelfFromCopy] -# Tests a bug with generic self types identified in issue #12641 -from typing import Generic, Sequence, TypeVar - -T = TypeVar("T") -Self = TypeVar("Self") - -class deque(Sequence[T]): - def copy(self: Self) -> Self: ... - -class List(Sequence[T]): ... - -class Test(Generic[T]): - def test(self) -> None: - a: deque[List[T]] - # previously this failed with 'Incompatible types in assignment (expression has type "deque[List[List[T]]]", variable has type "deque[List[T]]")' - b: deque[List[T]] = a.copy()