[ty] Ignore ClassVar declarations when resolving instance members (#18241)

## Summary

Make sure that the following definitions all lead to the same outcome
(bug originally noticed by @AlexWaygood)

```py
from typing import ClassVar

class Descriptor:
    def __get__(self, instance, owner) -> int:
        return 42

class C:
    a: ClassVar[Descriptor]
    b: Descriptor = Descriptor()
    c: ClassVar[Descriptor] = Descriptor()

reveal_type(C().a)  # revealed: int  (previously: int | Descriptor)
reveal_type(C().b)  # revealed: int
reveal_type(C().c)  # revealed: int
```

## Test Plan

New Markdown tests
This commit is contained in:
David Peter 2025-05-21 19:23:35 +02:00 committed by GitHub
parent 02fd48132c
commit da4be789ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 1 deletions

View file

@ -777,6 +777,30 @@ reveal_type(C.variable_with_class_default1) # revealed: str
reveal_type(c_instance.variable_with_class_default1) # revealed: str
```
#### Descriptor attributes as class variables
Whether they are explicitly qualified as `ClassVar`, or just have a class level default, we treat
descriptor attributes as class variables. This test mainly makes sure that we do *not* treat them as
instance variables. This would lead to a different outcome, since the `__get__` method would not be
called (the descriptor protocol is not invoked for instance variables).
```py
from typing import ClassVar
class Descriptor:
def __get__(self, instance, owner) -> int:
return 42
class C:
a: ClassVar[Descriptor]
b: Descriptor = Descriptor()
c: ClassVar[Descriptor] = Descriptor()
reveal_type(C().a) # revealed: int
reveal_type(C().b) # revealed: int
reveal_type(C().c) # revealed: int
```
### Inheritance of class/instance attributes
#### Instance variable defined in a base class