Skip to content

Commit

Permalink
Fixed a bug that resulted in incorrect type evaluation when calling a…
Browse files Browse the repository at this point in the history
… generic class constructor from within that class implementation. This addresses #3927.
  • Loading branch information
msfterictraut committed Sep 19, 2022
1 parent 92b90d2 commit b5e461b
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 6 deletions.
11 changes: 7 additions & 4 deletions packages/pyright-internal/src/analyzer/typeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2668,7 +2668,7 @@ class TypeVarTransformer {
// _pendingTypeVarTransformations set.
const typeVarName = TypeVarType.getNameWithScope(type);
if (!this._pendingTypeVarTransformations.has(typeVarName)) {
replacementType = this.transformTypeVar(type);
replacementType = this.transformTypeVar(type) ?? type;

if (!this._isTransformingTypeArg) {
this._pendingTypeVarTransformations.add(typeVarName);
Expand Down Expand Up @@ -2739,7 +2739,7 @@ class TypeVarTransformer {
return type;
}

transformTypeVar(typeVar: TypeVarType): Type {
transformTypeVar(typeVar: TypeVarType): Type | undefined {
return typeVar;
}

Expand Down Expand Up @@ -2840,7 +2840,8 @@ class TypeVarTransformer {
} else {
const typeParamName = TypeVarType.getNameWithScope(typeParam);
if (!this._pendingTypeVarTransformations.has(typeParamName)) {
replacementType = this.transformTypeVar(typeParam);
const transformedType = this.transformTypeVar(typeParam);
replacementType = transformedType ?? typeParam;

if (replacementType !== typeParam) {
if (!this._isTransformingTypeArg) {
Expand All @@ -2849,6 +2850,8 @@ class TypeVarTransformer {
this._pendingTypeVarTransformations.delete(typeParamName);
}

specializationNeeded = true;
} else if (transformedType !== undefined && !classType.typeArguments) {
specializationNeeded = true;
}
}
Expand Down Expand Up @@ -3147,7 +3150,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
}
}

return typeVar;
return undefined;
}

override transformUnionSubtype(preTransform: Type, postTransform: Type): Type | undefined {
Expand Down
28 changes: 27 additions & 1 deletion packages/pyright-internal/src/tests/samples/genericTypes94.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# specialized with type variables in a recursive manner.

from dataclasses import dataclass
from typing import Callable, Generic, TypeVar
from typing import Callable, Generic, Iterable, Iterator, TypeVar, overload

S = TypeVar("S")
T = TypeVar("T")
Expand Down Expand Up @@ -54,3 +54,29 @@ def method1(self, val: U) -> "ClassC[U, S]":
else:
return ClassC(self.value)


T_co = TypeVar("T_co", covariant=True)

class ClassD(Generic[T_co]):
@overload
def __init__(self, arg: Iterable[T_co]) -> None:
...

@overload
def __init__(self, arg: Callable[[], Iterable[T_co]]) -> None:
...

def __init__(self, arg: Iterable[T_co] | Callable[[], Iterable[T_co]]) -> None:
...

def __iter__(self) -> Iterator[T_co]:
...


class ClassE(ClassD[T_co]):
def method(self) -> "ClassE[ClassE[T_co]]":
def inner():
for x in self:
yield ClassE(lambda: [x])

return ClassE(inner)
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class D(C[float]):
...


reveal_type(C.prop, expected_text="CachedSlotProperty[Self@C[T@C], int]")
reveal_type(C.prop, expected_text="CachedSlotProperty[C[T@C], int]")
reveal_type(D.prop, expected_text="CachedSlotProperty[D, int]")


Expand Down

0 comments on commit b5e461b

Please sign in to comment.