From 01786a5344913910ff47398a79cbacba3af1a036 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sat, 2 Nov 2024 20:09:56 -0700 Subject: [PATCH] Improved the handling of a TypeVar whose definition involves a circular definition. This partially addresses #9353. --- .../pyright-internal/src/analyzer/checker.ts | 6 +++++ .../src/analyzer/typeEvaluator.ts | 25 ++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/checker.ts b/packages/pyright-internal/src/analyzer/checker.ts index e3bdba5c1458..c1c9d31c46f6 100644 --- a/packages/pyright-internal/src/analyzer/checker.ts +++ b/packages/pyright-internal/src/analyzer/checker.ts @@ -5357,6 +5357,12 @@ export class Checker extends ParseTreeWalker { return; } + // Skip type variables that have been internally synthesized + // for a variety of reasons. + if (param.shared.isSynthesized) { + return; + } + // Skip type variables with auto-variance. if (param.shared.declaredVariance === Variance.Auto) { return; diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index f78ae9c697b0..a1467b287402 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -17232,8 +17232,7 @@ export function createTypeEvaluator( arg.d.valueExpr ); } - genericTypeParams = []; - addTypeVarsToListIfUnique(genericTypeParams, getTypeVarArgsRecursive(argType)); + genericTypeParams = buildTypeParamsFromTypeArgs(argType); } } } else if ( @@ -17249,8 +17248,7 @@ export function createTypeEvaluator( arg.d.valueExpr ); } - protocolTypeParams = []; - addTypeVarsToListIfUnique(protocolTypeParams, getTypeVarArgsRecursive(argType)); + protocolTypeParams = buildTypeParamsFromTypeArgs(argType); if (node.d.typeParams && protocolTypeParams.length > 0) { addDiagnostic( @@ -17749,6 +17747,25 @@ export function createTypeEvaluator( }); } + function buildTypeParamsFromTypeArgs(classType: ClassType): TypeVarType[] { + const typeParams: TypeVarType[] = []; + const typeArgs = classType.priv.typeArgs ?? []; + + typeArgs.forEach((typeArg, index) => { + if (isTypeVar(typeArg)) { + typeParams.push(typeArg); + return; + } + + // Synthesize a dummy type parameter. + const typeVar = TypeVarType.createInstance(`__P${index}`); + typeVar.shared.isSynthesized = true; + typeParams.push(typeVar); + }); + + return typeParams; + } + // Determines whether the type parameters has a default that refers to another // type parameter. If so, validates that it is in the list of "live" type // parameters and updates the scope of the type parameter referred to in the