Added some additional improvements and tests from another working branch. (#8474)

This commit is contained in:
Eric Traut 2024-07-18 08:40:34 -07:00 committed by GitHub
parent c6a449d1a1
commit f4ac69bf05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 116 additions and 30 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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]:
...

View File

@ -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)

View File

@ -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]]")