Skip to content

Commit

Permalink
Added special-case logic to permit type[T] to be treated as assigna…
Browse files Browse the repository at this point in the history
…ble to `TypeForm[T]` in accordance with the latest draft of PEP 747. This addresses #9900. (#9933)
  • Loading branch information
erictraut authored Feb 17, 2025
1 parent ccb873d commit 397e8c9
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 deletions.
21 changes: 21 additions & 0 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24708,6 +24708,27 @@ export function createTypeEvaluator(
}

let concreteSrcType = makeTopLevelTypeVarsConcrete(srcType);

// Handle the TypeForm special form. Add a special case for
// type[T] to be assignable to TypeForm[T].
if (ClassType.isBuiltIn(destType, 'TypeForm')) {
const destTypeArg =
destType.priv.typeArgs && destType.priv.typeArgs.length > 0
? destType.priv.typeArgs[0]
: UnknownType.create();

let srcTypeArg: Type | undefined;
if (isClassInstance(concreteSrcType) && ClassType.isBuiltIn(concreteSrcType, 'type')) {
srcTypeArg = concreteSrcType;
} else if (isInstantiableClass(concreteSrcType)) {
srcTypeArg = convertToInstance(concreteSrcType);
}

if (srcTypeArg) {
return assignType(destTypeArg, srcTypeArg, diag, constraints, flags, recursionCount);
}
}

if (isClass(concreteSrcType) && TypeBase.isInstance(concreteSrcType)) {
// Handle the case where the source is an unpacked tuple.
if (
Expand Down
12 changes: 4 additions & 8 deletions packages/pyright-internal/src/tests/samples/typeForm2.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,27 +209,23 @@ def func6(x: T) -> T:
return x


# These should maybe generage errors, but given
# that the typing spec doesn't say anything about how
# to evaluate the type of a special form when it's used
# in a value expression context, it's not clear.
def func7():
# This should generate an error.
t1 = tf(Generic)

# This should generate an error.
t2 = tf(Final)

# This should generate an error.
t3 = tf(Final[int])

# This should generate an error.
t4 = tf(Concatenate[int])

# This should generate an error.
t5 = tf(Unpack[int])

# This should generate an error.
t6 = tf(Required[int])

# This should generate an error.
t7 = tf(NotRequired[int])

# This should generate an error.
t8 = tf(ReadOnly[int])
25 changes: 17 additions & 8 deletions packages/pyright-internal/src/tests/samples/typeForm4.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,28 +126,28 @@ def func5[**P, R]():

def func6[**P, R]():
# This should generate an error.
t1: TypeForm = Generic
t1: TypeForm[int] = Generic

# This should generate an error.
t2: TypeForm = Final
t2: TypeForm[int] = Final

# This should generate an error.
t3: TypeForm = Final[int]
t3: TypeForm[int] = Final[int]

# This should generate an error.
t4: TypeForm = Concatenate[int]
t4: TypeForm[int] = Concatenate[int]

# This should generate an error.
t5: TypeForm = Unpack[int]
t5: TypeForm[int] = Unpack[int]

# This should generate an error.
t6: TypeForm = Required[int]
t6: TypeForm[int] = Required[int]

# This should generate an error.
t7: TypeForm = NotRequired[int]
t7: TypeForm[int] = NotRequired[int]

# This should generate an error.
t8: TypeForm = ReadOnly[int]
t8: TypeForm[int] = ReadOnly[int]

var1 = 1
# This should generate an error.
Expand Down Expand Up @@ -230,3 +230,12 @@ def func9():

# This should generate an error.
t1.append(complex)


def func10[T](x: type[T], y: type[int]):
t1: TypeForm = x
t2: TypeForm[T] = x

t3: TypeForm = y
t4: TypeForm[int] = y
t5: TypeForm[float] = y
2 changes: 1 addition & 1 deletion packages/pyright-internal/src/tests/typeEvaluator8.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,7 @@ test('TypeForm2', () => {
configOptions.diagnosticRuleSet.enableExperimentalFeatures = true;
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeForm2.py'], configOptions);

TestUtils.validateResults(analysisResults, 8);
TestUtils.validateResults(analysisResults, 0);
});

test('TypeForm3', () => {
Expand Down

0 comments on commit 397e8c9

Please sign in to comment.