diff --git a/crates/red_knot_python_semantic/resources/mdtest/descriptor_protocol.md b/crates/red_knot_python_semantic/resources/mdtest/descriptor_protocol.md index 74dd203b02..00c0ee6da9 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/descriptor_protocol.md +++ b/crates/red_knot_python_semantic/resources/mdtest/descriptor_protocol.md @@ -285,6 +285,31 @@ C.descriptor = "something else" reveal_type(C.descriptor) # revealed: Unknown | int ``` +## `__get__` is called with correct arguments + +```py +from __future__ import annotations + +class TailoredForClassObjectAccess: + def __get__(self, instance: None, owner: type[C]) -> int: + return 1 + +class TailoredForInstanceAccess: + def __get__(self, instance: C, owner: type[C] | None = None) -> str: + return "a" + +class C: + class_object_access: TailoredForClassObjectAccess = TailoredForClassObjectAccess() + instance_access: TailoredForInstanceAccess = TailoredForInstanceAccess() + +reveal_type(C.class_object_access) # revealed: int +reveal_type(C().instance_access) # revealed: str + +# TODO: These should emit a diagnostic +reveal_type(C().class_object_access) # revealed: TailoredForClassObjectAccess +reveal_type(C.instance_access) # revealed: TailoredForInstanceAccess +``` + ## Descriptors with incorrect `__get__` signature ```py diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 338e44deba..5e3a5db004 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -1663,7 +1663,7 @@ impl<'db> Type<'db> { let member = self.static_member(db, name); let instance = None; - let owner = self.to_meta_type(db); + let owner = *self; // TODO: Handle `__get__` call errors (see above). member.map_type(|ty| ty.try_call_dunder_get(db, instance, owner).unwrap_or(ty))