From 07f25ad4ec61f402dc5d142bebdfa0326459b323 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 12 Nov 2024 18:44:48 -0800 Subject: [PATCH] Fixed bug that results in the incorrect detection of an asymmetric descriptor if the descriptor class is generic. This addresses #9450. --- .../src/analyzer/typeEvaluator.ts | 4 ++-- .../src/tests/samples/descriptor1.py | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index ac1aa75a9016..c1229a3815ce 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -6610,8 +6610,8 @@ export function createTypeEvaluator( if (!getterSymbolResult || !setterSymbolResult) { isAsymmetric = false; } else { - let getterType = getEffectiveTypeOfSymbol(getterSymbolResult.symbol); - const setterType = getEffectiveTypeOfSymbol(setterSymbolResult.symbol); + let getterType = getTypeOfMember(getterSymbolResult); + const setterType = getTypeOfMember(setterSymbolResult); // If this is an overload, find the appropriate overload. if (isOverloaded(getterType)) { diff --git a/packages/pyright-internal/src/tests/samples/descriptor1.py b/packages/pyright-internal/src/tests/samples/descriptor1.py index b92833c3f9ba..564473c140b1 100644 --- a/packages/pyright-internal/src/tests/samples/descriptor1.py +++ b/packages/pyright-internal/src/tests/samples/descriptor1.py @@ -1,7 +1,7 @@ # This sample tests the detection and handling of asymmetric descriptors # and properties. Type narrowing should be disabled in these cases. -from typing import Any, Hashable, Iterable, Literal, overload +from typing import Any, Hashable, Iterable, Literal, Self, overload class A: @@ -101,12 +101,24 @@ def __set__(self, owner: "B", value: int | None) -> None: ... def __set__(self, owner: Any, value: int | None) -> None: ... +class Descriptor6[GT, ST]: + @overload + def __get__(self, instance: None, owner: Any) -> Self: ... + + @overload + def __get__(self, instance: Any, owner: Any) -> GT: ... + def __get__(self, instance: Any, owner: Any) -> Any: ... + + def __set__(self, instance: Any, value: ST): ... + + class B: desc1: Descriptor1 desc2: Descriptor2 desc3: Descriptor3 desc4: Descriptor4 desc5: Descriptor5 + desc6: Descriptor6[int | None, int | None] def func4(obj: B) -> Literal[3]: @@ -148,3 +160,6 @@ def func7(obj: B): obj.desc5 = 3 reveal_type(obj.desc5, expected_text="int") + + obj.desc6 = 1 + reveal_type(obj.desc6, expected_text="Literal[1]")