[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

@ -1738,9 +1738,15 @@ impl<'db> ClassLiteral<'db> {
let declared_and_qualifiers = symbol_from_declarations(db, declarations);
match declared_and_qualifiers {
Ok(SymbolAndQualifiers {
symbol: declared @ Symbol::Type(declared_ty, declaredness),
symbol: mut declared @ Symbol::Type(declared_ty, declaredness),
qualifiers,
}) => {
// For the purpose of finding instance attributes, ignore `ClassVar`
// declarations:
if qualifiers.contains(TypeQualifiers::CLASS_VAR) {
declared = Symbol::Unbound;
}
// The attribute is declared in the class body.
let bindings = use_def.public_bindings(symbol_id);