diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 18468fac335c..20345f4773a1 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -1086,7 +1086,7 @@ def analyze_class_attribute_access( if not node.node.is_classvar and node.node.info.self_type: def_vars.add(node.node.info.self_type) typ_vars = set(get_type_vars(t)) - if def_vars & typ_vars: + if any(tv for tv in def_vars & typ_vars if tv.upper_bound != itype): if node.node.is_classvar: message = message_registry.GENERIC_CLASS_VAR_ACCESS else: diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index 0cd3b03dca60..a3297d471f6f 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -2233,6 +2233,22 @@ xi = C[int].x # E: Access to generic instance variables via class is ambiguous reveal_type(xi) # N: Revealed type is "builtins.int" [builtins fixtures/classmethod.pyi] +[case testGenericClassAttrSelfType] +from typing import TypeVar, Generic, Self, Type, Mapping + +class A: + d: Mapping[str, Self] + + @classmethod + def make(cls) -> Self: + return cls.d["asdf"] + +def main(A_t: Type[A]) -> None: + reveal_type(A.d) # N: Revealed type is "typing.Mapping[builtins.str, __main__.A]" + reveal_type(A_t.d) # N: Revealed type is "typing.Mapping[builtins.str, __main__.A]" + +[builtins fixtures/classmethod.pyi] + [case testGenericClassAttrUnboundOnSubClass] from typing import Generic, TypeVar, Tuple T = TypeVar('T')