From f6016a20525967de161bc7ba63ff00fd6d3b3038 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Mon, 2 Mar 2026 12:40:48 +0100 Subject: [PATCH] Made PEP 747 (Annotating Type Forms) no longer experimental --- docs/features.md | 2 +- .../pyright-internal/src/analyzer/sentinel.ts | 6 +- .../src/analyzer/typeEvaluator.ts | 88 +++++-------------- 3 files changed, 22 insertions(+), 74 deletions(-) diff --git a/docs/features.md b/docs/features.md index c8bd58429888..29202f8fc74d 100644 --- a/docs/features.md +++ b/docs/features.md @@ -38,7 +38,7 @@ Pyright supports [configuration files](configuration.md) that provide granular c * [PEP 728](https://www.python.org/dev/peps/pep-0728/) TypedDict with typed extra items * [PEP 742](https://www.python.org/dev/peps/pep-0742/) narrowing types with TypeIs * [PEP 746](https://www.python.org/dev/peps/pep-0746/) (experimental) type checking annotated metadata -* [PEP 747](https://www.python.org/dev/peps/pep-0747/) (experimental) annotating type forms +* [PEP 747](https://www.python.org/dev/peps/pep-0747/) annotating type forms * [PEP 764](https://www.python.org/dev/peps/pep-0764/) (experimental) inline typed dictionaries * Type inference for function return values, instance variables, class variables, and globals * Type guards that understand conditional code flow constructs like if/else statements diff --git a/packages/pyright-internal/src/analyzer/sentinel.ts b/packages/pyright-internal/src/analyzer/sentinel.ts index 79b679cf5694..690b9a162c43 100644 --- a/packages/pyright-internal/src/analyzer/sentinel.ts +++ b/packages/pyright-internal/src/analyzer/sentinel.ts @@ -77,11 +77,7 @@ export function createSentinelType( classType = ClassType.cloneWithLiteral(classType, new SentinelLiteral(fullClassName, className)); let instanceType = ClassType.cloneAsInstance(classType); - - // Is TypeForm supported? - if (fileInfo.diagnosticRuleSet.enableExperimentalFeatures) { - instanceType = TypeBase.cloneWithTypeForm(instanceType, instanceType); - } + instanceType = TypeBase.cloneWithTypeForm(instanceType, instanceType); return instanceType; } diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index 6cd8a1b8d814..53b3b04b2e78 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -1089,10 +1089,7 @@ export function createTypeEvaluator( if (isAny(anySpecialForm)) { TypeBase.setSpecialForm(anySpecialForm, anyClass); - - if (isTypeFormSupported(node)) { - TypeBase.setTypeForm(anySpecialForm, convertToInstance(anySpecialForm)); - } + TypeBase.setTypeForm(anySpecialForm, convertToInstance(anySpecialForm)); } } } @@ -1715,11 +1712,7 @@ export function createTypeEvaluator( }; } - if ( - node.d.strings.length !== 1 || - node.d.strings[0].nodeType !== ParseNodeType.String || - !isTypeFormSupported(node) - ) { + if (node.d.strings.length !== 1 || node.d.strings[0].nodeType !== ParseNodeType.String) { return typeResult; } @@ -4986,10 +4979,6 @@ export function createTypeEvaluator( } function addTypeFormForSymbol(node: ExpressionNode, type: Type, flags: EvalFlags, includesVarDecl: boolean): Type { - if (!isTypeFormSupported(node)) { - return type; - } - const isValid = isSymbolValidTypeExpression(type, includesVarDecl); // If the type already has type information associated with it, don't replace. @@ -7630,10 +7619,7 @@ export function createTypeEvaluator( ...aliasInfo, typeArgs: aliasTypeArgs, }); - - if (isTypeFormSupported(node)) { - type = TypeBase.cloneWithTypeForm(type, reportedError ? undefined : convertToInstance(type)); - } + type = TypeBase.cloneWithTypeForm(type, reportedError ? undefined : convertToInstance(type)); if (baseType.props?.typeAliasInfo) { return { type, node }; @@ -8804,7 +8790,7 @@ export function createTypeEvaluator( } const typeFormResult = getTypeOfArgExpectingType(convertNodeToArg(node.d.args[0]), { - typeFormArg: isTypeFormSupported(node), + typeFormArg: true, noNonTypeSpecialForms: true, typeExpression: true, }); @@ -13824,9 +13810,7 @@ export function createTypeEvaluator( ? prefetched.noneTypeClass : convertToInstance(prefetched.noneTypeClass); - if (isTypeFormSupported(node)) { - type = TypeBase.cloneWithTypeForm(type, convertToInstance(type)); - } + type = TypeBase.cloneWithTypeForm(type, convertToInstance(type)); } } else if ( node.d.constType === KeywordType.True || @@ -15699,7 +15683,7 @@ export function createTypeEvaluator( FunctionType.addParamSpecVariadics(functionType, convertToInstance(paramSpec)); } - if (isTypeFormSupported(errorNode) && isValidTypeForm) { + if (isValidTypeForm) { functionType = TypeBase.cloneWithTypeForm(functionType, convertToInstance(functionType)); } @@ -15915,7 +15899,7 @@ export function createTypeEvaluator( result = TypeBase.cloneAsSpecialForm(result, ClassType.cloneAsInstance(prefetched.unionTypeClass)); } - if (isTypeFormSupported(node) && isValidTypeForm) { + if (isValidTypeForm) { result = TypeBase.cloneWithTypeForm(result, convertToInstance(result)); } @@ -15985,10 +15969,7 @@ export function createTypeEvaluator( return convertToInstance(validateTypeArg(typeArg) ? typeArg.type : UnknownType.create()); }); let resultType = ClassType.specialize(classType, convertedTypeArgs); - - if (isTypeFormSupported(errorNode)) { - resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); - } + resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); return resultType; } @@ -16019,10 +16000,7 @@ export function createTypeEvaluator( }); let resultType = ClassType.specialize(classType, convertedTypeArgs); - - if (isTypeFormSupported(errorNode)) { - resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); - } + resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); return resultType; } @@ -16625,7 +16603,7 @@ export function createTypeEvaluator( if (unionType.props?.typeForm) { unionType = TypeBase.cloneWithTypeForm(unionType, undefined); } - } else if (isTypeFormSupported(errorNode)) { + } else { const typeFormType = combineTypes(types.map((t) => t.props!.typeForm!)); unionType = TypeBase.cloneWithTypeForm(unionType, typeFormType); } @@ -16985,10 +16963,7 @@ export function createTypeEvaluator( if (assignedName === 'LiteralString') { specialType.shared.baseClasses.push(prefetched?.strClass ?? AnyType.create()); computeMroLinearization(specialType); - - if (isTypeFormSupported(node)) { - specialType = TypeBase.cloneWithTypeForm(specialType, convertToInstance(specialType)); - } + specialType = TypeBase.cloneWithTypeForm(specialType, convertToInstance(specialType)); } // Handle 'Never' and 'NoReturn' specially. @@ -16998,9 +16973,7 @@ export function createTypeEvaluator( specialType ); - if (isTypeFormSupported(node)) { - specialType = TypeBase.cloneWithTypeForm(specialType, convertToInstance(specialType)); - } + specialType = TypeBase.cloneWithTypeForm(specialType, convertToInstance(specialType)); } writeTypeCache(node, { type: specialType }, EvalFlags.None); @@ -21197,9 +21170,7 @@ export function createTypeEvaluator( let resultType = aliasedName === 'Never' ? NeverType.createNever() : NeverType.createNoReturn(); resultType = TypeBase.cloneAsSpecialForm(resultType, classType); - if (isTypeFormSupported(errorNode)) { - resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); - } + resultType = TypeBase.cloneWithTypeForm(resultType, convertToInstance(resultType)); return { type: resultType }; } @@ -21221,9 +21192,7 @@ export function createTypeEvaluator( typeType = explodeGenericClass(typeType); } - if (isTypeFormSupported(errorNode)) { - typeType = TypeBase.cloneWithTypeForm(typeType, convertToInstance(typeType)); - } + typeType = TypeBase.cloneWithTypeForm(typeType, convertToInstance(typeType)); return { type: typeType }; } @@ -21383,9 +21352,7 @@ export function createTypeEvaluator( typeType = explodeGenericClass(typeType); } - if (isTypeFormSupported(errorNode)) { - typeType = TypeBase.cloneWithTypeForm(typeType, convertToInstance(typeType)); - } + typeType = TypeBase.cloneWithTypeForm(typeType, convertToInstance(typeType)); return { type: typeType }; } @@ -21402,12 +21369,7 @@ export function createTypeEvaluator( /* isSpecialForm */ false ); - if (isTypeFormSupported(errorNode)) { - specializedClass = TypeBase.cloneWithTypeForm( - specializedClass, - convertToInstance(specializedClass) - ); - } + specializedClass = TypeBase.cloneWithTypeForm(specializedClass, convertToInstance(specializedClass)); return { type: specializedClass }; } @@ -21667,13 +21629,10 @@ export function createTypeEvaluator( } let specializedClass = ClassType.specialize(classType, typeArgTypes, typeArgs !== undefined); - - if (isTypeFormSupported(errorNode)) { - specializedClass = TypeBase.cloneWithTypeForm( - specializedClass, - isValidTypeForm ? convertToInstance(specializedClass) : undefined - ); - } + specializedClass = TypeBase.cloneWithTypeForm( + specializedClass, + isValidTypeForm ? convertToInstance(specializedClass) : undefined + ); return { type: specializedClass }; } @@ -28626,13 +28585,6 @@ export function createTypeEvaluator( return { sourceType: simpleSrcType, destType: simpleDestType }; } - function isTypeFormSupported(node: ParseNode) { - const fileInfo = AnalyzerNodeInfo.getFileInfo(node); - - // For now, enable only if enableExperimentalFeatures is true. - return fileInfo.diagnosticRuleSet.enableExperimentalFeatures; - } - function printType(type: Type, options?: PrintTypeOptions): string { let flags = evaluatorOptions.printTypeFlags;