mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-17 11:17:17 +03:00
Fixed a bug that resulted in a false positive when an expression of type type[Self]
was used as the base type for a member access expression that was then used to call an instance method on that class. This addresses #5530. (#5532)
Co-authored-by: Eric Traut <erictr@microsoft.com>
This commit is contained in:
parent
5be5852603
commit
d7b0a85f1d
@ -5602,7 +5602,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
type: ClassType.isClassProperty(lookupClass)
|
||||
? baseTypeClass
|
||||
: isAccessedThroughObject
|
||||
? bindToType || ClassType.cloneAsInstance(baseTypeClass)
|
||||
? bindToType ?? ClassType.cloneAsInstance(baseTypeClass)
|
||||
: NoneType.createInstance(),
|
||||
},
|
||||
},
|
||||
@ -5801,6 +5801,20 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
// If this function is an instance member (e.g. a lambda that was
|
||||
// assigned to an instance variable), don't perform any binding.
|
||||
if (!isAccessedThroughObject || (memberInfo && !memberInfo.isInstanceMember)) {
|
||||
let effectiveBindToType = bindToType;
|
||||
|
||||
if (bindToType && !isInstantiableMetaclass(baseTypeClass)) {
|
||||
// If bindToType is an instantiable class or TypeVar but we're targeting
|
||||
// an instance method (in a non-metaclass), we need to convert
|
||||
// the bindToType to an instance.
|
||||
const targetMethod = isFunction(concreteSubtype)
|
||||
? concreteSubtype
|
||||
: concreteSubtype.overloads[0];
|
||||
if (FunctionType.isInstanceMethod(targetMethod) && !TypeBase.isInstance(bindToType)) {
|
||||
effectiveBindToType = convertToInstance(bindToType) as ClassType | TypeVarType;
|
||||
}
|
||||
}
|
||||
|
||||
return bindFunctionToClassOrObject(
|
||||
isAccessedThroughObject ? ClassType.cloneAsInstance(baseTypeClass) : baseTypeClass,
|
||||
concreteSubtype,
|
||||
@ -5808,7 +5822,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
errorNode,
|
||||
/* recursionCount */ undefined,
|
||||
treatConstructorAsClassMember,
|
||||
bindToType
|
||||
effectiveBindToType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
# This sample tests the case where a `type[T]` or `type[Self]` typevar is
|
||||
# used as the base for a member access but is then used to call an
|
||||
# instance method on the resulting class.
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
||||
class A:
|
||||
@classmethod
|
||||
def method1(cls) -> None:
|
||||
cls.method2
|
||||
|
||||
@contextmanager
|
||||
def method2(self):
|
||||
yield
|
@ -525,6 +525,11 @@ test('MemberAccess21', () => {
|
||||
TestUtils.validateResults(analysisResults, 1);
|
||||
});
|
||||
|
||||
test('MemberAccess22', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['memberAccess22.py']);
|
||||
TestUtils.validateResults(analysisResults, 0);
|
||||
});
|
||||
|
||||
test('DataClassNamedTuple1', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['dataclassNamedTuple1.py']);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user