diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index df9133d7a..5d142b98b 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -11801,12 +11801,23 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions } const fileInfo = AnalyzerNodeInfo.getFileInfo(name); + const typeAliasScopeId = getScopeIdForNode(name); + + const boundTypeVars = typeParameters.filter(typeVar => typeVar.scopeId !== typeAliasScopeId); + if (boundTypeVars.length > 0) { + addError( + Localizer.Diagnostic.genericTypeAliasBoundTypeVar().format({ + names: boundTypeVars.map(t => `${t.details.name}`).join(', ') + }), + errorNode + ); + } return TypeBase.cloneForTypeAlias( type, name.value, `${fileInfo.moduleName}.${name.value}`, - getScopeIdForNode(name), + typeAliasScopeId, typeParameters.length > 0 ? typeParameters : undefined ); } diff --git a/packages/pyright-internal/src/localization/localize.ts b/packages/pyright-internal/src/localization/localize.ts index 815d21cb3..930a55e71 100644 --- a/packages/pyright-internal/src/localization/localize.ts +++ b/packages/pyright-internal/src/localization/localize.ts @@ -392,6 +392,8 @@ export namespace Localizer { export const genericClassAssigned = () => getRawString('Diagnostic.genericClassAssigned'); export const genericClassDeleted = () => getRawString('Diagnostic.genericClassDeleted'); export const genericNotAllowed = () => getRawString('Diagnostic.genericNotAllowed'); + export const genericTypeAliasBoundTypeVar = () => + new ParameterizedString<{ names: string }>(getRawString('Diagnostic.genericTypeAliasBoundTypeVar')); export const genericTypeArgMissing = () => getRawString('Diagnostic.genericTypeArgMissing'); export const genericTypeArgTypeVar = () => getRawString('Diagnostic.genericTypeArgTypeVar'); export const genericTypeArgUnique = () => getRawString('Diagnostic.genericTypeArgUnique'); diff --git a/packages/pyright-internal/src/localization/package.nls.en-us.json b/packages/pyright-internal/src/localization/package.nls.en-us.json index 4631f51dd..cf20337d5 100644 --- a/packages/pyright-internal/src/localization/package.nls.en-us.json +++ b/packages/pyright-internal/src/localization/package.nls.en-us.json @@ -157,6 +157,7 @@ "genericClassAssigned": "Generic class type cannot be assigned", "genericClassDeleted": "Generic class type cannot be deleted", "genericNotAllowed": "\"Generic\" is not valid in this context", + "genericTypeAliasBoundTypeVar": "Generic type alias within class cannot use bound type variables {names}", "genericTypeArgMissing": "\"Generic\" requires at least one type argument", "genericTypeArgTypeVar": "Type argument for \"Generic\" must be a type variable", "genericTypeArgUnique": "Type arguments for \"Generic\" must be unique", diff --git a/packages/pyright-internal/src/tests/samples/typeAlias5.py b/packages/pyright-internal/src/tests/samples/typeAlias5.py index 592bc2964..3ac15ebf2 100644 --- a/packages/pyright-internal/src/tests/samples/typeAlias5.py +++ b/packages/pyright-internal/src/tests/samples/typeAlias5.py @@ -2,7 +2,7 @@ # TypeVars. from datetime import datetime -from typing import IO, List, Type, TypeVar, Union +from typing import IO, Dict, Generic, List, Type, TypeVar, Union _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") @@ -39,3 +39,12 @@ v2: FooIsh[Bar] = Bar() # This should generate an error. v3: FooIsh[Type[Bar]] = 42 + + +MyTypeAlias = Dict[_T1, _T2] + + +class MyClass1(Generic[_T1, _T2]): + # This should generate an error because S and T are bound + # type variables. + MyTypeAlias = Dict[_T1, _T2] diff --git a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts index 047f1a8ee..2d736b9a1 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts @@ -309,7 +309,7 @@ test('TypeAlias4', () => { test('TypeAlias5', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeAlias5.py']); - TestUtils.validateResults(analysisResults, 2); + TestUtils.validateResults(analysisResults, 3); }); test('TypeAlias6', () => {