From 83a75977f5fb4de63afcf430fbbe2801bda2636e Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Fri, 15 Jul 2022 16:13:26 +0100 Subject: [PATCH 01/33] 3rd times the charm --- mypy/checker.py | 4 +- mypy/checkmember.py | 8 +++- mypy/semanal.py | 95 ++++++++++++++++++++++++++++++++++++++++----- mypy/subtypes.py | 10 ++++- mypy/typeanal.py | 13 ++++++- mypy/types.py | 47 ++++++++++++++++++++++ 6 files changed, 162 insertions(+), 15 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 39f3fa42942d..9a0749b6772c 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -38,7 +38,7 @@ is_named_instance, union_items, TypeQuery, LiteralType, is_optional, remove_optional, TypeTranslator, StarType, get_proper_type, ProperType, get_proper_types, is_literal_type, TypeAliasType, TypeGuardedType, ParamSpecType, - OVERLOAD_NAMES, UnboundType + OVERLOAD_NAMES, UnboundType, SelfType ) from mypy.sametypes import is_same_type from mypy.messages import ( @@ -1148,7 +1148,7 @@ def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None: 'but must return a subtype of' ) elif not isinstance(get_proper_type(bound_type.ret_type), - (AnyType, Instance, TupleType)): + (AnyType, Instance, TupleType, SelfType)): self.fail( message_registry.NON_INSTANCE_NEW_TYPE.format( format_type(bound_type.ret_type)), diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 2172361ea2f0..5dd9ae3d4211 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -7,7 +7,7 @@ Type, Instance, AnyType, TupleType, TypedDictType, CallableType, FunctionLike, TypeVarLikeType, Overloaded, TypeVarType, UnionType, PartialType, TypeOfAny, LiteralType, DeletedType, NoneType, TypeType, has_type_vars, get_proper_type, ProperType, ParamSpecType, - ENUM_REMOVED_PROPS + SelfType, ENUM_REMOVED_PROPS ) from mypy.nodes import ( TypeInfo, FuncBase, Var, FuncDef, SymbolNode, SymbolTable, Context, @@ -500,6 +500,8 @@ def analyze_descriptor_access(descriptor_type: Type, analyze_descriptor_access(typ, mx) for typ in descriptor_type.items ]) + elif isinstance(descriptor_type, SelfType): + return instance_type elif not isinstance(descriptor_type, Instance): return descriptor_type @@ -802,7 +804,9 @@ def analyze_class_attribute_access(itype: Instance, # C[int].x # Also an error, since C[int] is same as C at runtime if isinstance(t, TypeVarType) or has_type_vars(t): # Exception: access on Type[...], including first argument of class methods is OK. - if not isinstance(get_proper_type(mx.original_type), TypeType) or node.implicit: + if isinstance(t, SelfType): + return mx.named_type(info.fullname) + elif not isinstance(get_proper_type(mx.original_type), TypeType) or node.implicit: if node.node.is_classvar: message = message_registry.GENERIC_CLASS_VAR_ACCESS else: diff --git a/mypy/semanal.py b/mypy/semanal.py index e00913a8cde4..d000aada39bd 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -99,7 +99,7 @@ TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, Parameters, ParamSpecType, PROTOCOL_NAMES, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, FINAL_DECORATOR_NAMES, REVEAL_TYPE_NAMES, - ASSERT_TYPE_NAMES, OVERLOAD_NAMES, is_named_instance, + ASSERT_TYPE_NAMES, OVERLOAD_NAMES, is_named_instance, SelfType, SELF_TYPE_NAMES, ) from mypy.typeops import function_type, get_type_vars from mypy.type_visitor import TypeQuery @@ -697,19 +697,84 @@ def analyze_func_def(self, defn: FuncDef) -> None: def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: """Check basic signature validity and tweak annotation of self/cls argument.""" # Only non-static methods are special. - functype = func.type if not func.is_static: if func.name in ['__init_subclass__', '__class_getitem__']: func.is_class = True if not func.arguments: self.fail('Method must have at least one argument', func) - elif isinstance(functype, CallableType): - self_type = get_proper_type(functype.arg_types[0]) - if isinstance(self_type, AnyType): + elif isinstance(func.type, CallableType): + self_type = get_proper_type(func.type.arg_types[0]) + if isinstance(self_type, AnyType) and not self_type.type_of_any == TypeOfAny.explicit: leading_type: Type = fill_typevars(info) if func.is_class or func.name == '__new__': leading_type = self.class_type(leading_type) - func.type = replace_implicit_first_type(functype, leading_type) + func.type = replace_implicit_first_type(func.type, leading_type) + + leading_type = func.type.arg_types[0] + proper_leading_type = get_proper_type(leading_type) + print("proper leading type is", proper_leading_type, func) + if isinstance(proper_leading_type, Instance): # method[[Self, ...], Self] case + proper_leading_type = self_type_type = SelfType("Self", proper_leading_type) + func.type = replace_implicit_first_type(func.type, proper_leading_type) + elif ( + isinstance(proper_leading_type, TypeType) and isinstance(proper_leading_type.item, Instance) + ): # classmethod[[type[Self], ...], Self] case + self_type_type = SelfType("Self", proper_leading_type.item) + proper_leading_type = self.class_type(self_type_type) + func.type = replace_implicit_first_type(func.type, proper_leading_type) + elif self.is_self_type(proper_leading_type): + proper_leading_type = self_type_type = SelfType("Self", self.named_type(info.fullname)) + func.type = replace_implicit_first_type(func.type, proper_leading_type) + elif isinstance(proper_leading_type, UnboundType): + # classmethod[[type[Self], ...], Self] case + node = self.lookup(proper_leading_type.name, func) + if ( + node is not None + and node.fullname in {"typing.Type", "builtins.type"} + and proper_leading_type.args + and self.is_self_type(proper_leading_type.args[0]) + ): + self_type_type = SelfType("Self", self.named_type(info.fullname)) + proper_leading_type = self.class_type(self_type_type) + func.type = replace_implicit_first_type(func.type, proper_leading_type) + + # bind any SelfTypes in args and return types + for idx, arg in enumerate(func.type.arg_types): + if self.is_self_type(arg): + if func.is_static: + self.fail( + "Self-type annotations of staticmethods are not supported, " + "please replace the type with {}".format(self_type.type.name), + func + ) + func.type.arg_types[idx] = self.named_type( + self_type.type.name + ) # we replace them here for them + continue + if self_type_type.fullname == self_type_type.name: + assert isinstance(arg, UnboundType) + table_node = self.lookup(arg.name, func) + assert isinstance(table_node, SymbolTableNode) and table_node.node + self_type_type.fullname = table_node.node.fullname + func.type.arg_types[idx] = self_type_type + + if self.is_self_type(func.type.ret_type): + if self_type_type.fullname == self_type_type.name: + assert isinstance(func.type.ret_type, UnboundType) + table_node = self.lookup_qualified( + func.type.ret_type.name, func.type.ret_type + ) + assert isinstance(table_node, SymbolTableNode) and table_node.node + self_type_type.fullname = table_node.node.fullname + if func.is_static: + self.fail( + "Self-type annotations of staticmethods are not supported, " + "please replace the type with {}".format(self_type.type.name), + func, + ) + func.type.ret_type = self.named_type(self_type.type.name) + return + func.type.ret_type = self_type_type def set_original_def(self, previous: Optional[Node], new: Union[FuncDef, Decorator]) -> bool: """If 'new' conditionally redefine 'previous', set 'previous' as original @@ -3434,9 +3499,10 @@ def check_classvar(self, s: AssignmentStmt) -> None: analyzed = self.anal_type(s.type) if analyzed is not None and get_type_vars(analyzed): # This means that we have a type var defined inside of a ClassVar. - # This is not allowed by PEP526. + # This is not allowed by PEP526. (Unless it's a SelfType, which is fine) # See https://github.com/python/mypy/issues/11538 - self.fail(message_registry.CLASS_VAR_WITH_TYPEVARS, s) + if not (s.type.args and self.is_self_type(s.type.args[0])): + self.fail(message_registry.CLASS_VAR_WITH_TYPEVARS, s) elif not isinstance(lvalue, MemberExpr) or self.is_self_member_ref(lvalue): # In case of member access, report error only when assigning to self # Other kinds of member assignments should be already reported @@ -3458,6 +3524,14 @@ def is_final_type(self, typ: Optional[Type]) -> bool: return False return sym.node.fullname in FINAL_TYPE_NAMES + def is_self_type(self, typ: Optional[Type]) -> bool: + if not isinstance(typ, UnboundType): + return False + sym = self.lookup_qualified(typ.name, typ) + if not sym or not sym.node: + return False + return sym.node.fullname in SELF_TYPE_NAMES + def fail_invalid_classvar(self, context: Context) -> None: self.fail(message_registry.CLASS_VAR_OUTSIDE_OF_CLASS, context) @@ -5534,7 +5608,10 @@ def has_placeholder(typ: Type) -> bool: return typ.accept(HasPlaceholders()) -def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike: +FunctionLikeT = TypeVar("FunctionLikeT", bound=FunctionLike) + + +def replace_implicit_first_type(sig: FunctionLikeT, new: Type) -> FunctionLikeT: if isinstance(sig, CallableType): if len(sig.arg_types) == 0: return sig diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 8b7b3153ecaf..90b36cbaad52 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -8,7 +8,7 @@ Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, is_named_instance, FunctionLike, TypeOfAny, LiteralType, get_proper_type, TypeAliasType, ParamSpecType, - Parameters, UnpackType, TUPLE_LIKE_INSTANCE_NAMES, TypeVarTupleType, + Parameters, UnpackType, TUPLE_LIKE_INSTANCE_NAMES, TypeVarTupleType, SelfType, ) import mypy.applytype import mypy.constraints @@ -265,6 +265,8 @@ def visit_instance(self, left: Instance) -> bool: right = self.right if isinstance(right, TupleType) and mypy.typeops.tuple_fallback(right).type.is_enum: return self._is_subtype(left, mypy.typeops.tuple_fallback(right)) + if isinstance(right, SelfType): + return self._is_subtype(left, right.upper_bound) if isinstance(right, Instance): if TypeState.is_cached_subtype_check(self._subtype_kind, left, right): return True @@ -336,6 +338,12 @@ def visit_type_var(self, left: TypeVarType) -> bool: return True return self._is_subtype(left.upper_bound, self.right) + def visit_self_type(self, left: SelfType) -> bool: + right = self.right + if isinstance(self.right, SelfType): + right = self.right.upper_bound + return self._is_subtype(left.upper_bound, right) + def visit_param_spec(self, left: ParamSpecType) -> bool: right = self.right if ( diff --git a/mypy/typeanal.py b/mypy/typeanal.py index bd0f684653b2..422521cd9d1b 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -18,7 +18,7 @@ PlaceholderType, Overloaded, get_proper_type, TypeAliasType, RequiredType, TypeVarLikeType, ParamSpecType, ParamSpecFlavor, UnpackType, TypeVarTupleType, callable_with_ellipsis, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, - LITERAL_TYPE_NAMES, ANNOTATED_TYPE_NAMES, + LITERAL_TYPE_NAMES, ANNOTATED_TYPE_NAMES, SelfType, SELF_TYPE_NAMES, ) from mypy.nodes import ( @@ -428,6 +428,17 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt self.fail("NotRequired[] must have exactly one type argument", t) return AnyType(TypeOfAny.from_error) return RequiredType(self.anal_type(t.args[0]), required=False) + elif fullname in SELF_TYPE_NAMES: + from mypy.semanal import SemanticAnalyzer # circular import + + if not isinstance(self.api, SemanticAnalyzer): + self.fail("Self is unbound", t) + return AnyType(TypeOfAny.from_error) + if not isinstance(self.api.type, TypeInfo): + self.fail("Self is not enclosed in a class", t) + return AnyType(TypeOfAny.from_error) + bound = self.named_type(self.api.type.fullname) + return SelfType(fullname, bound, line=t.line, column=t.column) elif self.anal_type_guard_arg(t, fullname) is not None: # In most contexts, TypeGuard[...] acts as an alias for bool (ignoring its args) return self.named_type('builtins.bool') diff --git a/mypy/types.py b/mypy/types.py index f0f7add2d92f..1764ba744ee3 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -116,6 +116,12 @@ 'typing_extensions.Annotated', ) +# Supported Self type names. +SELF_TYPE_NAMES: Final = ( + 'typing.Self', + 'typing_extensions.Self' +) + # We use this constant in various places when checking `tuple` subtyping: TUPLE_LIKE_INSTANCE_NAMES: Final = ( 'builtins.tuple', @@ -549,6 +555,44 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarType': ) +class SelfType(TypeVarType): + __slots__ = () + upper_bound: 'Instance' + + def __init__(self, fullname: str, upper_bound: 'Instance', line: int = -1, column: int = -1) -> None: + super().__init__( + "Self", fullname, -1, [], upper_bound, line=line, column=column + ) + + def accept(self, visitor: 'TypeVisitor[T]') -> T: + from mypy.subtypes import SubtypeVisitor + if isinstance(visitor, (TypeStrVisitor, SubtypeVisitor)): + return visitor.visit_self_type(self) + return super().accept(visitor) + + def __hash__(self) -> int: + return hash(self.upper_bound) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SelfType): + return NotImplemented + return self.upper_bound == other.upper_bound + + def serialize(self) -> JsonDict: + return {'.class': 'SelfType', + 'fullname': self.fullname, + 'upper_bound': self.upper_bound.serialize(), + } + + @classmethod + def deserialize(cls, data: JsonDict) -> 'SelfType': + assert data['.class'] == 'SelfType' + return SelfType( + data['fullname'], + deserialize_type(data['upper_bound']), + ) + + class ParamSpecFlavor: # Simple ParamSpec reference such as "P" BARE: Final = 0 @@ -2659,6 +2703,9 @@ def visit_type_var(self, t: TypeVarType) -> str: s += f'(upper_bound={t.upper_bound.accept(self)})' return s + def visit_self_type(self, t: SelfType) -> str: + return f"Self@{t.upper_bound.accept(self)}" + def visit_param_spec(self, t: ParamSpecType) -> str: # prefixes are displayed as Concatenate s = '' From 3278f5fa1216d0b9b113c38225c193fc3f0321a6 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Fri, 15 Jul 2022 17:12:23 +0100 Subject: [PATCH 02/33] Remove debug print --- mypy/semanal.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index d000aada39bd..7613d695b972 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -712,7 +712,6 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: leading_type = func.type.arg_types[0] proper_leading_type = get_proper_type(leading_type) - print("proper leading type is", proper_leading_type, func) if isinstance(proper_leading_type, Instance): # method[[Self, ...], Self] case proper_leading_type = self_type_type = SelfType("Self", proper_leading_type) func.type = replace_implicit_first_type(func.type, proper_leading_type) From fe0eea78ff32dea526f41e6efa47d8a49f17858c Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Sun, 17 Jul 2022 14:03:38 +0100 Subject: [PATCH 03/33] Fix CI --- mypy/semanal.py | 39 ++++++++++++--------------------------- mypy/subtypes.py | 2 ++ mypy/typeanal.py | 17 +++++++++++------ mypy/types.py | 40 +++++++++++++++++++++++++--------------- 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 7613d695b972..407da54bd25a 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -712,18 +712,17 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: leading_type = func.type.arg_types[0] proper_leading_type = get_proper_type(leading_type) - if isinstance(proper_leading_type, Instance): # method[[Self, ...], Self] case + if isinstance(proper_leading_type, Instance): # method[[Instance, ...], Any] case proper_leading_type = self_type_type = SelfType("Self", proper_leading_type) - func.type = replace_implicit_first_type(func.type, proper_leading_type) + func.type.variables = [self_type_type, *func.type.variables] elif ( isinstance(proper_leading_type, TypeType) and isinstance(proper_leading_type.item, Instance) - ): # classmethod[[type[Self], ...], Self] case + ): # classmethod[[type[Instance], ...], Any] case self_type_type = SelfType("Self", proper_leading_type.item) proper_leading_type = self.class_type(self_type_type) - func.type = replace_implicit_first_type(func.type, proper_leading_type) - elif self.is_self_type(proper_leading_type): + func.type.variables = [self_type_type, *func.type.variables] + elif self.is_self_type(proper_leading_type): # method[[Self, ...], Self] case proper_leading_type = self_type_type = SelfType("Self", self.named_type(info.fullname)) - func.type = replace_implicit_first_type(func.type, proper_leading_type) elif isinstance(proper_leading_type, UnboundType): # classmethod[[type[Self], ...], Self] case node = self.lookup(proper_leading_type.name, func) @@ -735,21 +734,15 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: ): self_type_type = SelfType("Self", self.named_type(info.fullname)) proper_leading_type = self.class_type(self_type_type) - func.type = replace_implicit_first_type(func.type, proper_leading_type) + else: + return + else: + return + func.type = replace_implicit_first_type(func.type, proper_leading_type) - # bind any SelfTypes in args and return types + # bind any SelfTypes in args and return types for idx, arg in enumerate(func.type.arg_types): if self.is_self_type(arg): - if func.is_static: - self.fail( - "Self-type annotations of staticmethods are not supported, " - "please replace the type with {}".format(self_type.type.name), - func - ) - func.type.arg_types[idx] = self.named_type( - self_type.type.name - ) # we replace them here for them - continue if self_type_type.fullname == self_type_type.name: assert isinstance(arg, UnboundType) table_node = self.lookup(arg.name, func) @@ -765,14 +758,6 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: ) assert isinstance(table_node, SymbolTableNode) and table_node.node self_type_type.fullname = table_node.node.fullname - if func.is_static: - self.fail( - "Self-type annotations of staticmethods are not supported, " - "please replace the type with {}".format(self_type.type.name), - func, - ) - func.type.ret_type = self.named_type(self_type.type.name) - return func.type.ret_type = self_type_type def set_original_def(self, previous: Optional[Node], new: Union[FuncDef, Decorator]) -> bool: @@ -5607,7 +5592,7 @@ def has_placeholder(typ: Type) -> bool: return typ.accept(HasPlaceholders()) -FunctionLikeT = TypeVar("FunctionLikeT", bound=FunctionLike) +FunctionLikeT = TypeVar("FunctionLikeT", CallableType, Overloaded) def replace_implicit_first_type(sig: FunctionLikeT, new: Type) -> FunctionLikeT: diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 90b36cbaad52..c528e241693f 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -330,6 +330,8 @@ def visit_instance(self, left: Instance) -> bool: return False def visit_type_var(self, left: TypeVarType) -> bool: + if isinstance(left, SelfType): + return self.visit_self_type(left) right = self.right if isinstance(right, TypeVarType) and left.id == right.id: return True diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 422521cd9d1b..286d856fb7ca 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -1143,11 +1143,16 @@ def bind_function_type_variables( """Find the type variables of the function type and bind them in our tvar_scope""" if fun_type.variables: for var in fun_type.variables: - var_node = self.lookup_qualified(var.name, defn) - assert var_node, "Binding for function type variable not found within function" - var_expr = var_node.node - assert isinstance(var_expr, TypeVarLikeExpr) - self.tvar_scope.bind_new(var.name, var_expr) + if not isinstance(var, SelfType): + var_node = self.lookup_qualified(var.name, defn) + assert var_node, "Binding for function type variable not found within function" + var_expr = var_node.node + # if isinstance(var_expr, Var) and var_expr.fullname in SELF_TYPE_NAMES: + # var_expr = TypeVarExpr("Self", var_expr.fullname, [], var.upper_bound) + assert isinstance(var_expr, TypeVarLikeExpr) + self.tvar_scope.bind_new(var.name, var_expr) + else: + self.tvar_scope.bind_existing(var) return fun_type.variables typevars = self.infer_type_variables(fun_type) # Do not define a new type variable if already defined in scope. @@ -1209,7 +1214,7 @@ def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = Fa return analyzed def anal_var_def(self, var_def: TypeVarLikeType) -> TypeVarLikeType: - if isinstance(var_def, TypeVarType): + if isinstance(var_def, TypeVarType) and not isinstance(var_def, SelfType): return TypeVarType( var_def.name, var_def.fullname, diff --git a/mypy/types.py b/mypy/types.py index 1764ba744ee3..f7c2ee06174c 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -500,7 +500,7 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarLikeType': class TypeVarType(TypeVarLikeType): """Type that refers to a type variable.""" - __slots__ = ('values', 'variance') + __slots__ = ('values', 'variance', 'stack') values: List[Type] # Value restriction, empty list if no restriction variance: int @@ -512,6 +512,7 @@ def __init__(self, name: str, fullname: str, id: Union[TypeVarId, int], values: assert values is not None, "No restrictions must be represented by empty list" self.values = values self.variance = variance + self.stack = inspect.stack() @staticmethod def new_unification_variable(old: 'TypeVarType') -> 'TypeVarType': @@ -555,21 +556,26 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarType': ) +SELF_ID = TypeVarId(0.5) # type: ignore +# this is a hack cause I need a way to represent a number that's constant and can't be +ve or -ve +# and using TypeVarId.new() would quickly hit a huge number which is harder to read. + + class SelfType(TypeVarType): __slots__ = () upper_bound: 'Instance' def __init__(self, fullname: str, upper_bound: 'Instance', line: int = -1, column: int = -1) -> None: super().__init__( - "Self", fullname, -1, [], upper_bound, line=line, column=column + "Self", + fullname, + SELF_ID, + [], + upper_bound, + line=line, + column=column, ) - def accept(self, visitor: 'TypeVisitor[T]') -> T: - from mypy.subtypes import SubtypeVisitor - if isinstance(visitor, (TypeStrVisitor, SubtypeVisitor)): - return visitor.visit_self_type(self) - return super().accept(visitor) - def __hash__(self) -> int: return hash(self.upper_bound) @@ -1119,6 +1125,7 @@ def deserialize(cls, data: JsonDict) -> 'DeletedType': # Fake TypeInfo to be used as a placeholder during Instance de-serialization. NOT_READY: Final = mypy.nodes.FakeInfo("De-serialization failure: TypeInfo not fixed") +import inspect class Instance(ProperType): @@ -1152,12 +1159,13 @@ def try_getting_instance_fallback(typ: ProperType) -> Optional[Instance]: """ - __slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value', '_hash') + __slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value', '_hash', 'stack') def __init__(self, typ: mypy.nodes.TypeInfo, args: Sequence[Type], line: int = -1, column: int = -1, *, last_known_value: Optional['LiteralType'] = None) -> None: super().__init__(line, column) + # self.stack = inspect.stack() self.type = typ self.args = tuple(args) self.type_ref: Optional[str] = None @@ -1516,6 +1524,7 @@ class CallableType(FunctionLike): 'type_guard', # T, if -> TypeGuard[T] (ret_type is bool in this case). 'from_concatenate', # whether this callable is from a concatenate object # (this is used for error messages) + 'stack', ) def __init__(self, @@ -1539,6 +1548,7 @@ def __init__(self, type_guard: Optional[Type] = None, from_concatenate: bool = False ) -> None: + self.stack = inspect.stack() super().__init__(line, column) assert len(arg_types) == len(arg_kinds) == len(arg_names) if variables is None: @@ -2614,12 +2624,10 @@ def get_proper_types(it: Iterable[Optional[Type]] # to make it easier to gradually get modules working with mypyc. # Import them here, after the types are defined. # This is intended as a re-export also. -from mypy.type_visitor import ( # noqa - TypeVisitor as TypeVisitor, - SyntheticTypeVisitor as SyntheticTypeVisitor, - TypeTranslator as TypeTranslator, - TypeQuery as TypeQuery, -) +from mypy.type_visitor import SyntheticTypeVisitor as SyntheticTypeVisitor +from mypy.type_visitor import TypeQuery as TypeQuery +from mypy.type_visitor import TypeTranslator as TypeTranslator +from mypy.type_visitor import TypeVisitor as TypeVisitor # noqa class TypeStrVisitor(SyntheticTypeVisitor[str]): @@ -2693,6 +2701,8 @@ def visit_instance(self, t: Instance) -> str: return s def visit_type_var(self, t: TypeVarType) -> str: + if isinstance(t, SelfType): + return self.visit_self_type(t) if t.name is None: # Anonymous type variable type (only numeric id). s = f'`{t.id}' From 7f5f286437f065c9e18a761a5d1a45b76e922201 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Sun, 17 Jul 2022 19:06:15 +0100 Subject: [PATCH 04/33] Remove calls to inspect.stack() --- mypy/types.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index f7c2ee06174c..dfe5eb61a3de 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -500,7 +500,7 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarLikeType': class TypeVarType(TypeVarLikeType): """Type that refers to a type variable.""" - __slots__ = ('values', 'variance', 'stack') + __slots__ = ('values', 'variance') values: List[Type] # Value restriction, empty list if no restriction variance: int @@ -512,7 +512,6 @@ def __init__(self, name: str, fullname: str, id: Union[TypeVarId, int], values: assert values is not None, "No restrictions must be represented by empty list" self.values = values self.variance = variance - self.stack = inspect.stack() @staticmethod def new_unification_variable(old: 'TypeVarType') -> 'TypeVarType': @@ -1159,13 +1158,12 @@ def try_getting_instance_fallback(typ: ProperType) -> Optional[Instance]: """ - __slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value', '_hash', 'stack') + __slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value', '_hash') def __init__(self, typ: mypy.nodes.TypeInfo, args: Sequence[Type], line: int = -1, column: int = -1, *, last_known_value: Optional['LiteralType'] = None) -> None: super().__init__(line, column) - # self.stack = inspect.stack() self.type = typ self.args = tuple(args) self.type_ref: Optional[str] = None @@ -1524,7 +1522,6 @@ class CallableType(FunctionLike): 'type_guard', # T, if -> TypeGuard[T] (ret_type is bool in this case). 'from_concatenate', # whether this callable is from a concatenate object # (this is used for error messages) - 'stack', ) def __init__(self, @@ -1548,7 +1545,6 @@ def __init__(self, type_guard: Optional[Type] = None, from_concatenate: bool = False ) -> None: - self.stack = inspect.stack() super().__init__(line, column) assert len(arg_types) == len(arg_kinds) == len(arg_names) if variables is None: From 76f216a6590307a5c4694c8566145e1c22cbad91 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Sat, 30 Jul 2022 15:18:53 +0100 Subject: [PATCH 05/33] Fix passing an instance as a SelfType --- mypy/applytype.py | 4 +++- mypy/expandtype.py | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mypy/applytype.py b/mypy/applytype.py index b32b88fa3276..5e514276099b 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -6,7 +6,7 @@ from mypy.types import ( Type, TypeVarId, TypeVarType, CallableType, AnyType, PartialType, get_proper_types, TypeVarLikeType, ProperType, ParamSpecType, Parameters, get_proper_type, - TypeVarTupleType, + TypeVarTupleType, SelfType ) from mypy.nodes import Context @@ -23,6 +23,8 @@ def get_target_type( return type if isinstance(tvar, TypeVarTupleType): return type + if isinstance(tvar, SelfType): + return type assert isinstance(tvar, TypeVarType) values = get_proper_types(tvar.values) if values: diff --git a/mypy/expandtype.py b/mypy/expandtype.py index ce43aeaeb6e5..36080e5757f0 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -6,7 +6,7 @@ ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, FunctionLike, TypeVarType, LiteralType, get_proper_type, ProperType, TypeAliasType, ParamSpecType, TypeVarLikeType, Parameters, ParamSpecFlavor, - UnpackType, TypeVarTupleType + UnpackType, TypeVarTupleType, SelfType ) @@ -44,7 +44,10 @@ def freshen_function_type_vars(callee: F) -> F: for v in callee.variables: # TODO(PEP612): fix for ParamSpecType if isinstance(v, TypeVarType): - tv: TypeVarLikeType = TypeVarType.new_unification_variable(v) + if isinstance(v, SelfType): + tv: TypeVarLikeType = v + else: + tv = TypeVarType.new_unification_variable(v) elif isinstance(v, TypeVarTupleType): tv = TypeVarTupleType.new_unification_variable(v) else: From d8c02db90d76f244eda1f293ef4372e785e8c9b8 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Sat, 30 Jul 2022 15:47:31 +0100 Subject: [PATCH 06/33] Fix CI --- mypy/checkmember.py | 6 +++++- mypy/semanal.py | 4 ++-- mypy/typeanal.py | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index cc6a713e0fb7..7bdec2b23e76 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -4,6 +4,10 @@ from typing_extensions import TYPE_CHECKING +from mypy.erasetype import erase_typevars +from mypy.expandtype import freshen_function_type_vars, expand_type_by_instance +from mypy.maptype import map_instance_to_supertype +from mypy.messages import MessageBuilder from mypy.nodes import ( ARG_POS, ARG_STAR, @@ -66,7 +70,7 @@ if TYPE_CHECKING: # import for forward declaration only import mypy.checker -from mypy import state +from mypy import state, meet, message_registry, subtypes class MemberContext: diff --git a/mypy/semanal.py b/mypy/semanal.py index ae22b2180ebc..6bec0e037f2d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -866,8 +866,8 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: func.is_class = True if not func.arguments: self.fail("Method must have at least one argument", func) - elif isinstance(functype, CallableType): - self_type = get_proper_type(functype.arg_types[0]) + elif isinstance(func.type, CallableType): + self_type = get_proper_type(func.type.arg_types[0]) if isinstance(self_type, AnyType) and not self_type.type_of_any == TypeOfAny.explicit: leading_type: Type = fill_typevars(info) if func.is_class or func.name == "__new__": diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 6590448bf292..75a91e08308b 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -47,7 +47,7 @@ FINAL_TYPE_NAMES, LITERAL_TYPE_NAMES, NEVER_NAMES, - SELF_TYPE_NAMES + SELF_TYPE_NAMES, TYPE_ALIAS_NAMES, AnyType, CallableArgument, From 3159549e1849f37730a60380052d1cfe06a062b4 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 1 Aug 2022 12:46:56 +0100 Subject: [PATCH 07/33] Fix joining for obj if bool else self --- mypy/join.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mypy/join.py b/mypy/join.py index 31f31ed88714..1e7836711b0d 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -29,6 +29,7 @@ PartialType, PlaceholderType, ProperType, + SelfType, TupleType, Type, TypeAliasType, @@ -278,6 +279,8 @@ def visit_erased_type(self, t: ErasedType) -> ProperType: return self.s def visit_type_var(self, t: TypeVarType) -> ProperType: + if isinstance(t, SelfType) and isinstance(self.s, Instance) and is_subtype(self.s, t): + return mypy.typeops.make_simplified_union([self.s, t]) if isinstance(self.s, TypeVarType) and self.s.id == t.id: return self.s else: From f031af7f8d41ca461b77af481f2db03d5147627e Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 1 Aug 2022 12:59:43 +0100 Subject: [PATCH 08/33] Fix accessing an instance on cls --- mypy/checkmember.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 7bdec2b23e76..5516e582dd26 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -5,7 +5,7 @@ from typing_extensions import TYPE_CHECKING from mypy.erasetype import erase_typevars -from mypy.expandtype import freshen_function_type_vars, expand_type_by_instance +from mypy.expandtype import expand_type_by_instance, freshen_function_type_vars from mypy.maptype import map_instance_to_supertype from mypy.messages import MessageBuilder from mypy.nodes import ( @@ -70,7 +70,7 @@ if TYPE_CHECKING: # import for forward declaration only import mypy.checker -from mypy import state, meet, message_registry, subtypes +from mypy import meet, message_registry, state, subtypes class MemberContext: @@ -910,6 +910,9 @@ def analyze_class_attribute_access( # Exception: access on Type[...], including first argument of class methods is OK. if isinstance(t, SelfType): return mx.named_type(info.fullname) + if isinstance(t, UnionType): + if any(isinstance(item, SelfType) for item in t.items): + return make_simplified_union(t.items + [mx.named_type(info.fullname)]) elif not isinstance(get_proper_type(mx.original_type), TypeType) or node.implicit: if node.node.is_classvar: message = message_registry.GENERIC_CLASS_VAR_ACCESS From ab62d9301fac63bb52876ff54ec73f459f22cbd6 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 1 Aug 2022 14:46:10 +0100 Subject: [PATCH 09/33] Fix joining the other way round --- mypy/join.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mypy/join.py b/mypy/join.py index 1e7836711b0d..23af5c6221fe 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -335,6 +335,8 @@ def visit_instance(self, t: Instance) -> ProperType: return join_types(t, self.s) elif isinstance(self.s, LiteralType): return join_types(t, self.s) + elif isinstance(self.s, SelfType): + return join_types(t, self.s) else: return self.default(self.s) From 823168b06db314be74678a83d2a7fd83137ed783 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 1 Aug 2022 14:49:18 +0100 Subject: [PATCH 10/33] Show the name that's not found --- mypy/checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index c691a3e9ab0d..ef95720e71e4 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -5792,7 +5792,7 @@ def lookup_qualified(self, name: str) -> SymbolTableNode: n = self.modules[parts[0]] for i in range(1, len(parts) - 1): sym = n.names.get(parts[i]) - assert sym is not None, "Internal error: attempted lookup of unknown name" + assert sym is not None, f"Internal error: attempted lookup of unknown name {name!r}" n = cast(MypyFile, sym.node) last = parts[-1] if last in n.names: From c8e9407bf9383c294d622373ce424ac10d279da6 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 8 Aug 2022 10:59:23 +0100 Subject: [PATCH 11/33] I have no clue what's going on here --- mypy/checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index cf0d4178a560..0fc5fd82d878 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -5753,7 +5753,7 @@ def lookup_qualified(self, name: str) -> SymbolTableNode: n = self.modules[parts[0]] for i in range(1, len(parts) - 1): sym = n.names.get(parts[i]) - assert sym is not None, f"Internal error: attempted lookup of unknown name {name!r}" + assert sym is not None, f"Internal error: attempted lookup of unknown name {name!r} {n} {self.modules}" n = cast(MypyFile, sym.node) last = parts[-1] if last in n.names: From 39c208da50c75e4d00708170f114fcdd859c0eea Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 8 Aug 2022 12:03:51 +0100 Subject: [PATCH 12/33] So it's fine in modules but the name just isn't present??? --- mypy/checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index 0fc5fd82d878..1aaaa129e8e7 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -5753,7 +5753,7 @@ def lookup_qualified(self, name: str) -> SymbolTableNode: n = self.modules[parts[0]] for i in range(1, len(parts) - 1): sym = n.names.get(parts[i]) - assert sym is not None, f"Internal error: attempted lookup of unknown name {name!r} {n} {self.modules}" + assert sym is not None, f"Internal error: attempted lookup of unknown name {name!r} {n.names}" n = cast(MypyFile, sym.node) last = parts[-1] if last in n.names: From f05cfeca89c0abe093ec919d33e28868e967f27f Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 8 Aug 2022 13:06:37 +0100 Subject: [PATCH 13/33] I'm just going to leave it and construct the Instance myself --- mypy/checkmember.py | 11 ++++++----- mypy/types.py | 9 +++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 5516e582dd26..0e439114de04 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -64,6 +64,7 @@ TypeVarType, UnionType, get_proper_type, + has_self_types, has_type_vars, ) @@ -908,11 +909,11 @@ def analyze_class_attribute_access( # C[int].x # Also an error, since C[int] is same as C at runtime if isinstance(t, TypeVarType) or has_type_vars(t): # Exception: access on Type[...], including first argument of class methods is OK. - if isinstance(t, SelfType): - return mx.named_type(info.fullname) - if isinstance(t, UnionType): - if any(isinstance(item, SelfType) for item in t.items): - return make_simplified_union(t.items + [mx.named_type(info.fullname)]) + if has_self_types(t): + any = AnyType(TypeOfAny.from_omitted_generics) + return make_simplified_union( + [t, Instance(info, [any] * len(info.defn.type_vars))] + ) # TODO look into why we can't use named_type here elif not isinstance(get_proper_type(mx.original_type), TypeType) or node.implicit: if node.node.is_classvar: message = message_registry.GENERIC_CLASS_VAR_ACCESS diff --git a/mypy/types.py b/mypy/types.py index 76c070230487..87a10f315508 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -3202,6 +3202,15 @@ def has_type_vars(typ: Type) -> bool: return typ.accept(HasTypeVars()) +class HasSelfTypes(HasTypeVars): + def visit_type_var(self, t: TypeVarType) -> bool: + return isinstance(t, SelfType) + + +def has_self_types(typ: Type) -> bool: + return typ.accept(HasSelfTypes()) + + class HasRecursiveType(TypeQuery[bool]): def __init__(self) -> None: super().__init__(any) From 6e16093d41bacb11bf070ee206dcaf91cbe65271 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Thu, 11 Aug 2022 14:43:20 +0100 Subject: [PATCH 14/33] Fix a bit of CI --- mypy/checker.py | 2 +- mypy/checkmember.py | 6 +++--- mypy/messages.py | 4 ++++ mypy/semanal.py | 13 +++++++++---- mypy/types.py | 29 +++++++++++++---------------- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 6406aa4b9b42..066cdeafda7a 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -5753,7 +5753,7 @@ def lookup_qualified(self, name: str) -> SymbolTableNode: n = self.modules[parts[0]] for i in range(1, len(parts) - 1): sym = n.names.get(parts[i]) - assert sym is not None, f"Internal error: attempted lookup of unknown name {name!r} {n.names}" + assert sym is not None, f"Internal error: attempted lookup of unknown name" n = cast(MypyFile, sym.node) last = parts[-1] if last in n.names: diff --git a/mypy/checkmember.py b/mypy/checkmember.py index c97cc91cc0ef..9b0a95747242 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -569,9 +569,9 @@ def analyze_descriptor_access(descriptor_type: Type, mx: MemberContext) -> Type: if isinstance(descriptor_type, UnionType): # Map the access over union types - return make_simplified_union([ - analyze_descriptor_access(typ, mx) for typ in descriptor_type.items - ]) + return make_simplified_union( + [analyze_descriptor_access(typ, mx) for typ in descriptor_type.items] + ) elif isinstance(descriptor_type, SelfType): return instance_type elif not isinstance(descriptor_type, Instance): diff --git a/mypy/messages.py b/mypy/messages.py index 8214455a12c6..4c1b89bd18ae 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -412,6 +412,10 @@ def has_no_attr( extra = " (not async iterable)" if not self.are_type_names_disabled(): failed = False + if isinstance(original_type, TypeVarType) and isinstance( + original_type.upper_bound, Instance + ): + original_type = original_type.upper_bound if isinstance(original_type, Instance) and original_type.type.names: alternatives = set(original_type.type.names.keys()) diff --git a/mypy/semanal.py b/mypy/semanal.py index 39cf5177aa8b..94f9b1c3c444 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -894,7 +894,10 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: self.fail("Method must have at least one argument", func) elif isinstance(func.type, CallableType): self_type = get_proper_type(func.type.arg_types[0]) - if isinstance(self_type, AnyType) and not self_type.type_of_any == TypeOfAny.explicit: + if ( + isinstance(self_type, AnyType) + and not self_type.type_of_any == TypeOfAny.explicit + ): leading_type: Type = fill_typevars(info) if func.is_class or func.name == "__new__": leading_type = self.class_type(leading_type) @@ -905,14 +908,16 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: if isinstance(proper_leading_type, Instance): # method[[Instance, ...], Any] case proper_leading_type = self_type_type = SelfType("Self", proper_leading_type) func.type.variables = [self_type_type, *func.type.variables] - elif ( - isinstance(proper_leading_type, TypeType) and isinstance(proper_leading_type.item, Instance) + elif isinstance(proper_leading_type, TypeType) and isinstance( + proper_leading_type.item, Instance ): # classmethod[[type[Instance], ...], Any] case self_type_type = SelfType("Self", proper_leading_type.item) proper_leading_type = self.class_type(self_type_type) func.type.variables = [self_type_type, *func.type.variables] elif self.is_self_type(proper_leading_type): # method[[Self, ...], Self] case - proper_leading_type = self_type_type = SelfType("Self", self.named_type(info.fullname)) + proper_leading_type = self_type_type = SelfType( + "Self", self.named_type(info.fullname) + ) elif isinstance(proper_leading_type, UnboundType): # classmethod[[type[Self], ...], Self] case node = self.lookup(proper_leading_type.name, func) diff --git a/mypy/types.py b/mypy/types.py index 899ae5c08db2..04b98c904609 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -116,10 +116,7 @@ ANNOTATED_TYPE_NAMES: Final = ("typing.Annotated", "typing_extensions.Annotated") # Supported Self type names. -SELF_TYPE_NAMES: Final = ( - 'typing.Self', - 'typing_extensions.Self' -) +SELF_TYPE_NAMES: Final = ("typing.Self", "typing_extensions.Self") # We use this constant in various places when checking `tuple` subtyping: TUPLE_LIKE_INSTANCE_NAMES: Final = ( @@ -579,9 +576,11 @@ def deserialize(cls, data: JsonDict) -> "TypeVarType": class SelfType(TypeVarType): __slots__ = () - upper_bound: 'Instance' + upper_bound: "Instance" - def __init__(self, fullname: str, upper_bound: 'Instance', line: int = -1, column: int = -1) -> None: + def __init__( + self, fullname: str, upper_bound: "Instance", line: int = -1, column: int = -1 + ) -> None: super().__init__( "Self", fullname, @@ -601,18 +600,16 @@ def __eq__(self, other: object) -> bool: return self.upper_bound == other.upper_bound def serialize(self) -> JsonDict: - return {'.class': 'SelfType', - 'fullname': self.fullname, - 'upper_bound': self.upper_bound.serialize(), - } + return { + ".class": "SelfType", + "fullname": self.fullname, + "upper_bound": self.upper_bound.serialize(), + } @classmethod - def deserialize(cls, data: JsonDict) -> 'SelfType': - assert data['.class'] == 'SelfType' - return SelfType( - data['fullname'], - deserialize_type(data['upper_bound']), - ) + def deserialize(cls, data: JsonDict) -> "SelfType": + assert data[".class"] == "SelfType" + return SelfType(data["fullname"], deserialize_type(data["upper_bound"])) class ParamSpecFlavor: From 0c5c26f049b4ced05ff4ef5c8a09f784f4c15d9d Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Thu, 11 Aug 2022 15:22:30 +0100 Subject: [PATCH 15/33] Fix more CI --- mypy/semanal.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mypy/semanal.py b/mypy/semanal.py index 94f9b1c3c444..abdc3a29c3c8 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -226,6 +226,7 @@ ) from mypy.semanal_typeddict import TypedDictAnalyzer from mypy.tvar_scope import TypeVarLikeScope +from mypy.type_visitor import TypeQuery from mypy.typeanal import ( TypeAnalyser, TypeVarLikeList, From 6f29a2f362f5f47d105cd816acf48e626ac046c7 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Sat, 13 Aug 2022 17:03:22 +0100 Subject: [PATCH 16/33] Fix constraints --- mypy/expandtype.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 1a2e42b186eb..b57ca6e9d29f 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -143,6 +143,9 @@ def visit_instance(self, t: Instance) -> Type: return args def visit_type_var(self, t: TypeVarType) -> Type: + if isinstance(t, SelfType): + return expand_type(t.upper_bound, self.variables) + repl = self.variables.get(t.id, t) if isinstance(repl, ProperType) and isinstance(repl, Instance): # TODO: do we really need to do this? From 379c66209dbf71dce2d1bdc94d13bcf30da47950 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 15 Aug 2022 14:09:04 +0100 Subject: [PATCH 17/33] Fix bug with typeddict narrowing Also reduced pointless changes diff --- mypy/checker.py | 4 ++-- mypy/plugins/default.py | 2 +- mypy/typeanal.py | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 2d8b6668a12a..81242d8ae454 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1329,7 +1329,7 @@ def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None: "but must return a subtype of", ) elif not isinstance( - get_proper_type(bound_type.ret_type), (AnyType, Instance, TupleType, SelfType) + get_proper_type(bound_type.ret_type), (AnyType, Instance, TupleType) ): self.fail( message_registry.NON_INSTANCE_NEW_TYPE.format(format_type(bound_type.ret_type)), @@ -5761,7 +5761,7 @@ def lookup_qualified(self, name: str) -> SymbolTableNode: n = self.modules[parts[0]] for i in range(1, len(parts) - 1): sym = n.names.get(parts[i]) - assert sym is not None, f"Internal error: attempted lookup of unknown name" + assert sym is not None, "Internal error: attempted lookup of unknown name" n = cast(MypyFile, sym.node) last = parts[-1] if last in n.names: diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index 64d93d8e5b30..362e1027883a 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -182,7 +182,7 @@ def typed_dict_get_signature_callback(ctx: MethodSigContext) -> CallableType: and len(ctx.args[0]) == 1 and isinstance(ctx.args[0][0], StrExpr) and len(signature.arg_types) == 2 - and len(signature.variables) == 1 + and len(signature.variables) == 2 and len(ctx.args[1]) == 1 ): key = ctx.args[0][0].value diff --git a/mypy/typeanal.py b/mypy/typeanal.py index bc434e78429c..025268b30df7 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -1299,10 +1299,11 @@ def bind_function_type_variables( for var in fun_type.variables: if not isinstance(var, SelfType): var_node = self.lookup_qualified(var.name, defn) + assert var_node, "Binding for function type variable not found within function" + var_expr = var_node.node - # if isinstance(var_expr, Var) and var_expr.fullname in SELF_TYPE_NAMES: - # var_expr = TypeVarExpr("Self", var_expr.fullname, [], var.upper_bound) + assert isinstance(var_expr, TypeVarLikeExpr) self.tvar_scope.bind_new(var.name, var_expr) else: From af3241c0f6e84088a4648555ee88b7e98b1a70f6 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 15 Aug 2022 14:11:02 +0100 Subject: [PATCH 18/33] Run black --- mypy/checker.py | 4 +--- mypy/types.py | 10 +--------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 81242d8ae454..8866882ec82f 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1328,9 +1328,7 @@ def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None: "returns", "but must return a subtype of", ) - elif not isinstance( - get_proper_type(bound_type.ret_type), (AnyType, Instance, TupleType) - ): + elif not isinstance(get_proper_type(bound_type.ret_type), (AnyType, Instance, TupleType)): self.fail( message_registry.NON_INSTANCE_NEW_TYPE.format(format_type(bound_type.ret_type)), fdef, diff --git a/mypy/types.py b/mypy/types.py index 6082820a2ded..1e205b929cfb 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -581,15 +581,7 @@ class SelfType(TypeVarType): def __init__( self, fullname: str, upper_bound: "Instance", line: int = -1, column: int = -1 ) -> None: - super().__init__( - "Self", - fullname, - SELF_ID, - [], - upper_bound, - line=line, - column=column, - ) + super().__init__("Self", fullname, SELF_ID, [], upper_bound, line=line, column=column) def __hash__(self) -> int: return hash(self.upper_bound) From dc93feb87ae8faf45e12f38f77b0554815929d17 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 15 Aug 2022 14:16:34 +0100 Subject: [PATCH 19/33] Fix flake8 warnings --- mypy/applytype.py | 1 - mypy/checker.py | 1 - mypy/semanal.py | 14 -------------- mypy/types.py | 1 - 4 files changed, 17 deletions(-) diff --git a/mypy/applytype.py b/mypy/applytype.py index 2c05b9abc112..f98264b68f5d 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -9,7 +9,6 @@ Parameters, ParamSpecType, PartialType, - ProperType, SelfType, Type, TypeVarId, diff --git a/mypy/checker.py b/mypy/checker.py index 8866882ec82f..bc9bdf5390ec 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -183,7 +183,6 @@ ParamSpecType, PartialType, ProperType, - SelfType, StarType, TupleType, Type, diff --git a/mypy/semanal.py b/mypy/semanal.py index eef45e5e3451..d67b3e27a70f 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -255,7 +255,6 @@ TYPED_NAMEDTUPLE_NAMES, AnyType, CallableType, - FunctionLike, Instance, LiteralType, LiteralValue, @@ -6096,19 +6095,6 @@ def is_future_flag_set(self, flag: str) -> bool: return self.modules[self.cur_mod_id].is_future_flag_set(flag) -class HasPlaceholders(TypeQuery[bool]): - def __init__(self) -> None: - super().__init__(any) - - def visit_placeholder_type(self, t: PlaceholderType) -> bool: - return True - - -def has_placeholder(typ: Type) -> bool: - """Check if a type contains any placeholder types (recursively).""" - return typ.accept(HasPlaceholders()) - - FunctionLikeT = TypeVar("FunctionLikeT", CallableType, Overloaded) diff --git a/mypy/types.py b/mypy/types.py index 1e205b929cfb..47f681baf712 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1192,7 +1192,6 @@ def deserialize(cls, data: JsonDict) -> "DeletedType": # Fake TypeInfo to be used as a placeholder during Instance de-serialization. NOT_READY: Final = mypy.nodes.FakeInfo("De-serialization failure: TypeInfo not fixed") -import inspect class Instance(ProperType): From e01690b7c55b1f9463fdd9053e048b38cfdec886 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Mon, 15 Aug 2022 15:22:50 +0100 Subject: [PATCH 20/33] More typeddict fixes --- mypy/plugins/default.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index 362e1027883a..5fe5dac989f4 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -200,7 +200,7 @@ def typed_dict_get_signature_callback(ctx: MethodSigContext) -> CallableType: # Tweak the signature to include the value type as context. It's # only needed for type inference since there's a union with a type # variable that accepts everything. - tv = signature.variables[0] + tv = signature.variables[1] assert isinstance(tv, TypeVarType) return signature.copy_modified( arg_types=[signature.arg_types[0], make_simplified_union([value_type, tv])], @@ -262,7 +262,7 @@ def typed_dict_pop_signature_callback(ctx: MethodSigContext) -> CallableType: and len(ctx.args[0]) == 1 and isinstance(ctx.args[0][0], StrExpr) and len(signature.arg_types) == 2 - and len(signature.variables) == 1 + and len(signature.variables) == 2 and len(ctx.args[1]) == 1 ): key = ctx.args[0][0].value @@ -271,7 +271,7 @@ def typed_dict_pop_signature_callback(ctx: MethodSigContext) -> CallableType: # Tweak the signature to include the value type as context. It's # only needed for type inference since there's a union with a type # variable that accepts everything. - tv = signature.variables[0] + tv = signature.variables[1] assert isinstance(tv, TypeVarType) typ = make_simplified_union([value_type, tv]) return signature.copy_modified(arg_types=[str_type, typ], ret_type=typ) From 87a4cdf3955648975cd6c1177833b42b5483d334 Mon Sep 17 00:00:00 2001 From: James Hilton-Balfe Date: Tue, 30 Aug 2022 15:37:55 +0100 Subject: [PATCH 21/33] Fix more CI issues --- mypy/plugins/enums.py | 36 ++++++++++++++++-------------------- mypy/subtypes.py | 4 ++-- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/mypy/plugins/enums.py b/mypy/plugins/enums.py index f1d4fb8f0fe4..918f8b904d6b 100644 --- a/mypy/plugins/enums.py +++ b/mypy/plugins/enums.py @@ -12,7 +12,7 @@ """ from __future__ import annotations -from typing import Iterable, Optional, Sequence, TypeVar, cast +from typing import Optional, Sequence, TypeVar, cast from typing_extensions import Final import mypy.plugin # To avoid circular imports. @@ -20,7 +20,7 @@ from mypy.semanal_enum import ENUM_BASES from mypy.subtypes import is_equivalent from mypy.typeops import make_simplified_union -from mypy.types import CallableType, Instance, LiteralType, ProperType, Type, get_proper_type +from mypy.types import CallableType, Instance, LiteralType, ProperType, Type, get_proper_type, SelfType ENUM_NAME_ACCESS: Final = {f"{prefix}.name" for prefix in ENUM_BASES} | { f"{prefix}._name_" for prefix in ENUM_BASES @@ -57,16 +57,6 @@ def enum_name_callback(ctx: "mypy.plugin.AttributeContext") -> Type: _T = TypeVar("_T") -def _first(it: Iterable[_T]) -> Optional[_T]: - """Return the first value from any iterable. - - Returns ``None`` if the iterable is empty. - """ - for val in it: - return val - return None - - def _infer_value_type_with_auto_fallback( ctx: "mypy.plugin.AttributeContext", proper_type: Optional[ProperType] ) -> Optional[Type]: @@ -86,7 +76,7 @@ def _infer_value_type_with_auto_fallback( # `_generate_next_value_` is `Any`. In reality the default `auto()` # returns an `int` (presumably the `Any` in typeshed is to make it # easier to subclass and change the returned type). - type_with_gnv = _first(ti for ti in info.mro if ti.names.get("_generate_next_value_")) + type_with_gnv = next((ti for ti in info.mro if ti.names.get("_generate_next_value_")), None) if type_with_gnv is None: return ctx.default_attr_type @@ -107,10 +97,13 @@ def _implements_new(info: TypeInfo) -> bool: subclass. In the latter case, we must infer Any as long as mypy can't infer the type of _value_ from assignments in __new__. """ - type_with_new = _first( - ti - for ti in info.mro - if ti.names.get("__new__") and not ti.fullname.startswith("builtins.") + type_with_new = next( + ( + ti + for ti in info.mro + if ti.names.get("__new__") and not ti.fullname.startswith("builtins.") + ), + None, ) if type_with_new is None: return False @@ -147,8 +140,11 @@ class SomeEnum: # however, if we can prove that the all of the enum members have the # same value-type, then it doesn't matter which member was passed in. # The value-type is still known. - if isinstance(ctx.type, Instance): - info = ctx.type.type + ctx_type = ctx.type + if isinstance(ctx_type, SelfType): + ctx_type = ctx_type.upper_bound + if isinstance(ctx_type, Instance): + info = ctx_type.type # As long as mypy doesn't understand attribute creation in __new__, # there is no way to predict the value type if the enum class has a @@ -171,7 +167,7 @@ class SomeEnum: for t in node_types if t is None or not isinstance(t, CallableType) ) - underlying_type = _first(proper_types) + underlying_type = next(iter(proper_types), None) if underlying_type is None: return ctx.default_attr_type diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 7b52ad2da90a..3ddc7477a38d 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -574,8 +574,8 @@ def visit_type_var(self, left: TypeVarType) -> bool: def visit_self_type(self, left: SelfType) -> bool: right = self.right - if isinstance(self.right, SelfType): - right = self.right.upper_bound + if isinstance(right, SelfType): + right = right.upper_bound return self._is_subtype(left.upper_bound, right) def visit_param_spec(self, left: ParamSpecType) -> bool: From 93a96ff0e884da546e9f02ea5cef0f5bd76c1334 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Sun, 11 Sep 2022 14:16:15 +0100 Subject: [PATCH 22/33] Avoid printing Self in signatures --- mypy/types.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/types.py b/mypy/types.py index c7cc997a7ac2..f98b019dc07a 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -3064,7 +3064,9 @@ def visit_callable_type(self, t: CallableType) -> str: if t.variables: vs = [] for var in t.variables: - if isinstance(var, TypeVarType): + if isinstance(var, SelfType): + pass # purposely skip printing self type + elif isinstance(var, TypeVarType): # We reimplement TypeVarType.__repr__ here in order to support id_mapper. if var.values: vals = f"({', '.join(val.accept(self) for val in var.values)})" From 1ede2812a85405e420a570cf4ce42423b2349bd3 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Tue, 13 Sep 2022 01:25:37 +0100 Subject: [PATCH 23/33] fix more tests --- mypy/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/types.py b/mypy/types.py index f98b019dc07a..5eebbf9f803b 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -3078,7 +3078,7 @@ def visit_callable_type(self, t: CallableType) -> str: else: # For other TypeVarLikeTypes, just use the name vs.append(var.name) - s = f"[{', '.join(vs)}] {s}" + s = f"[{', '.join(vs)}] {s}" if vs else s return f"def {s}" From 2f02d13e893e751940b8ee6be48b5dcccc45d934 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Tue, 13 Sep 2022 15:34:47 +0100 Subject: [PATCH 24/33] Fix attribute error message for TypeVars --- mypy/messages.py | 3 ++- mypy/plugins/enums.py | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index dc3688a535f3..7fddb6b16e37 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -74,6 +74,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, TupleType, Type, TypeAliasType, @@ -406,7 +407,7 @@ def has_no_attr( extra = " (not async iterable)" if not self.are_type_names_disabled(): failed = False - if isinstance(original_type, TypeVarType) and isinstance( + if isinstance(original_type, SelfType) and isinstance( original_type.upper_bound, Instance ): original_type = original_type.upper_bound diff --git a/mypy/plugins/enums.py b/mypy/plugins/enums.py index 3b3732fb5b10..e4e9611376b9 100644 --- a/mypy/plugins/enums.py +++ b/mypy/plugins/enums.py @@ -20,7 +20,15 @@ from mypy.semanal_enum import ENUM_BASES from mypy.subtypes import is_equivalent from mypy.typeops import make_simplified_union -from mypy.types import CallableType, Instance, LiteralType, ProperType, Type, get_proper_type, SelfType +from mypy.types import ( + CallableType, + Instance, + LiteralType, + ProperType, + Type, + get_proper_type, + SelfType, +) ENUM_NAME_ACCESS: Final = {f"{prefix}.name" for prefix in ENUM_BASES} | { f"{prefix}._name_" for prefix in ENUM_BASES From bf54da0d7990d8715a0bc95317e1ebe5b7c658aa Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Sat, 17 Sep 2022 00:38:11 +0100 Subject: [PATCH 25/33] Fix more reprs --- mypy/messages.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/messages.py b/mypy/messages.py index 7fddb6b16e37..525273304584 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -2525,7 +2525,9 @@ def [T <: int] f(self, x: int, y: T) -> None if tp.variables: tvars = [] for tvar in tp.variables: - if isinstance(tvar, TypeVarType): + if isinstance(tvar, SelfType): + pass + elif isinstance(tvar, TypeVarType): upper_bound = get_proper_type(tvar.upper_bound) if ( isinstance(upper_bound, Instance) From 2be7770d0933c26ee8d6aa289dbf664a4e0c3b6d Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Sat, 17 Sep 2022 15:39:03 +0100 Subject: [PATCH 26/33] Fix more CI --- mypy/checkexpr.py | 3 +++ mypy/messages.py | 6 ++++-- mypy/plugins/enums.py | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index fba6caec4072..4f23a8ca89ae 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -138,6 +138,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, StarType, TupleType, Type, @@ -1959,6 +1960,8 @@ def check_for_extra_actual_arguments( def missing_classvar_callable_note( self, object_type: Type, callable_name: str, context: Context ) -> None: + if isinstance(object_type, SelfType): + object_type = object_type.upper_bound if isinstance(object_type, ProperType) and isinstance(object_type, Instance): _, var_name = callable_name.rsplit(".", maxsplit=1) node = object_type.type.get(var_name) diff --git a/mypy/messages.py b/mypy/messages.py index 525273304584..83eef8e168b9 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1223,7 +1223,7 @@ def undefined_in_superclass(self, member: str, context: Context) -> None: def first_argument_for_super_must_be_type(self, actual: Type, context: Context) -> None: actual = get_proper_type(actual) - if isinstance(actual, Instance): + if isinstance(actual, (Instance, SelfType)): # Don't include type of instance, because it can look confusingly like a type # object. type_str = "a non-type instance" @@ -1829,6 +1829,8 @@ def report_protocol_problems( class_obj = False is_module = False + if isinstance(subtype, SelfType): + subtype = subtype.upper_bound if isinstance(subtype, TupleType): if not isinstance(subtype.partial_fallback, Instance): return @@ -2545,7 +2547,7 @@ def [T <: int] f(self, x: int, y: T) -> None else: # For other TypeVarLikeTypes, just use the repr tvars.append(repr(tvar)) - s = f"[{', '.join(tvars)}] {s}" + s = f"[{', '.join(tvars)}] {s}" if tvars else s return f"def {s}" diff --git a/mypy/plugins/enums.py b/mypy/plugins/enums.py index e4e9611376b9..c4de60a1effa 100644 --- a/mypy/plugins/enums.py +++ b/mypy/plugins/enums.py @@ -25,9 +25,9 @@ Instance, LiteralType, ProperType, + SelfType, Type, get_proper_type, - SelfType, ) ENUM_NAME_ACCESS: Final = {f"{prefix}.name" for prefix in ENUM_BASES} | { From cf6ac9b6b7d6ef4e7027cd8a6e7a84b6824d6860 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Mon, 19 Sep 2022 18:46:32 +0100 Subject: [PATCH 27/33] Fix some tests --- test-data/unit/check-protocols.test | 4 ++-- test-data/unit/merge.test | 4 ++-- test-data/unit/semanal-classes.test | 8 ++++---- test-data/unit/semanal-types.test | 10 +++++----- test-data/unit/typexport-basic.test | 14 +++++++------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index 3302fd4402b3..5b5f00016600 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -3297,9 +3297,9 @@ test(C) # E: Argument 1 to "test" has incompatible type "Type[C]"; expected "P" # N: def foo(obj: Any, arg: str) -> str \ # N: Got: \ # N: @overload \ - # N: def foo(self: C, arg: int) -> int \ + # N: def foo(self: Self@C, arg: int) -> int \ # N: @overload \ - # N: def foo(self: C, arg: str) -> int + # N: def foo(self: Self@C, arg: str) -> int [case testProtocolClassObjectClassMethod] from typing import Protocol diff --git a/test-data/unit/merge.test b/test-data/unit/merge.test index a593a064cbb2..e400c763eefa 100644 --- a/test-data/unit/merge.test +++ b/test-data/unit/merge.test @@ -76,7 +76,7 @@ MypyFile:1<1>( Args( Var(self) Var(x)) - def (self: target.A<4>, x: builtins.str<5>) -> builtins.int<6> + def (self: Self@target.A<4>, x: builtins.str<5>) -> builtins.int<6> Block:2<7>( PassStmt:3<8>())))) ==> @@ -92,7 +92,7 @@ MypyFile:1<1>( Args( Var(self) Var(x)) - def (self: target.A<4>, x: builtins.int<6>) -> builtins.str<5> + def (self: Self@target.A<4>, x: builtins.int<6>) -> builtins.str<5> Block:2<10>( PassStmt:3<11>())))) diff --git a/test-data/unit/semanal-classes.test b/test-data/unit/semanal-classes.test index 082a3fe69050..bc4c008acd78 100644 --- a/test-data/unit/semanal-classes.test +++ b/test-data/unit/semanal-classes.test @@ -202,8 +202,8 @@ MypyFile:1( Block:7( ExpressionStmt:7( NameExpr(self [l])))) - Overload(def (self: __main__.A), \ - def (self: __main__.A, x: __main__.A)) + Overload(def (self: Self@__main__.A), \ + def (self: Self@__main__.A, x: __main__.A)) Decorator:3( Var(f) NameExpr(overload [typing.overload]) @@ -223,7 +223,7 @@ MypyFile:1( Args( Var(self) Var(x)) - def (self: __main__.A, x: __main__.A) + def (self: Self@__main__.A, x: __main__.A) Block:6( ExpressionStmt:6( NameExpr(self [l])))))))) @@ -550,7 +550,7 @@ MypyFile:1( default( Var(x) NameExpr(X [__main__.A.X]))) - def (self: __main__.A, x: builtins.int =) + def (self: Self@__main__.A, x: builtins.int =) Block:4( PassStmt:4())))) diff --git a/test-data/unit/semanal-types.test b/test-data/unit/semanal-types.test index d832772f5f81..2f2e3fe59d22 100644 --- a/test-data/unit/semanal-types.test +++ b/test-data/unit/semanal-types.test @@ -573,7 +573,7 @@ MypyFile:1( Args( Var(self) Var(o)) - def (self: __main__.A, o: builtins.object) + def (self: Self@__main__.A, o: builtins.object) Block:2( PassStmt:2())))) @@ -650,7 +650,7 @@ MypyFile:1( Args( Var(self) Var(x)) - def (self: __main__.c[t`1, s`2], x: s`2) -> t`1 + def (self: Self@__main__.c[t`1, s`2], x: s`2) -> t`1 Block:7( PassStmt:7())))) @@ -1141,7 +1141,7 @@ MypyFile:1( Args( Var(self) Var(x)) - def [T] (self: __main__.A, x: T`-1) -> T`-1 + def [T] (self: Self@__main__.A, x: T`-1) -> T`-1 Block:4( PassStmt:4())))) @@ -1193,7 +1193,7 @@ MypyFile:1( Args( Var(self) Var(x)) - def (self: __main__.A[_m.T`1], x: _m.T`1) -> Any + def (self: Self@__main__.A[_m.T`1], x: _m.T`1) -> Any Block:5( AssignmentStmt:6( NameExpr(b [l]) @@ -1253,7 +1253,7 @@ MypyFile:1( Args( Var(self) Var(x)) - def (self: __main__.A, x: builtins.int) -> builtins.str + def (self: Self@__main__.A, x: builtins.int) -> builtins.str Block:3( AssignmentStmt:4( NameExpr(x [l]) diff --git a/test-data/unit/typexport-basic.test b/test-data/unit/typexport-basic.test index 5cbdf38d1b4f..22a53e0ba2ff 100644 --- a/test-data/unit/typexport-basic.test +++ b/test-data/unit/typexport-basic.test @@ -927,7 +927,7 @@ class A: A.f [builtins fixtures/tuple.pyi] [out] -MemberExpr(10) : Overload(def (self: A), def (self: A, builtins.object)) +MemberExpr(10) : Overload(def (self: Self@A), def (self: A, builtins.object)) [case testOverloadedUnboundMethodWithImplicitSig] ## MemberExpr @@ -942,7 +942,7 @@ class A: A.f [builtins fixtures/tuple.pyi] [out] -MemberExpr(10) : Overload(def (self: A) -> Any, def (self: A, Any) -> Any) +MemberExpr(10) : Overload(def (self: Self@A) -> Any, def (self: A, Any) -> Any) [case testUnboundMethodWithInheritance] ## MemberExpr @@ -965,7 +965,7 @@ class A: def f(self, x: t) -> None: pass A.f(A(), B()) [out] -MemberExpr(7) : def (self: A, x: B) +MemberExpr(7) : def (self: Self@A, x: B) [case testUnboundMethodOfGenericClass] ## MemberExpr @@ -978,8 +978,8 @@ A.f a_b = A() # type: A[B] A.f(a_b, B()) [out] -MemberExpr(7) : def [t] (self: A[t`1], x: t`1) -MemberExpr(9) : def (self: A[B], x: B) +MemberExpr(7) : def [t] (self: Self@A[t`1], x: t`1) +MemberExpr(9) : def (self: Self@A[B], x: B) [case testUnboundOverloadedMethodOfGenericClass] ## CallExpr @@ -1008,7 +1008,7 @@ class A(Generic[t]): def f(self, x): pass A.f(None, None) [out] -MemberExpr(7) : def (self: A[t`1], x: Any) -> Any +MemberExpr(7) : def (self: Self@A[t`1], x: Any) -> Any [case testGenericMethodOfGenericClass] ## MemberExpr @@ -1022,7 +1022,7 @@ ab = None # type: A[B] o = None # type: object A.f(ab, o) [out] -MemberExpr(10) : def (self: A[B], y: builtins.object) +MemberExpr(10) : def (self: Self@A[B], y: builtins.object) -- Type variables with value restriction From c65787595fd2087fc53f662801d16abd7c19bd6f Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Sun, 25 Sep 2022 20:50:31 +0100 Subject: [PATCH 28/33] Fix some more failing CI --- mypy/checker.py | 3 +++ test-data/unit/check-attr.test | 10 +++++----- test-data/unit/check-classes.test | 24 ++++++++++++------------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index de98fa0fa179..b0166ed030a6 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -184,6 +184,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, StarType, TupleType, Type, @@ -3096,6 +3097,8 @@ def check_assignment_to_slots(self, lvalue: Lvalue) -> None: return inst = get_proper_type(self.expr_checker.accept(lvalue.expr)) + if isinstance(inst, SelfType): + inst = inst.upper_bound if not isinstance(inst, Instance): return if inst.type.slots is None: diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index c5b64ee61376..4ce3e3eb1848 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -218,8 +218,8 @@ from attr import attrib, attrs class A: a: int reveal_type(A) # N: Revealed type is "def (a: builtins.int) -> __main__.A" -reveal_type(A.__eq__) # N: Revealed type is "def (builtins.object, builtins.object) -> builtins.bool" -reveal_type(A.__ne__) # N: Revealed type is "def (builtins.object, builtins.object) -> builtins.bool" +reveal_type(A.__eq__) # N: Revealed type is "def (Self@builtins.object, builtins.object) -> builtins.bool" +reveal_type(A.__ne__) # N: Revealed type is "def (Self@builtins.object, builtins.object) -> builtins.bool" A(1) < A(2) # E: Unsupported left operand type for < ("A") A(1) <= A(2) # E: Unsupported left operand type for <= ("A") @@ -612,7 +612,7 @@ class A(Generic[T]): x: Optional[T] @classmethod def clsmeth(cls) -> None: - reveal_type(cls) # N: Revealed type is "Type[__main__.A[T`1]]" + reveal_type(cls) # N: Revealed type is "Type[Self@__main__.A[T`1]]" [builtins fixtures/classmethod.pyi] @@ -665,7 +665,7 @@ class A: b: str = attr.ib() @classmethod def new(cls) -> A: - reveal_type(cls) # N: Revealed type is "Type[__main__.A]" + reveal_type(cls) # N: Revealed type is "Type[Self@__main__.A]" return cls(6, 'hello') @classmethod def bad(cls) -> A: @@ -700,7 +700,7 @@ class A: @classmethod def foo(cls, x: Union[int, str]) -> Union[int, str]: - reveal_type(cls) # N: Revealed type is "Type[__main__.A]" + reveal_type(cls) # N: Revealed type is "Type[Self@__main__.A]" reveal_type(cls.other()) # N: Revealed type is "builtins.str" return x diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 5f1c23b756ed..8ee86b3fbd0a 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -148,7 +148,7 @@ class Base: pass class Derived(Base): - __hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "Callable[[Base], int]") + __hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "Callable[[Self], int]") [case testOverridePartialAttributeWithMethod] @@ -1111,10 +1111,10 @@ class Outer: reveal_type(Inner().make_int) # N: Revealed type is "def () -> builtins.int" some_int = Inner().make_int() -reveal_type(Outer.Inner.make_int) # N: Revealed type is "def (self: __main__.Outer.Inner) -> builtins.int" +reveal_type(Outer.Inner.make_int) # N: Revealed type is "def (self: Self@__main__.Outer.Inner) -> builtins.int" reveal_type(Outer().some_int) # N: Revealed type is "builtins.int" Bar = Outer.Inner -reveal_type(Bar.make_int) # N: Revealed type is "def (self: __main__.Outer.Inner) -> builtins.int" +reveal_type(Bar.make_int) # N: Revealed type is "def (self: Self@__main__.Outer.Inner) -> builtins.int" x = Bar() # type: Bar def produce() -> Bar: reveal_type(Bar().make_int) # N: Revealed type is "def () -> builtins.int" @@ -1267,7 +1267,7 @@ class C: cls(1) # E: Too many arguments for "C" cls.bar() cls.bar(1) # E: Too many arguments for "bar" of "C" - cls.bozo() # E: "Type[C]" has no attribute "bozo" + cls.bozo() # E: "Type[Self]" has no attribute "bozo" [builtins fixtures/classmethod.pyi] [out] @@ -1959,9 +1959,9 @@ class A: def __iadd__(self, other: int) -> int: pass def __radd__(self, other: int) -> int: pass -reveal_type(A.__add__) # N: Revealed type is "def (__main__.A, builtins.int) -> builtins.int" -reveal_type(A.__iadd__) # N: Revealed type is "def (__main__.A, builtins.int) -> builtins.int" -reveal_type(A.__radd__) # N: Revealed type is "def (__main__.A, builtins.int) -> builtins.int" +reveal_type(A.__add__) # N: Revealed type is "def (Self@__main__.A, builtins.int) -> builtins.int" +reveal_type(A.__iadd__) # N: Revealed type is "def (Self@__main__.A, builtins.int) -> builtins.int" +reveal_type(A.__radd__) # N: Revealed type is "def (Self@__main__.A, builtins.int) -> builtins.int" [case testOperatorMethodOverrideWithIdenticalOverloadedType] from foo import * @@ -2079,8 +2079,8 @@ class B: class C: def __radd__(self, other, oops) -> int: ... [out] -tmp/foo.pyi:3: error: Invalid signature "Callable[[B], A]" -tmp/foo.pyi:5: error: Invalid signature "Callable[[C, Any, Any], int]" +tmp/foo.pyi:3: error: Invalid signature "Callable[[Self], A]" +tmp/foo.pyi:5: error: Invalid signature "Callable[[Self, Any, Any], int]" [case testReverseOperatorOrderingCase1] class A: @@ -2670,8 +2670,8 @@ class C: class D: def __getattribute__(self, x: str) -> None: pass [out] -main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattribute__" -main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattribute__" +main:4: error: Invalid signature "Callable[[Self, A], B]" for "__getattribute__" +main:6: error: Invalid signature "Callable[[Self, str, str], C]" for "__getattribute__" [case testGetattr] @@ -2711,7 +2711,7 @@ a: A b: B a1: A = a.foo -b1: B = a.bar # E: Incompatible types in assignment (expression has type "A", variable has type "B") +b1: B = a.bar # E: Incompatible types in assignment (expression has type "Self", variable has type "B") a2: A = b.baz # E: Incompatible types in assignment (expression has type "int", variable has type "A") b2: B = b.roo # E: Incompatible types in assignment (expression has type "int", variable has type "B") [builtins fixtures/tuple.pyi] From e226e1450e879b593137f04da3931d751c0a47da Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Wed, 28 Sep 2022 00:19:27 +0100 Subject: [PATCH 29/33] Fix more CI --- mypy/checkexpr.py | 3 ++- mypy/semanal.py | 7 +++---- mypy/types.py | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 84be1f265d49..a8b445ea8139 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1961,9 +1961,10 @@ def check_for_extra_actual_arguments( def missing_classvar_callable_note( self, object_type: Type, callable_name: str, context: Context ) -> None: + object_type = get_proper_type(object_type) if isinstance(object_type, SelfType): object_type = object_type.upper_bound - if isinstance(object_type, ProperType) and isinstance(object_type, Instance): + if isinstance(object_type, Instance): _, var_name = callable_name.rsplit(".", maxsplit=1) node = object_type.type.get(var_name) if node is not None and isinstance(node.node, Var): diff --git a/mypy/semanal.py b/mypy/semanal.py index 3c116ed9fb7e..5c7bc19963e8 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -215,7 +215,6 @@ ) from mypy.semanal_typeddict import TypedDictAnalyzer from mypy.tvar_scope import TypeVarLikeScope -from mypy.type_visitor import TypeQuery from mypy.typeanal import ( TypeAnalyser, TypeVarLikeList, @@ -4033,7 +4032,7 @@ def check_classvar(self, s: AssignmentStmt) -> None: # This means that we have a type var defined inside of a ClassVar. # This is not allowed by PEP526. (Unless it's a SelfType, which is fine) # See https://github.com/python/mypy/issues/11538 - if not (s.type.args and self.is_self_type(s.type.args[0])): + if not (isinstance(s.type, Instance) and s.type.args and self.is_self_type(s.type.args[0])): self.fail(message_registry.CLASS_VAR_WITH_TYPEVARS, s) elif not isinstance(lvalue, MemberExpr) or self.is_self_member_ref(lvalue): # In case of member access, report error only when assigning to self @@ -4056,7 +4055,7 @@ def is_final_type(self, typ: Type | None) -> bool: return False return sym.node.fullname in FINAL_TYPE_NAMES - def is_self_type(self, typ: Optional[Type]) -> bool: + def is_self_type(self, typ: Type | None) -> bool: if not isinstance(typ, UnboundType): return False sym = self.lookup_qualified(typ.name, typ) @@ -6147,7 +6146,7 @@ def anal_type( self.add_type_alias_deps(a.aliases_used) return typ - def class_type(self, self_type: Type) -> Type: + def class_type(self, self_type: Type) -> ProperType: return TypeType.make_normalized(self_type) def schedule_patch(self, priority: int, patch: Callable[[], None]) -> None: diff --git a/mypy/types.py b/mypy/types.py index 14700380205f..b17693e429bd 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -576,17 +576,17 @@ def deserialize(cls, data: JsonDict) -> TypeVarType: ) -SELF_ID = TypeVarId(0.5) # type: ignore +SELF_ID = TypeVarId(0.5) # type: ignore[arg-type] # this is a hack cause I need a way to represent a number that's constant and can't be +ve or -ve # and using TypeVarId.new() would quickly hit a huge number which is harder to read. class SelfType(TypeVarType): __slots__ = () - upper_bound: "Instance" + upper_bound: Instance def __init__( - self, fullname: str, upper_bound: "Instance", line: int = -1, column: int = -1 + self, fullname: str, upper_bound: Instance, line: int = -1, column: int = -1 ) -> None: super().__init__("Self", fullname, SELF_ID, [], upper_bound, line=line, column=column) @@ -608,7 +608,7 @@ def serialize(self) -> JsonDict: @classmethod def deserialize(cls, data: JsonDict) -> "SelfType": assert data[".class"] == "SelfType" - return SelfType(data["fullname"], deserialize_type(data["upper_bound"])) + return SelfType(data["fullname"], Instance.deserialize(data["upper_bound"])) class ParamSpecFlavor: From 74feea6b0aa0347961b35995113e701a4d0e99c4 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Sun, 2 Oct 2022 15:47:53 +0100 Subject: [PATCH 30/33] Fix more more CI --- mypy/messages.py | 7 ++++++- test-data/unit/check-classes.test | 4 ++-- test-data/unit/check-dataclasses.test | 4 ++-- test-data/unit/check-generics.test | 6 +++--- test-data/unit/check-overloading.test | 2 +- test-data/unit/check-typeddict.test | 4 ++-- test-data/unit/check-unreachable-code.test | 12 ++++++------ 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index a8ebcf7d5011..757fd2fe330a 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1198,7 +1198,12 @@ def could_not_infer_type_arguments( ) -> None: callee_name = callable_name(callee_type) if callee_name is not None and n > 0: - self.fail(f"Cannot infer type argument {n} of {callee_name}", context) + self.fail( + f"Cannot infer type argument " + f"{n-1 if any(isinstance(v, SelfType) for v in callee_type.variables) else n} " + f"of {callee_name}", + context + ) else: self.fail("Cannot infer function type argument", context) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 8ee86b3fbd0a..d865c5cb1546 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -105,7 +105,7 @@ class A: class B: pass [out] main:4: error: Incompatible types in assignment (expression has type "A", variable has type "B") -main:5: error: "A" has no attribute "g" +main:5: error: "Self" has no attribute "g" [case testAssignToMethodViaInstance] import typing @@ -894,7 +894,7 @@ class A: if int(): h = f g = h - ff = f # type: Callable[[B], None] # E: Incompatible types in assignment (expression has type "Callable[[A], None]", variable has type "Callable[[B], None]") + ff = f # type: Callable[[B], None] # E: Incompatible types in assignment (expression has type "Callable[[Self], None]", variable has type "Callable[[B], None]") if int(): g = ff # E: Incompatible types in assignment (expression has type "Callable[[B], None]", variable has type "Callable[[A], None]") [out] diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index b821aefe8f7c..39b481923c3c 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -568,7 +568,7 @@ class A: @classmethod def foo(cls, x: Union[int, str]) -> Union[int, str]: - reveal_type(cls) # N: Revealed type is "Type[__main__.A]" + reveal_type(cls) # N: Revealed type is "Type[Self@__main__.A]" reveal_type(cls.other()) # N: Revealed type is "builtins.str" return x @@ -856,7 +856,7 @@ class A(Generic[T]): @classmethod def foo(cls) -> None: - reveal_type(cls) # N: Revealed type is "Type[__main__.A[T`1]]" + reveal_type(cls) # N: Revealed type is "Type[Self@__main__.A[T`1]]" cls.x # E: Access to generic instance variables via class is ambiguous @classmethod diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index b7d98a783a49..40f51585ff7b 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -209,7 +209,7 @@ x = None # type: B class B: pass [out] main:7: error: Argument 1 to "f" of "A" has incompatible type "B"; expected "T" -main:8: error: Incompatible types in assignment (expression has type "A[T]", variable has type "A[B]") +main:8: error: Incompatible types in assignment (expression has type "Self", variable has type "A[B]") [case testGenericTypeBodyWithMultipleVariables] from typing import TypeVar, Generic @@ -222,8 +222,8 @@ class A(Generic[S, T]): if int(): s = t # E: Incompatible types in assignment (expression has type "T", variable has type "S") t = s # E: Incompatible types in assignment (expression has type "S", variable has type "T") - a = self # type: A[S, B] # E: Incompatible types in assignment (expression has type "A[S, T]", variable has type "A[S, B]") - b = self # type: A[T, T] # E: Incompatible types in assignment (expression has type "A[S, T]", variable has type "A[T, T]") + a = self # type: A[S, B] # E: Incompatible types in assignment (expression has type "Self", variable has type "A[S, B]") + b = self # type: A[T, T] # E: Incompatible types in assignment (expression has type "Self", variable has type "A[T, T]") c = self # type: A[S, T] if int(): t = t diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index a5e6cefc2af0..a14c40e815b1 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -4224,7 +4224,7 @@ class Wrapper: @classmethod # E: Overloaded function implementation cannot produce return type of signature 1 def foo(cls, x: Union[int, str]) -> str: - reveal_type(cls) # N: Revealed type is "Type[__main__.Wrapper]" + reveal_type(cls) # N: Revealed type is "Type[Self@__main__.Wrapper]" reveal_type(cls.other()) # N: Revealed type is "builtins.str" return "..." diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 7fba4da071f3..1906cf6798f5 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -2518,9 +2518,9 @@ class TD(TypedDict): x: str y: str -reveal_type(TD.__iter__) # N: Revealed type is "def (typing._TypedDict) -> typing.Iterator[builtins.str]" +reveal_type(TD.__iter__) # N: Revealed type is "def (Self@typing._TypedDict) -> typing.Iterator[builtins.str]" reveal_type(TD.__annotations__) # N: Revealed type is "typing.Mapping[builtins.str, builtins.object]" -reveal_type(TD.values) # N: Revealed type is "def (self: typing.Mapping[T`1, T_co`2]) -> typing.Iterable[T_co`2]" +reveal_type(TD.values) # N: Revealed type is "def (self: Self@typing.Mapping[T`1, T_co`2]) -> typing.Iterable[T_co`2]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index 64736e55e2dd..9cc6ca77b120 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -614,21 +614,21 @@ from typing import Any Parent: Any class Child(Parent): def foo(self) -> int: - reveal_type(self) # N: Revealed type is "__main__.Child" + reveal_type(self) # N: Revealed type is "Self@__main__.Child" if self is None: reveal_type(self) return None - reveal_type(self) # N: Revealed type is "__main__.Child" + reveal_type(self) # N: Revealed type is "Self@__main__.Child" return 3 def bar(self) -> int: if 1: self = super(Child, self).something() - reveal_type(self) # N: Revealed type is "__main__.Child" + reveal_type(self) # N: Revealed type is "Self@__main__.Child" if self is None: reveal_type(self) return None - reveal_type(self) # N: Revealed type is "__main__.Child" + reveal_type(self) # N: Revealed type is "Self@__main__.Child" return 3 [builtins fixtures/isinstance.pyi] @@ -639,11 +639,11 @@ from typing import Any Parent: Any class Child(Parent): def foo(self) -> int: - reveal_type(self) # N: Revealed type is "__main__.Child" + reveal_type(self) # N: Revealed type is "Self@__main__.Child" if self is None: reveal_type(self) # N: Revealed type is "None" return None - reveal_type(self) # N: Revealed type is "__main__.Child" + reveal_type(self) # N: Revealed type is "Self@__main__.Child" return 3 [builtins fixtures/isinstance.pyi] From 15924b2e220d685ec0b975a83904514d44d04634 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Sun, 23 Oct 2022 17:33:43 +0100 Subject: [PATCH 31/33] Fix more tests --- test-data/unit/check-classes.test | 2 +- test-data/unit/check-super.test | 2 +- test-data/unit/semanal-abstractclasses.test | 8 ++--- test-data/unit/semanal-classes.test | 8 ++--- test-data/unit/semanal-types.test | 2 +- test-data/unit/typexport-basic.test | 36 ++++++++++----------- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 4b25941700ae..8da69c9dc45c 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7022,7 +7022,7 @@ class C: def meth(cls): ... reveal_type(C.meth) # N: Revealed type is "def () -> Any" -reveal_type(C.__new__) # N: Revealed type is "def (cls: Type[__main__.C]) -> Any" +reveal_type(C.__new__) # N: Revealed type is "def (cls: Type[Self@__main__.C]) -> Any" [builtins fixtures/classmethod.pyi] [case testOverrideGenericSelfClassMethod] diff --git a/test-data/unit/check-super.test b/test-data/unit/check-super.test index 0913f4f25126..bce89cf9fe73 100644 --- a/test-data/unit/check-super.test +++ b/test-data/unit/check-super.test @@ -123,7 +123,7 @@ class C(B): def h(self, x) -> None: reveal_type(super(x, x).f) # N: Revealed type is "def ()" reveal_type(super(C, x).f) # N: Revealed type is "def ()" - reveal_type(super(C, type(x)).f) # N: Revealed type is "def (self: __main__.B)" + reveal_type(super(C, type(x)).f) # N: Revealed type is "def (self: Self@__main__.B)" [case testSuperInUnannotatedMethod] class C: diff --git a/test-data/unit/semanal-abstractclasses.test b/test-data/unit/semanal-abstractclasses.test index b0cb00e82106..4f7f252097d5 100644 --- a/test-data/unit/semanal-abstractclasses.test +++ b/test-data/unit/semanal-abstractclasses.test @@ -20,7 +20,7 @@ MypyFile:1( g Args( Var(self)) - def (self: __main__.A) -> __main__.A + def (self: Self@__main__.A) -> __main__.A Abstract Block:6( PassStmt:6()))) @@ -30,7 +30,7 @@ MypyFile:1( f Args( Var(self)) - def (self: __main__.A) -> __main__.A + def (self: Self@__main__.A) -> __main__.A Abstract Block:8( ReturnStmt:8( @@ -86,7 +86,7 @@ MypyFile:1( f Args( Var(self)) - def (self: __main__.A[T`1]) -> __main__.A[T`1] + def (self: Self@__main__.A[T`1]) -> __main__.A[T`1] Abstract Block:6( PassStmt:6()))))) @@ -113,7 +113,7 @@ MypyFile:1( g Args( Var(self)) - def (self: __main__.A) -> __main__.A + def (self: Self@__main__.A) -> __main__.A Abstract Block:7( PassStmt:7()))))) diff --git a/test-data/unit/semanal-classes.test b/test-data/unit/semanal-classes.test index bc4c008acd78..9680fde37ec7 100644 --- a/test-data/unit/semanal-classes.test +++ b/test-data/unit/semanal-classes.test @@ -211,7 +211,7 @@ MypyFile:1( f Args( Var(self)) - def (self: __main__.A) + def (self: Self@__main__.A) Block:4( ExpressionStmt:4( NameExpr(self [l]))))) @@ -470,7 +470,7 @@ MypyFile:1( Args( Var(cls) Var(z)) - def (cls: Type[__main__.A], z: builtins.int) -> builtins.str + def (cls: Type[Self@__main__.A], z: builtins.int) -> builtins.str Class Block:3( PassStmt:3()))))) @@ -490,7 +490,7 @@ MypyFile:1( f Args( Var(cls)) - def (cls: Type[__main__.A]) -> builtins.str + def (cls: Type[Self@__main__.A]) -> builtins.str Class Block:3( PassStmt:3()))))) @@ -512,7 +512,7 @@ MypyFile:1( f Args( Var(self)) - def (self: __main__.A) -> builtins.str + def (self: Self@__main__.A) -> builtins.str Property Block:4( PassStmt:4()))))) diff --git a/test-data/unit/semanal-types.test b/test-data/unit/semanal-types.test index 2f2e3fe59d22..20093838f87a 100644 --- a/test-data/unit/semanal-types.test +++ b/test-data/unit/semanal-types.test @@ -619,7 +619,7 @@ MypyFile:1( f Args( Var(self)) - def (self: __main__.c[t`1]) -> t`1 + def (self: Self@__main__.c[t`1]) -> t`1 Block:6( PassStmt:6())))) diff --git a/test-data/unit/typexport-basic.test b/test-data/unit/typexport-basic.test index 22a53e0ba2ff..617392162372 100644 --- a/test-data/unit/typexport-basic.test +++ b/test-data/unit/typexport-basic.test @@ -58,7 +58,7 @@ class B: pass NameExpr(3) : A NameExpr(6) : A NameExpr(7) : B -NameExpr(10) : A +NameExpr(10) : Self@A [case testEllipsis] import typing @@ -247,13 +247,13 @@ class A: [out] MemberExpr(6) : A MemberExpr(6) : Any -NameExpr(6) : A -NameExpr(6) : A +NameExpr(6) : Self@A +NameExpr(6) : Self@A MemberExpr(7) : A MemberExpr(7) : A MemberExpr(7) : A -NameExpr(7) : A -NameExpr(7) : A +NameExpr(7) : Self@A +NameExpr(7) : Self@A [case testIf] @@ -339,7 +339,7 @@ class A(Generic[T]): [out] CallExpr(5) : T`1 MemberExpr(5) : def () -> T`1 -NameExpr(5) : A[T`1] +NameExpr(5) : Self@A[T`1] [case testGenericFunctionCallWithTypeApp-skip] ## CallExpr|TypeApplication|NameExpr @@ -438,7 +438,7 @@ class B(A[C]): CallExpr(8) : None MemberExpr(8) : def (a: C) NameExpr(8) : C -NameExpr(8) : B +NameExpr(8) : Self@B [case testInheritedMethodReferenceWithGenericSubclass] from typing import TypeVar, Generic @@ -454,7 +454,7 @@ class B(A[C, T], Generic[T]): CallExpr(9) : None MemberExpr(9) : def (a: C) NameExpr(9) : C -NameExpr(9) : B[T`1] +NameExpr(9) : Self@B[T`1] [case testExternalReferenceWithGenericInheritance] from typing import TypeVar, Generic @@ -903,7 +903,7 @@ class A: def f(self) -> None: pass A.f [out] -MemberExpr(5) : def (self: A) +MemberExpr(5) : def (self: Self@A) [case testUnboundMethodWithImplicitSig] ## MemberExpr @@ -912,7 +912,7 @@ class A: def f(self): pass A.f [out] -MemberExpr(5) : def (self: A) -> Any +MemberExpr(5) : def (self: Self@A) -> Any [case testOverloadedUnboundMethod] ## MemberExpr @@ -927,7 +927,7 @@ class A: A.f [builtins fixtures/tuple.pyi] [out] -MemberExpr(10) : Overload(def (self: Self@A), def (self: A, builtins.object)) +MemberExpr(10) : Overload(def (self: Self@A), def (self: Self@A, builtins.object)) [case testOverloadedUnboundMethodWithImplicitSig] ## MemberExpr @@ -942,7 +942,7 @@ class A: A.f [builtins fixtures/tuple.pyi] [out] -MemberExpr(10) : Overload(def (self: Self@A) -> Any, def (self: A, Any) -> Any) +MemberExpr(10) : Overload(def (self: A) -> Any, def (self: A, Any) -> Any) [case testUnboundMethodWithInheritance] ## MemberExpr @@ -954,7 +954,7 @@ class B(A): pass B.f [out] -MemberExpr(8) : def (self: A) +MemberExpr(8) : def (self: Self@A) [case testUnboundGenericMethod] ## MemberExpr @@ -965,7 +965,7 @@ class A: def f(self, x: t) -> None: pass A.f(A(), B()) [out] -MemberExpr(7) : def (self: Self@A, x: B) +MemberExpr(7) : def (self: A, x: B) [case testUnboundMethodOfGenericClass] ## MemberExpr @@ -979,7 +979,7 @@ a_b = A() # type: A[B] A.f(a_b, B()) [out] MemberExpr(7) : def [t] (self: Self@A[t`1], x: t`1) -MemberExpr(9) : def (self: Self@A[B], x: B) +MemberExpr(9) : def (self: A[B], x: B) [case testUnboundOverloadedMethodOfGenericClass] ## CallExpr @@ -1008,7 +1008,7 @@ class A(Generic[t]): def f(self, x): pass A.f(None, None) [out] -MemberExpr(7) : def (self: Self@A[t`1], x: Any) -> Any +MemberExpr(7) : def (self: A[t`1], x: Any) -> Any [case testGenericMethodOfGenericClass] ## MemberExpr @@ -1022,7 +1022,7 @@ ab = None # type: A[B] o = None # type: object A.f(ab, o) [out] -MemberExpr(10) : def (self: Self@A[B], y: builtins.object) +MemberExpr(10) : def (self: A[B], y: builtins.object) -- Type variables with value restriction @@ -1159,7 +1159,7 @@ class A: self.x = ( A()) [out] -NameExpr(5) : A +NameExpr(5) : Self@A NameExpr(6) : def () -> A [case testListMultiplicationInContext] From 7f125e9588bac98ee35ab6b608ae2fb6475d9a63 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Fri, 28 Oct 2022 00:33:33 +0100 Subject: [PATCH 32/33] Fix more tests --- test-data/unit/check-classes.test | 2 +- test-data/unit/fine-grained.test | 6 +++--- test-data/unit/merge.test | 32 +++++++++++++++---------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 8da69c9dc45c..4b25941700ae 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7022,7 +7022,7 @@ class C: def meth(cls): ... reveal_type(C.meth) # N: Revealed type is "def () -> Any" -reveal_type(C.__new__) # N: Revealed type is "def (cls: Type[Self@__main__.C]) -> Any" +reveal_type(C.__new__) # N: Revealed type is "def (cls: Type[__main__.C]) -> Any" [builtins fixtures/classmethod.pyi] [case testOverrideGenericSelfClassMethod] diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 49f03a23177e..6a6d559f7e05 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -2378,7 +2378,7 @@ class B: x: int [out] == -a.py:4: error: Argument 1 to "deca" has incompatible type "Callable[[D, B], B]"; expected "Callable[..., str]" +a.py:4: error: Argument 1 to "deca" has incompatible type "Callable[[Self, B], B]"; expected "Callable[..., str]" == a.py:7: error: "B" has no attribute "x" == @@ -2429,7 +2429,7 @@ class C: pass [out] == -a.py:6: error: Argument 1 to "dec" of "C" has incompatible type "Callable[[Inner, int], int]"; expected "Callable[..., str]" +a.py:6: error: Argument 1 to "dec" of "C" has incompatible type "Callable[[Self, int], int]"; expected "Callable[..., str]" [case testDecoratorUpdateClassInFunction] import a @@ -2465,7 +2465,7 @@ class B: x: str [out] == -a.py:6: error: Argument 1 to "dec" of "C" has incompatible type "Callable[[Inner, B], int]"; expected "Callable[..., str]" +a.py:6: error: Argument 1 to "dec" of "C" has incompatible type "Callable[[Self, B], int]"; expected "Callable[..., str]" == a.py:8: error: Incompatible return value type (got "str", expected "int") diff --git a/test-data/unit/merge.test b/test-data/unit/merge.test index e400c763eefa..9ec99e814f9b 100644 --- a/test-data/unit/merge.test +++ b/test-data/unit/merge.test @@ -148,7 +148,7 @@ MypyFile:1<1>( f Args( Var(self)) - def (self: target.A<4>) -> target.B<5> + def (self: Self@target.A<4>) -> target.B<5> Block:2<6>( ReturnStmt:3<7>( CallExpr:3<8>( @@ -172,7 +172,7 @@ MypyFile:1<1>( f Args( Var(self)) - def (self: target.A<4>) -> target.B<5> + def (self: Self@target.A<4>) -> target.B<5> Block:3<14>( ExpressionStmt:4<15>( IntExpr(1)) @@ -203,7 +203,7 @@ MypyFile:1<1>( f Args( Var(self)) - def (self: target.A<4>) + def (self: Self@target.A<4>) Block:2<5>( ExpressionStmt:3<6>( CallExpr:3<7>( @@ -223,7 +223,7 @@ MypyFile:1<1>( f Args( Var(self)) - def (self: target.A<4>) + def (self: Self@target.A<4>) Block:2<11>( ExpressionStmt:3<12>( CallExpr:3<13>( @@ -256,7 +256,7 @@ MypyFile:1<1>( f Args( Var(self)) - def (self: target.A<4>) + def (self: Self@target.A<4>) Block:2<5>( AssignmentStmt:3<6>( MemberExpr:3<8>( @@ -279,7 +279,7 @@ MypyFile:1<1>( f Args( Var(self)) - def (self: target.A<4>) + def (self: Self@target.A<4>) Block:2<13>( AssignmentStmt:3<14>( MemberExpr:3<15>( @@ -450,27 +450,27 @@ class A: CallExpr:3: target.A<0> MemberExpr:3: target.A<0> NameExpr:3: def () -> target.A<0> -NameExpr:3: target.A<0> +NameExpr:3: Self@target.A<0> MemberExpr:4: target.A<0> -NameExpr:4: target.A<0> +NameExpr:4: Self@target.A<0> IntExpr:5: Literal[1]?<1> MemberExpr:5: builtins.int<1> -NameExpr:5: target.A<0> +NameExpr:5: Self@target.A<0> MemberExpr:6: builtins.int<1> NameExpr:6: target.A<0> ==> ## target IntExpr:3: Literal[1]?<1> MemberExpr:3: builtins.int<1> -NameExpr:3: target.A<0> +NameExpr:3: Self@target.A<0> MemberExpr:4: builtins.int<1> -NameExpr:4: target.A<0> +NameExpr:4: Self@target.A<0> CallExpr:5: target.A<0> MemberExpr:5: target.A<0> NameExpr:5: def () -> target.A<0> -NameExpr:5: target.A<0> -MemberExpr:6: target.A<0> -NameExpr:6: target.A<0> +NameExpr:5: Self@target.A<0> +MemberExpr:6: Self@target.A<0> +NameExpr:6: Self@target.A<0> [case testMethod_types] import target @@ -487,12 +487,12 @@ class A: ## target CallExpr:3: target.A<0> MemberExpr:3: def () -> target.A<0> -NameExpr:3: target.A<0> +NameExpr:3: Self@target.A<0> ==> ## target CallExpr:4: target.A<0> MemberExpr:4: def () -> target.A<0> -NameExpr:4: target.A<0> +NameExpr:4: Self@target.A<0> [case testRenameFunction] import target From 8e60528b0f8b005727a09f27a78522ee51eb3474 Mon Sep 17 00:00:00 2001 From: Gobot1234 Date: Sun, 6 Nov 2022 23:26:46 +0000 Subject: [PATCH 33/33] Fix more tests --- test-data/unit/check-incremental.test | 4 ++-- test-data/unit/check-parameter-specification.test | 4 ++-- test-data/unit/fine-grained.test | 4 ++-- test-data/unit/merge.test | 4 ++-- test-data/unit/typexport-basic.test | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index ac005001b135..fb225e602afa 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -3967,8 +3967,8 @@ class A: [out1] [out2] tmp/b.py:3: note: Revealed type is "def (a: builtins.int) -> a.A" -tmp/b.py:4: note: Revealed type is "def (builtins.object, builtins.object) -> builtins.bool" -tmp/b.py:5: note: Revealed type is "def (builtins.object, builtins.object) -> builtins.bool" +tmp/b.py:4: note: Revealed type is "def (Self@builtins.object, builtins.object) -> builtins.bool" +tmp/b.py:5: note: Revealed type is "def (Self@builtins.object, builtins.object) -> builtins.bool" tmp/b.py:6: note: Revealed type is "def [_DT] (self: _DT`-1, other: _DT`-1) -> builtins.bool" tmp/b.py:7: note: Revealed type is "def [_DT] (self: _DT`-1, other: _DT`-1) -> builtins.bool" tmp/b.py:8: note: Revealed type is "def [_DT] (self: _DT`-1, other: _DT`-1) -> builtins.bool" diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index f91995379b61..f075227a321f 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -843,7 +843,7 @@ class A: def func(self, action: Callable[_P, _R], *args: _P.args, **kwargs: _P.kwargs) -> _R: ... -reveal_type(A.func) # N: Revealed type is "def [_P, _R] (self: __main__.A, action: def (*_P.args, **_P.kwargs) -> _R`-2, *_P.args, **_P.kwargs) -> _R`-2" +reveal_type(A.func) # N: Revealed type is "def [_P, _R] (self: Self@__main__.A, action: def (*_P.args, **_P.kwargs) -> _R`-2, *_P.args, **_P.kwargs) -> _R`-2" # TODO: _R` keeps flip-flopping between 5 (?), 13, 14, 15. Spooky. # reveal_type(A().func) $ N: Revealed type is "def [_P, _R] (action: def (*_P.args, **_P.kwargs) -> _R`13, *_P.args, **_P.kwargs) -> _R`13" @@ -878,7 +878,7 @@ class A: def func(self, action: Job[_P, None]) -> Job[_P, None]: ... -reveal_type(A.func) # N: Revealed type is "def [_P] (self: __main__.A, action: __main__.Job[_P`-1, None]) -> __main__.Job[_P`-1, None]" +reveal_type(A.func) # N: Revealed type is "def [_P] (self: Self@__main__.A, action: __main__.Job[_P`-1, None]) -> __main__.Job[_P`-1, None]" # TODO: flakey, _P`4 alternates around. # reveal_type(A().func) $ N: Revealed type is "def [_P] (action: __main__.Job[_P`4, None]) -> __main__.Job[_P`4, None]" reveal_type(A().func(Job(lambda x: x))) # N: Revealed type is "__main__.Job[[x: Any], None]" diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 6a6d559f7e05..fad67e4e8fe0 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -2575,8 +2575,8 @@ main:3: note: Revealed type is "builtins.int" == main:3: error: No overload variant of "foo" of "Wrapper" matches argument type "int" main:3: note: Possible overload variants: -main:3: note: def foo(cls: Wrapper, x: int) -> int -main:3: note: def foo(cls: Wrapper, x: str) -> str +main:3: note: def foo(cls: Self, x: int) -> int +main:3: note: def foo(cls: Self, x: str) -> str main:3: note: Revealed type is "Any" [case testRefreshGenericClass] diff --git a/test-data/unit/merge.test b/test-data/unit/merge.test index 9ec99e814f9b..17977f8038a2 100644 --- a/test-data/unit/merge.test +++ b/test-data/unit/merge.test @@ -457,7 +457,7 @@ IntExpr:5: Literal[1]?<1> MemberExpr:5: builtins.int<1> NameExpr:5: Self@target.A<0> MemberExpr:6: builtins.int<1> -NameExpr:6: target.A<0> +NameExpr:6: Self@target.A<0> ==> ## target IntExpr:3: Literal[1]?<1> @@ -469,7 +469,7 @@ CallExpr:5: target.A<0> MemberExpr:5: target.A<0> NameExpr:5: def () -> target.A<0> NameExpr:5: Self@target.A<0> -MemberExpr:6: Self@target.A<0> +MemberExpr:6: target.A<0> NameExpr:6: Self@target.A<0> [case testMethod_types] diff --git a/test-data/unit/typexport-basic.test b/test-data/unit/typexport-basic.test index 617392162372..270d8fed8e19 100644 --- a/test-data/unit/typexport-basic.test +++ b/test-data/unit/typexport-basic.test @@ -912,7 +912,7 @@ class A: def f(self): pass A.f [out] -MemberExpr(5) : def (self: Self@A) -> Any +MemberExpr(5) : def (self: A) -> Any [case testOverloadedUnboundMethod] ## MemberExpr