From 3aea365b5ab0469f12f8058d1445e88e0bf6e502 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 27 Dec 2021 17:00:18 -0700 Subject: [PATCH] Fixed regression in type alias handling. --- .../src/analyzer/typeEvaluator.ts | 13 +++++++++++-- .../src/tests/samples/typeAlias11.py | 16 ++++++++++++++++ .../src/tests/typeEvaluator3.test.ts | 6 ++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 packages/pyright-internal/src/tests/samples/typeAlias11.py diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index 790390eaa..f78c9c2dd 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -6099,7 +6099,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions typeArgs.push(getTypeArgTypeResult(item, index)); }); - // Mark the node's type so it isn't reevaluated later. + // Set the node's type so it isn't reevaluated later. setTypeForNode(node.items[0].valueExpression); } else { node.items.forEach((arg, index) => { @@ -6153,7 +6153,8 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions node, }; - writeTypeCache(node, UnknownType.create(), adjustedFlags, /* isIncomplete */ false); + // Set the node's type so it isn't reevaluated later. + setTypeForNode(node); } else { typeResult = getTypeOfExpression(node, /* expectedType */ undefined, adjustedFlags); @@ -12974,12 +12975,19 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions if (!rightHandType) { // Determine whether there is a declared type. const declaredType = getDeclaredTypeForExpression(node.leftExpression, { method: 'set' }); + let flags: EvaluatorFlags = EvaluatorFlags.None; if (fileInfo.isStubFile) { // An assignment of ellipsis means "Any" within a type stub file. flags |= EvaluatorFlags.ConvertEllipsisToUnknown; } + if (node.rightExpression.nodeType === ParseNodeType.Name) { + // Don't specialize a generic class on assignment (e.g. "x = list") because + // we may want to later specialize it (e.g. "x[int]"). + flags |= EvaluatorFlags.DoNotSpecialize; + } + let typeAliasNameNode: NameNode | undefined; let isSpeculativeTypeAlias = false; @@ -12989,6 +12997,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions EvaluatorFlags.EvaluateStringLiteralAsType | EvaluatorFlags.ParamSpecDisallowed | EvaluatorFlags.TypeVarTupleDisallowed; + flags &= ~EvaluatorFlags.DoNotSpecialize; typeAliasNameNode = (node.leftExpression as TypeAnnotationNode).valueExpression as NameNode; } else if (node.leftExpression.nodeType === ParseNodeType.Name) { diff --git a/packages/pyright-internal/src/tests/samples/typeAlias11.py b/packages/pyright-internal/src/tests/samples/typeAlias11.py new file mode 100644 index 000000000..ee6206351 --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/typeAlias11.py @@ -0,0 +1,16 @@ +# This sample tests the simple aliasing of a generic class with no +# type arguments. + +from typing import Generic, Literal, TypeVar + + +_T = TypeVar("_T") + + +class ClassA(Generic[_T]): + def __init__(self, x: _T): + pass + + +A = ClassA +t1: Literal["ClassA[int]"] = reveal_type(A(3)) diff --git a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts index 90d4e89f6..34b65a90c 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts @@ -372,6 +372,12 @@ test('TypeAlias10', () => { TestUtils.validateResults(analysisResults, 4); }); +test('TypeAlias11', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeAlias11.py']); + + TestUtils.validateResults(analysisResults, 0); +}); + test('RecursiveTypeAlias1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['recursiveTypeAlias1.py']);