mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-19 20:27:45 +03:00
Fixed regression that caused false positive error when protocol match involved a property that returned a type that was generic.
This commit is contained in:
parent
15f6164788
commit
177ea4d79d
@ -32,7 +32,13 @@ import {
|
||||
Type,
|
||||
UnknownType,
|
||||
} from './types';
|
||||
import { CanAssignFlags, computeMroLinearization, getTypeVarScopeId, isProperty } from './typeUtils';
|
||||
import {
|
||||
CanAssignFlags,
|
||||
computeMroLinearization,
|
||||
getTypeVarScopeId,
|
||||
isProperty,
|
||||
partiallySpecializeType,
|
||||
} from './typeUtils';
|
||||
import { TypeVarMap } from './typeVarMap';
|
||||
|
||||
export function validatePropertyMethod(evaluator: TypeEvaluator, method: FunctionType, errorNode: ParseNode) {
|
||||
@ -89,6 +95,9 @@ export function createProperty(
|
||||
const propertyObject = ClassType.cloneAsInstance(propertyClass);
|
||||
propertyClass.isAsymmetricDescriptor = false;
|
||||
|
||||
// Update the __set__ and __delete__ methods if present.
|
||||
updateGetSetDelMethodForClonedProperty(propertyObject, evaluator);
|
||||
|
||||
// Fill in the fget method.
|
||||
const fgetSymbol = Symbol.createWithType(
|
||||
SymbolFlags.ClassMember,
|
||||
@ -100,9 +109,6 @@ export function createProperty(
|
||||
propertyClass.details.flags |= ClassTypeFlags.ClassProperty;
|
||||
}
|
||||
|
||||
// Update the __set__ and __set__ methods if present.
|
||||
updateGetSetDelMethodForClonedProperty(propertyObject, evaluator);
|
||||
|
||||
// Fill in the __get__ method with an overload.
|
||||
addGetMethodToPropertySymbolTable(propertyObject, fget);
|
||||
|
||||
@ -187,6 +193,9 @@ export function clonePropertyWithSetter(
|
||||
}
|
||||
});
|
||||
|
||||
// Update the __get__ and __delete__ methods if present.
|
||||
updateGetSetDelMethodForClonedProperty(propertyObject, evaluator);
|
||||
|
||||
// Fill in the fset method.
|
||||
const fsetSymbol = Symbol.createWithType(
|
||||
SymbolFlags.ClassMember,
|
||||
@ -194,9 +203,6 @@ export function clonePropertyWithSetter(
|
||||
);
|
||||
fields.set('fset', fsetSymbol);
|
||||
|
||||
// Update the __get__ and __delete__ methods if present.
|
||||
updateGetSetDelMethodForClonedProperty(propertyObject, evaluator);
|
||||
|
||||
// Fill in the __set__ method.
|
||||
addSetMethodToPropertySymbolTable(propertyObject, fset, evaluator);
|
||||
|
||||
@ -243,6 +249,9 @@ export function clonePropertyWithDeleter(
|
||||
}
|
||||
});
|
||||
|
||||
// Update the __get__ and __set__ methods if present.
|
||||
updateGetSetDelMethodForClonedProperty(propertyObject, evaluator);
|
||||
|
||||
// Fill in the fdel method.
|
||||
const fdelSymbol = Symbol.createWithType(
|
||||
SymbolFlags.ClassMember,
|
||||
@ -250,9 +259,6 @@ export function clonePropertyWithDeleter(
|
||||
);
|
||||
fields.set('fdel', fdelSymbol);
|
||||
|
||||
// Update the __get__ and __set__ methods if present.
|
||||
updateGetSetDelMethodForClonedProperty(propertyObject, evaluator);
|
||||
|
||||
// Fill in the __delete__ method.
|
||||
addDelMethodToPropertySymbolTable(propertyObject, fdel, evaluator);
|
||||
|
||||
@ -481,7 +487,7 @@ export function canAssignProperty(
|
||||
|
||||
if (destAccessType && isFunction(destAccessType)) {
|
||||
const srcAccessSymbol = srcPropertyType.details.fields.get(accessorInfo.name);
|
||||
const srcAccessType = srcAccessSymbol ? evaluator.getDeclaredTypeOfSymbol(srcAccessSymbol) : undefined;
|
||||
let srcAccessType = srcAccessSymbol ? evaluator.getDeclaredTypeOfSymbol(srcAccessSymbol) : undefined;
|
||||
|
||||
if (!srcAccessType || !isFunction(srcAccessType)) {
|
||||
if (diag) {
|
||||
@ -491,6 +497,8 @@ export function canAssignProperty(
|
||||
return;
|
||||
}
|
||||
|
||||
srcAccessType = partiallySpecializeType(srcAccessType, srcClass) as FunctionType;
|
||||
|
||||
const boundDestAccessType = evaluator.bindFunctionToClassOrObject(
|
||||
objectToBind,
|
||||
destAccessType,
|
||||
|
26
packages/pyright-internal/src/tests/samples/protocol29.py
Normal file
26
packages/pyright-internal/src/tests/samples/protocol29.py
Normal file
@ -0,0 +1,26 @@
|
||||
# This sample tests the special-case handling of properties that return
|
||||
# generics within a protocol.
|
||||
|
||||
from functools import partial
|
||||
from typing_extensions import Protocol, Self
|
||||
from typing import Any, Callable, Type, TypeVar
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
class Partial(Protocol[_T]):
|
||||
@property
|
||||
def func(self) -> Callable[..., _T]:
|
||||
...
|
||||
|
||||
def __new__(
|
||||
cls: Type[Self], __func: Callable[..., _T], *args: Any, **kwargs: Any
|
||||
) -> Self:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Partial[int]):
|
||||
...
|
||||
|
||||
|
||||
f(partial(int))
|
@ -1054,6 +1054,12 @@ test('Protocol28', () => {
|
||||
TestUtils.validateResults(analysisResults, 0);
|
||||
});
|
||||
|
||||
test('Protocol29', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['protocol29.py']);
|
||||
|
||||
TestUtils.validateResults(analysisResults, 0);
|
||||
});
|
||||
|
||||
test('TypedDict1', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typedDict1.py']);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user