diff --git a/mypy/applytype.py b/mypy/applytype.py index b66e148ee0ab..b6614ed69536 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -11,6 +11,7 @@ Parameters, ParamSpecType, PartialType, + SelfType, Type, TypeVarId, TypeVarLikeType, @@ -32,6 +33,8 @@ def get_target_type( return type if isinstance(tvar, TypeVarTupleType): return type + if isinstance(tvar, SelfType): + return type assert isinstance(tvar, TypeVarType) values = tvar.values p_type = get_proper_type(type) diff --git a/mypy/checker.py b/mypy/checker.py index 8dac00bba23a..2b56763e7d8a 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -186,6 +186,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, StarType, TupleType, Type, @@ -3198,6 +3199,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/mypy/checkexpr.py b/mypy/checkexpr.py index a07a1a1c9258..a8b445ea8139 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -138,6 +138,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, StarType, TupleType, Type, @@ -1960,7 +1961,10 @@ 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, ProperType) and isinstance(object_type, Instance): + object_type = get_proper_type(object_type) + if isinstance(object_type, SelfType): + object_type = object_type.upper_bound + 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/checkmember.py b/mypy/checkmember.py index 6221d753409c..708432653b10 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -4,7 +4,6 @@ from typing import TYPE_CHECKING, Callable, Sequence, cast -from mypy import meet, message_registry, subtypes from mypy.erasetype import erase_typevars from mypy.expandtype import expand_type_by_instance, freshen_function_type_vars from mypy.maptype import map_instance_to_supertype @@ -53,6 +52,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, TupleType, Type, TypedDictType, @@ -63,13 +63,14 @@ TypeVarType, UnionType, get_proper_type, + has_self_types, has_type_vars, ) if TYPE_CHECKING: # import for forward declaration only import mypy.checker -from mypy import state +from mypy import meet, message_registry, state, subtypes class MemberContext: @@ -609,6 +610,8 @@ def analyze_descriptor_access(descriptor_type: Type, mx: MemberContext) -> Type: 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): return orig_descriptor_type @@ -947,7 +950,12 @@ 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 not isinstance(get_proper_type(mx.original_type), TypeType) or node.implicit: + 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 else: diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 77bbb90faafb..c5c08df47eb3 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -17,6 +17,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, TupleType, Type, TypeAliasType, @@ -106,7 +107,10 @@ def freshen_function_type_vars(callee: F) -> F: tvmap: dict[TypeVarId, Type] = {} for v in callee.variables: 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): assert isinstance(v, TypeVarTupleType) tv = TypeVarTupleType.new_unification_variable(v) @@ -158,6 +162,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? diff --git a/mypy/join.py b/mypy/join.py index 4cd2c6b2534b..0ad49df4ed36 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -28,6 +28,7 @@ PartialType, PlaceholderType, ProperType, + SelfType, TupleType, Type, TypeAliasType, @@ -283,6 +284,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: @@ -337,6 +340,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) diff --git a/mypy/messages.py b/mypy/messages.py index cc9728f99e1d..cc90a7e6df90 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -74,6 +74,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, TupleType, Type, TypeAliasType, @@ -406,6 +407,10 @@ def has_no_attr( extra = " (not async iterable)" if not self.are_type_names_disabled(): failed = False + if isinstance(original_type, SelfType) 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()) @@ -1193,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) @@ -1219,7 +1229,7 @@ def variable_may_be_undefined(self, name: 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" @@ -1850,6 +1860,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 @@ -2542,7 +2554,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) @@ -2560,7 +2574,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/default.py b/mypy/plugins/default.py index 5ec37230b5ed..2e2f3daddd90 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -180,7 +180,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 @@ -198,7 +198,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])], @@ -260,7 +260,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 @@ -269,7 +269,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) diff --git a/mypy/plugins/enums.py b/mypy/plugins/enums.py index 75b301252f06..c4de60a1effa 100644 --- a/mypy/plugins/enums.py +++ b/mypy/plugins/enums.py @@ -12,7 +12,7 @@ """ from __future__ import annotations -from typing import Iterable, Sequence, TypeVar, cast +from typing import Sequence, TypeVar, cast from typing_extensions import Final import mypy.plugin # To avoid circular imports. @@ -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 +from mypy.types import ( + CallableType, + Instance, + LiteralType, + ProperType, + SelfType, + Type, + get_proper_type, +) ENUM_NAME_ACCESS: Final = {f"{prefix}.name" for prefix in ENUM_BASES} | { f"{prefix}._name_" for prefix in ENUM_BASES @@ -57,16 +65,6 @@ def enum_name_callback(ctx: mypy.plugin.AttributeContext) -> Type: _T = TypeVar("_T") -def _first(it: Iterable[_T]) -> _T | None: - """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: ProperType | None ) -> Type | None: @@ -86,7 +84,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 +105,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 +148,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 +175,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/semanal.py b/mypy/semanal.py index 5a1787c50650..1d042e1832ed 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -238,12 +238,12 @@ OVERLOAD_NAMES, PROTOCOL_NAMES, REVEAL_TYPE_NAMES, + SELF_TYPE_NAMES, TPDICT_NAMES, TYPE_ALIAS_NAMES, TYPED_NAMEDTUPLE_NAMES, AnyType, CallableType, - FunctionLike, Instance, LiteralType, LiteralValue, @@ -253,6 +253,7 @@ ParamSpecType, PlaceholderType, ProperType, + SelfType, StarType, TrivialSyntheticTypeTranslator, TupleType, @@ -914,19 +915,73 @@ def remove_unpack_kwargs(self, defn: FuncDef, typ: CallableType) -> CallableType 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) + 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 + ): # 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) + ) + 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) + else: + return + else: + return + 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 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 + func.type.ret_type = self_type_type def set_original_def(self, previous: Node | None, new: FuncDef | Decorator) -> bool: """If 'new' conditionally redefine 'previous', set 'previous' as original @@ -3990,10 +4045,10 @@ def check_classvar(self, s: AssignmentStmt) -> None: self.type.defn.type_vars ): # 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 (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 # Other kinds of member assignments should be already reported @@ -4015,6 +4070,14 @@ 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: Type | None) -> 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) @@ -6100,7 +6163,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: @@ -6164,7 +6227,10 @@ def is_future_flag_set(self, flag: str) -> bool: return self.modules[self.cur_mod_id].is_future_flag_set(flag) -def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike: +FunctionLikeT = TypeVar("FunctionLikeT", CallableType, Overloaded) + + +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 bc35b1a4d683..fe2a21bbc8ca 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -44,6 +44,7 @@ ParamSpecType, PartialType, ProperType, + SelfType, TupleType, Type, TypeAliasType, @@ -448,6 +449,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 @@ -600,6 +603,8 @@ def check_mixed( 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 @@ -607,6 +612,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(right, SelfType): + right = 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 2ed9523c410d..ae56db0a369f 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -47,6 +47,7 @@ FINAL_TYPE_NAMES, LITERAL_TYPE_NAMES, NEVER_NAMES, + SELF_TYPE_NAMES, TYPE_ALIAS_NAMES, AnyType, CallableArgument, @@ -65,6 +66,7 @@ PlaceholderType, RawExpressionType, RequiredType, + SelfType, StarType, SyntheticTypeVisitor, TrivialSyntheticTypeTranslator, @@ -565,6 +567,17 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Typ ) 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") @@ -1337,13 +1350,18 @@ def bind_function_type_variables( if fun_type.variables: defs = [] 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) - binding = self.tvar_scope.bind_new(var.name, var_expr) - defs.append(binding) + 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 + assert isinstance(var_expr, TypeVarLikeExpr) + binding = self.tvar_scope.bind_new(var.name, var_expr) + defs.append(binding) + else: + self.tvar_scope.bind_existing(var) + defs.append(var) return defs + typevars = self.infer_type_variables(fun_type) # Do not define a new type variable if already defined in scope. typevars = [ @@ -1407,7 +1425,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 d82b511f7d5a..b17693e429bd 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -114,6 +114,9 @@ # Supported Annotated type names. ANNOTATED_TYPE_NAMES: Final = ("typing.Annotated", "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", @@ -573,6 +576,41 @@ def deserialize(cls, data: JsonDict) -> TypeVarType: ) +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 + + 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) + + 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"], Instance.deserialize(data["upper_bound"])) + + class ParamSpecFlavor: # Simple ParamSpec reference such as "P" BARE: Final = 0 @@ -2912,6 +2950,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}" @@ -2922,6 +2962,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 = "" @@ -3021,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)})" @@ -3033,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}" @@ -3243,6 +3288,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) diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index ae966c5c9270..886adb7a1ee5 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 ff38297ae488..4b25941700ae 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 @@ -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] @@ -911,7 +911,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] @@ -1157,10 +1157,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" @@ -1313,7 +1313,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] @@ -2005,9 +2005,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 * @@ -2125,8 +2125,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: @@ -2716,8 +2716,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] @@ -2757,7 +2757,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] diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 4b2ff1af2151..17f27de5f954 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-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-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-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/check-protocols.test b/test-data/unit/check-protocols.test index 8cdfd2a3e0d9..f2387604ba18 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/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/check-typeddict.test b/test-data/unit/check-typeddict.test index 4c68b7b692ff..24dbb28f3d8b 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 44e6b66c02e6..bb72c50f19dc 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -622,21 +622,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] @@ -647,11 +647,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] diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 49f03a23177e..fad67e4e8fe0 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") @@ -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 a593a064cbb2..17977f8038a2 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>())))) @@ -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> +NameExpr:6: Self@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> +NameExpr:5: Self@target.A<0> MemberExpr:6: target.A<0> -NameExpr:6: 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 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 082a3fe69050..9680fde37ec7 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]) @@ -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]))))) @@ -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])))))))) @@ -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()))))) @@ -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..20093838f87a 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())))) @@ -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())))) @@ -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..270d8fed8e19 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 @@ -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: Self@A, builtins.object)) [case testOverloadedUnboundMethodWithImplicitSig] ## 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 @@ -978,7 +978,7 @@ 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(7) : def [t] (self: Self@A[t`1], x: t`1) MemberExpr(9) : def (self: A[B], x: B) [case testUnboundOverloadedMethodOfGenericClass] @@ -1159,7 +1159,7 @@ class A: self.x = ( A()) [out] -NameExpr(5) : A +NameExpr(5) : Self@A NameExpr(6) : def () -> A [case testListMultiplicationInContext]