mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-06 12:57:14 +03:00
Added some additional improvements and tests from another working branch. (#8474)
This commit is contained in:
parent
c6a449d1a1
commit
f4ac69bf05
@ -3923,6 +3923,12 @@ export function createTypeEvaluator(
|
||||
|
||||
// Fall back to a bound of "object" if no bound is provided.
|
||||
let boundType = subtype.shared.boundType ?? getObjectType();
|
||||
|
||||
// If this is a synthesized self/cls type var, self-specialize its type arguments.
|
||||
if (subtype.shared.isSynthesizedSelf && isClass(boundType)) {
|
||||
boundType = selfSpecializeClass(boundType);
|
||||
}
|
||||
|
||||
boundType = TypeBase.isInstantiable(subtype) ? convertToInstantiable(boundType) : boundType;
|
||||
|
||||
return addConditionToType(boundType, [{ typeVar: subtype, constraintIndex: 0 }]);
|
||||
@ -8640,18 +8646,20 @@ export function createTypeEvaluator(
|
||||
resultType = UnknownType.create();
|
||||
}
|
||||
|
||||
return {
|
||||
type: resultIsInstance ? convertToInstance(resultType, /* includeSubclasses */ false) : resultType,
|
||||
bindToSelfType: bindToType
|
||||
? TypeBase.cloneForCondition(
|
||||
let bindToSelfType: ClassType | TypeVarType | undefined;
|
||||
if (bindToType) {
|
||||
bindToSelfType = TypeBase.cloneForCondition(
|
||||
synthesizeTypeVarForSelfCls(
|
||||
ClassType.cloneIncludeSubclasses(bindToType, /* includeSubclasses */ false),
|
||||
/* isClsParam */ false
|
||||
),
|
||||
bindToType.props?.condition
|
||||
)
|
||||
: undefined,
|
||||
};
|
||||
);
|
||||
}
|
||||
|
||||
const type = resultIsInstance ? convertToInstance(resultType, /* includeSubclasses */ false) : resultType;
|
||||
|
||||
return { type, bindToSelfType };
|
||||
}
|
||||
|
||||
// Handle the super() call when used outside of a member access expression.
|
||||
@ -26341,11 +26349,6 @@ export function createTypeEvaluator(
|
||||
// should be completely reworked once there has been a public discussion
|
||||
// about the correct behavior.
|
||||
|
||||
// If the result is incomplete, do not attempt to narrow the type.
|
||||
if (assignedTypeResult.isIncomplete) {
|
||||
return assignedTypeResult;
|
||||
}
|
||||
|
||||
const narrowedType = mapSubtypes(assignedTypeResult.type, (assignedSubtype) => {
|
||||
// Handle the special case where the assigned type is a literal type.
|
||||
// Some types include very large unions of literal types, and we don't
|
||||
|
@ -2337,7 +2337,7 @@ export function synthesizeTypeVarForSelfCls(classType: ClassType, isClsParam: bo
|
||||
|
||||
const boundType = ClassType.cloneForSpecialization(
|
||||
classType,
|
||||
ClassType.getTypeParameters(classType),
|
||||
/* typeArguments */ undefined,
|
||||
/* isTypeArgumentExplicit */ false,
|
||||
/* includeSubclasses */ !!classType.priv.includeSubclasses
|
||||
);
|
||||
@ -4543,7 +4543,7 @@ class ExpectedTypeTransformer extends TypeVarTransformer {
|
||||
return TypeVarType.cloneAsInScopePlaceholder(typeVar, this._usageOffset);
|
||||
}
|
||||
|
||||
return typeVar;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
override transformParamSpec(paramSpec: TypeVarType): FunctionType | undefined {
|
||||
@ -4569,7 +4569,7 @@ class InScopePlaceholderTransformer extends TypeVarTransformer {
|
||||
return this._signatureContext.getTypeVarType(typeVar) ?? typeVar;
|
||||
}
|
||||
|
||||
return typeVar;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
override transformParamSpec(paramSpec: TypeVarType): FunctionType | undefined {
|
||||
|
@ -5,6 +5,8 @@
|
||||
# This function has no type annotations
|
||||
from typing import TypeVar
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def add(a, b):
|
||||
return a + b
|
||||
@ -14,9 +16,6 @@ async def async_call(x):
|
||||
return x
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def deco1(f: T) -> T:
|
||||
return f
|
||||
|
||||
@ -24,3 +23,13 @@ def deco1(f: T) -> T:
|
||||
@deco1
|
||||
def add2(a, b):
|
||||
return a + b
|
||||
|
||||
|
||||
def identity(a):
|
||||
return a
|
||||
|
||||
|
||||
def func1(x: T) -> T:
|
||||
a = identity(x)
|
||||
reveal_type(a, expected_text="T@func1")
|
||||
return a
|
||||
|
@ -1,6 +1,9 @@
|
||||
# This sample tests the return type inference for a generator.
|
||||
|
||||
from typing import Generator
|
||||
from typing import Awaitable, Generator, TypeVar
|
||||
|
||||
S = TypeVar("S")
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def func1() -> Generator[int, int, str]:
|
||||
@ -25,3 +28,13 @@ def func3():
|
||||
|
||||
# This should generate an error.
|
||||
[x for x in [[[1]], [[2]], [[3]]] for y in (yield x)]
|
||||
|
||||
|
||||
class ClassA[S, T](Awaitable[T]):
|
||||
def __init__(self, val: S) -> None:
|
||||
self.val = val
|
||||
|
||||
def __await__(self) -> Generator[S, T, T]:
|
||||
z = yield self.val
|
||||
reveal_type(z, expected_text="T@ClassA")
|
||||
return z
|
||||
|
@ -420,3 +420,38 @@ def func23(f: Callable[_P, _T2]) -> int:
|
||||
|
||||
def func23(f: Any) -> int:
|
||||
return 1
|
||||
|
||||
|
||||
class E1:
|
||||
...
|
||||
|
||||
|
||||
TE1 = TypeVar("TE1", bound=E1)
|
||||
|
||||
|
||||
class E2(E1, Generic[TE1]):
|
||||
...
|
||||
|
||||
|
||||
class E3(E1):
|
||||
...
|
||||
|
||||
|
||||
TE3 = TypeVar("TE3", bound=E3)
|
||||
|
||||
|
||||
class E4(E1):
|
||||
...
|
||||
|
||||
|
||||
class ClassE(E2[E4], Generic[TE1]):
|
||||
@overload
|
||||
def unpack(self: "ClassE[E2[TE3]]") -> Sequence[TE3]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def unpack(self) -> Sequence[Any]:
|
||||
...
|
||||
|
||||
def unpack(self) -> Sequence[Any]:
|
||||
...
|
||||
|
@ -1,6 +1,11 @@
|
||||
# This sample tests the type analyzer's handling of the super() call.
|
||||
|
||||
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class ClassA:
|
||||
@staticmethod
|
||||
def method1():
|
||||
@ -32,7 +37,7 @@ class ClassC(ClassA):
|
||||
super().method1()
|
||||
|
||||
|
||||
class Bar(ClassB, ClassC):
|
||||
class ClassD(ClassB, ClassC):
|
||||
def __init__(self):
|
||||
super().method2()
|
||||
super().method3()
|
||||
@ -45,19 +50,19 @@ class Bar(ClassB, ClassC):
|
||||
super().method1()
|
||||
|
||||
|
||||
super(Bar)
|
||||
super(ClassD)
|
||||
|
||||
# This should generate an error
|
||||
super(Bar).non_method2()
|
||||
super(ClassD).non_method2()
|
||||
|
||||
|
||||
super(ClassB, Bar).method1()
|
||||
super(ClassB, ClassD).method1()
|
||||
|
||||
# This should generate an error because Foo2
|
||||
# is not a subclass of Foo1.
|
||||
super(ClassB, ClassC).method1()
|
||||
|
||||
v1 = Bar()
|
||||
v1 = ClassD()
|
||||
super(ClassB, v1).method1()
|
||||
|
||||
v2 = ClassC()
|
||||
@ -66,10 +71,20 @@ v2 = ClassC()
|
||||
super(ClassB, v2).method1()
|
||||
|
||||
|
||||
class ClassD(ClassA):
|
||||
class ClassE(ClassA):
|
||||
def method5(self):
|
||||
class ClassDInner(super().method5()):
|
||||
# This should generate an error.
|
||||
x = super().method5()
|
||||
|
||||
return ClassDInner
|
||||
|
||||
|
||||
class ClassF(Generic[T]):
|
||||
def __init__(self, val: T):
|
||||
pass
|
||||
|
||||
|
||||
class ClassG(ClassF[T]):
|
||||
def __init__(self, val: T) -> None:
|
||||
super().__init__(val)
|
||||
|
@ -54,3 +54,14 @@ def func3(v2: type[Alias2], v3: type[Alias3], v4: type[Alias4]):
|
||||
reveal_type(v2, expected_text="type[int] | type[str]")
|
||||
reveal_type(v3, expected_text="type[int]")
|
||||
reveal_type(v4, expected_text="type[type[int]]")
|
||||
|
||||
|
||||
class B:
|
||||
TA1 = list
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.val = self.TA1
|
||||
|
||||
|
||||
b = B()
|
||||
reveal_type(b.val, expected_text="type[list[Unknown]]")
|
||||
|
Loading…
Reference in New Issue
Block a user