diff --git a/mypy/semanal.py b/mypy/semanal.py index e1d104921569..c079a865af1d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4724,7 +4724,7 @@ def make_name_lvalue_point_to_existing_def( and original_def.node.is_inferred ): for func in self.scope.functions: - func.def_or_infer_vars = True + mark_as_top_level(func) def analyze_tuple_or_list_lvalue(self, lval: TupleExpr, explicit_type: bool = False) -> None: """Analyze an lvalue or assignment target that is a list or tuple.""" @@ -4809,7 +4809,7 @@ def analyze_member_lvalue( # TODO: should we also set lval.kind = MDEF? self.type.names[lval.name] = SymbolTableNode(MDEF, v, implicit=True) for func in self.scope.functions: - func.def_or_infer_vars = True + mark_as_top_level(func) if self.is_self_member_ref(lval) or self.is_cls_member_ref(lval): assert self.type, "Self or cls member outside a class" @@ -4821,7 +4821,7 @@ def analyze_member_lvalue( and cur_node.node.is_initialized_in_class ): for func in self.scope.functions: - func.def_or_infer_vars = True + mark_as_top_level(func) self.check_lvalue_validity(lval.node, lval) def is_self_member_ref(self, memberexpr: MemberExpr) -> bool: @@ -8617,6 +8617,18 @@ def erase_func_annotations(func: FuncDef) -> None: func.unanalyzed_type = None +def mark_as_top_level(func: FuncBase) -> None: + """Mark a function to be processed as part of module top level. + + A non-trivial part here is that we want to keep overloads as a whole. + """ + func.def_or_infer_vars = True + if isinstance(func, OverloadedFuncDef): + for item in func.items: + defn = item if isinstance(item, FuncDef) else item.func + defn.def_or_infer_vars = True + + def dotted_identifier_leftmost(s: str) -> str | None: """The leftmost component of s, if s is a dotted identifier, else None. diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 9f0d5462cba3..70d9b388d7fd 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -9789,3 +9789,16 @@ class C(Generic[T]): ... [file lib.py] from typing import TypeVar T = TypeVar("T", default=int, bound=str) # E: TypeVar default must be a subtype of the bound type + +[case testSettablePropertyGetterCheckedWhenPartOfInterface] +class A: + @property + def p(self) -> str: + def nested() -> int: + return "no" # E: Incompatible return value type (got "str", expected "int") + return 0 # E: Incompatible return value type (got "int", expected "str") + + @p.setter + def p(self, value: int) -> None: + self.x = value +[builtins fixtures/property.pyi]