diff --git a/README.md b/README.md index 201898d93..d21fbd85b 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,6 @@ Pyright supports [configuration files](/docs/configuration.md) that provide gran * [PEP 655](https://www.python.org/dev/peps/pep-0655/) required typed dictionary items * [PEP 673](https://www.python.org/dev/peps/pep-0673/) Self type * [PEP 675](https://www.python.org/dev/peps/pep-0675/) arbitrary literal strings -* [PEP 677](https://www.python.org/dev/peps/pep-0677/) callable type syntax * [PEP 681](https://www.python.org/dev/peps/pep-0681/) dataclass transform * 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/parseTreeUtils.ts b/packages/pyright-internal/src/analyzer/parseTreeUtils.ts index 0787fd255..9e01a51ea 100644 --- a/packages/pyright-internal/src/analyzer/parseTreeUtils.ts +++ b/packages/pyright-internal/src/analyzer/parseTreeUtils.ts @@ -433,25 +433,6 @@ export function printExpression(node: ExpressionNode, flags = PrintExpressionFla case ParseNodeType.Set: { return node.entries.map((entry) => printExpression(entry, flags)).join(', '); } - - case ParseNodeType.ArrowCallable: { - const paramsText = node.parameters.map((param) => { - let prefix = ''; - if (param.category === ParameterCategory.VarArgList) { - prefix = '*'; - } else if (param.category === ParameterCategory.VarArgDictionary) { - prefix = '**'; - } - - const typeText = printExpression(param.typeAnnotation); - - return `${prefix}${typeText}`; - }); - - const optionalAsync = node.isAsync ? 'async ' : ''; - - return `${optionalAsync}(${paramsText.join(', ')}) -> ${printExpression(node.returnTypeAnnotation)}`; - } } return ''; @@ -1762,9 +1743,6 @@ export function printParseNodeType(type: ParseNodeType) { case ParseNodeType.PatternClassArgument: return 'PatternClassArgument'; - - case ParseNodeType.ArrowCallable: - return 'ArrowCallable'; } assertNever(type); diff --git a/packages/pyright-internal/src/analyzer/parseTreeWalker.ts b/packages/pyright-internal/src/analyzer/parseTreeWalker.ts index aa12f3223..2a3dde318 100644 --- a/packages/pyright-internal/src/analyzer/parseTreeWalker.ts +++ b/packages/pyright-internal/src/analyzer/parseTreeWalker.ts @@ -10,7 +10,6 @@ import { fail } from '../common/debug'; import { ArgumentNode, - ArrowCallableNode, AssertNode, AssignmentExpressionNode, AssignmentNode, @@ -572,12 +571,6 @@ export class ParseTreeWalker { } break; - case ParseNodeType.ArrowCallable: - if (this.visitArrowCallable(node)) { - return [...node.parameters.map((param) => param.typeAnnotation), node.returnTypeAnnotation]; - } - break; - default: fail('Unexpected node type'); break; @@ -591,10 +584,6 @@ export class ParseTreeWalker { return true; } - visitArrowCallable(node: ArrowCallableNode) { - return true; - } - visitAssert(node: AssertNode) { return true; } diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index dcb1f8a95..127e2e77e 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -28,7 +28,6 @@ import { TextRange } from '../common/textRange'; import { Localizer } from '../localization/localize'; import { ArgumentCategory, - ArrowCallableNode, AssignmentNode, AugmentedAssignmentNode, BinaryOperationNode, @@ -1071,11 +1070,6 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions break; } - case ParseNodeType.ArrowCallable: { - typeResult = getTypeFromArrowCallable(node, flags); - break; - } - case ParseNodeType.Assignment: { typeResult = getTypeOfExpression(node.rightExpression); assignTypeToExpression( @@ -11457,136 +11451,6 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions return type; } - function getTypeFromArrowCallable(node: ArrowCallableNode, flags: EvaluatorFlags): TypeResult { - // Emit an error if this will cause a runtime exception. - const fileInfo = AnalyzerNodeInfo.getFileInfo(node); - if ( - !fileInfo.isStubFile && - fileInfo.executionEnvironment.pythonVersion < PythonVersion.V3_11 && - (flags & EvaluatorFlags.NotParsedByInterpreter) === 0 - ) { - addError(Localizer.Diagnostic.arrowCallableIllegal(), node); - } - - const isIncomplete = false; - const functionType = FunctionType.createInstantiable('', '', '', FunctionTypeFlags.None); - - const enclosingScope = ParseTreeUtils.getEnclosingClassOrFunction(node); - - // Handle the case where the Callable has no enclosing scope. This can - // happen in the case where a generic function return type is annotated - // with a generic type alias that includes a Callable in its definition. - functionType.details.typeVarScopeId = enclosingScope - ? getScopeIdForNode(enclosingScope) - : WildcardTypeVarScopeId; - - const returnAnnotationOptions: AnnotationTypeOptions = {}; - if ((flags & EvaluatorFlags.AssociateTypeVarsWithCurrentScope) !== 0) { - returnAnnotationOptions.associateTypeVarsWithScope = true; - } - if ((flags & EvaluatorFlags.NotParsedByInterpreter) !== 0) { - returnAnnotationOptions.notParsedByInterpreter = true; - } - - let returnType = getTypeOfAnnotation(node.returnTypeAnnotation, returnAnnotationOptions); - if (node.isAsync) { - functionType.details.flags |= FunctionTypeFlags.Async; - const awaitableType = getTypingType(node, 'Awaitable'); - if (awaitableType && isInstantiableClass(awaitableType)) { - returnType = ClassType.cloneForSpecialization( - ClassType.cloneAsInstance(awaitableType), - [returnType], - /* isTypeArgumentExplicit */ true - ); - } else { - returnType = UnknownType.create(); - } - } - - functionType.details.declaredReturnType = returnType; - - let addPositionalOnly = true; - - const paramAnnotationOptions: AnnotationTypeOptions = { - allowParamSpec: true, - allowTypeVarTuple: true, - }; - - if ((flags & EvaluatorFlags.AssociateTypeVarsWithCurrentScope) !== 0) { - paramAnnotationOptions.associateTypeVarsWithScope = true; - } - - node.parameters.forEach((param, paramIndex) => { - const paramType = getTypeOfAnnotation(param.typeAnnotation, paramAnnotationOptions); - - if (isEllipsisType(paramType)) { - if (param.category !== ParameterCategory.Simple || paramIndex !== 0 || node.parameters.length > 1) { - addError(Localizer.Diagnostic.ellipsisContext(), param.typeAnnotation); - FunctionType.addParameter(functionType, { - category: ParameterCategory.Simple, - name: `__p${paramIndex}`, - isNameSynthesized: true, - type: UnknownType.create(), - hasDeclaredType: true, - }); - } else { - functionType.details.flags |= FunctionTypeFlags.SkipArgsKwargsCompatibilityCheck; - FunctionType.addDefaultParameters(functionType); - addPositionalOnly = false; - } - } else if (param.category === ParameterCategory.Simple) { - if (isTypeVar(paramType) && paramType.details.isParamSpec) { - addError(Localizer.Diagnostic.arrowCallableParamSpec(), param.typeAnnotation); - } - - if (isTypeVar(paramType) && paramType.details.isVariadic && !paramType.isVariadicUnpacked) { - addError(Localizer.Diagnostic.arrowCallableVariadicTypeVar(), param.typeAnnotation); - } - - FunctionType.addParameter(functionType, { - category: ParameterCategory.Simple, - name: `__p${paramIndex}`, - isNameSynthesized: true, - type: convertToInstance(paramType), - hasDeclaredType: true, - }); - } else if (param.category === ParameterCategory.VarArgList) { - if (!isVariadicTypeVar(paramType)) { - addError(Localizer.Diagnostic.arrowCallableNotVariadicTypeVar(), param.typeAnnotation); - } else { - if (paramType.isVariadicUnpacked) { - addError(Localizer.Diagnostic.arrowCallableVariadicTypeVarUnpacked(), param.typeAnnotation); - } - - FunctionType.addParameter(functionType, { - category: ParameterCategory.Simple, - name: `__p${paramIndex}`, - isNameSynthesized: true, - type: convertToInstance(TypeVarType.cloneForUnpacked(paramType)), - hasDeclaredType: true, - }); - } - } else if (param.category === ParameterCategory.VarArgDictionary) { - if (!isParamSpec(paramType)) { - addError(Localizer.Diagnostic.arrowCallableNotParamSpec(), param.typeAnnotation); - } else if (paramIndex !== node.parameters.length - 1) { - addError(Localizer.Diagnostic.arrowCallableParamSpecNotLast(), param.typeAnnotation); - } else { - functionType.details.paramSpec = paramType; - } - } - }); - - if (addPositionalOnly) { - FunctionType.addParameter(functionType, { - category: ParameterCategory.Simple, - type: UnknownType.create(), - }); - } - - return { node, type: functionType, isIncomplete }; - } - function getTypeFromDictionary(node: DictionaryNode, expectedType: Type | undefined): TypeResult { // If the expected type is a union, analyze for each of the subtypes // to find one that matches. @@ -16421,8 +16285,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions node.nodeType === ParseNodeType.PatternMapping || node.nodeType === ParseNodeType.PatternValue || node.nodeType === ParseNodeType.PatternMappingKeyEntry || - node.nodeType === ParseNodeType.PatternMappingExpandEntry || - node.nodeType === ParseNodeType.ArrowCallable + node.nodeType === ParseNodeType.PatternMappingExpandEntry ); } diff --git a/packages/pyright-internal/src/localization/localize.ts b/packages/pyright-internal/src/localization/localize.ts index 15cfd056d..68735cf6a 100644 --- a/packages/pyright-internal/src/localization/localize.ts +++ b/packages/pyright-internal/src/localization/localize.ts @@ -207,15 +207,6 @@ export namespace Localizer { export const argPositionalExpectedOne = () => getRawString('Diagnostic.argPositionalExpectedOne'); export const argTypePartiallyUnknown = () => getRawString('Diagnostic.argTypePartiallyUnknown'); export const argTypeUnknown = () => getRawString('Diagnostic.argTypeUnknown'); - export const arrowCallableIllegal = () => getRawString('Diagnostic.arrowCallableIllegal'); - export const arrowCallableNeedsParen = () => getRawString('Diagnostic.arrowCallableNeedsParen'); - export const arrowCallableNotParamSpec = () => getRawString('Diagnostic.arrowCallableNotParamSpec'); - export const arrowCallableNotVariadicTypeVar = () => getRawString('Diagnostic.arrowCallableNotVariadicTypeVar'); - export const arrowCallableParamSpec = () => getRawString('Diagnostic.arrowCallableParamSpec'); - export const arrowCallableParamSpecNotLast = () => getRawString('Diagnostic.arrowCallableParamSpecNotLast'); - export const arrowCallableVariadicTypeVar = () => getRawString('Diagnostic.arrowCallableVariadicTypeVar'); - export const arrowCallableVariadicTypeVarUnpacked = () => - getRawString('Diagnostic.arrowCallableVariadicTypeVarUnpacked'); export const assertAlwaysTrue = () => getRawString('Diagnostic.assertAlwaysTrue'); export const assignmentExprContext = () => getRawString('Diagnostic.assignmentExprContext'); export const assignmentExprComprehension = () => 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 80f5c4d2e..162909f9c 100644 --- a/packages/pyright-internal/src/localization/package.nls.en-us.json +++ b/packages/pyright-internal/src/localization/package.nls.en-us.json @@ -19,14 +19,6 @@ "argPositionalExpectedOne": "Expected 1 positional argument", "argTypePartiallyUnknown": "Argument type is partially unknown", "argTypeUnknown": "Argument type is unknown", - "arrowCallableIllegal": "Callable syntax requires Python 3.11 or newer", - "arrowCallableNeedsParen": "Callable expression requires parentheses when used in union or with other operators", - "arrowCallableNotParamSpec": "Expected ParamSpec after \"**\"", - "arrowCallableNotVariadicTypeVar": "Expected TypeVarTuple after \"*\"", - "arrowCallableParamSpec": "Expected \"**\" before ParamSpec", - "arrowCallableParamSpecNotLast": "ParamSpec must be the last parameter", - "arrowCallableVariadicTypeVarUnpacked": "TypeVarTuple is already unpacked; \"*\" is redundant", - "arrowCallableVariadicTypeVar": "Expected \"*\" before TypeVarTuple", "assertAlwaysTrue": "Assert expression always evaluates to true", "assignmentExprContext": "Assignment expression must be within module, function or lambda", "assignmentExprComprehension": "Assignment expression target \"{name}\" cannot use same name as comprehension for target", diff --git a/packages/pyright-internal/src/parser/parseNodes.ts b/packages/pyright-internal/src/parser/parseNodes.ts index 2d849bc1e..0545d44dd 100644 --- a/packages/pyright-internal/src/parser/parseNodes.ts +++ b/packages/pyright-internal/src/parser/parseNodes.ts @@ -104,7 +104,6 @@ export const enum ParseNodeType { PatternMappingExpandEntry, PatternValue, PatternClassArgument, - ArrowCallable, } export const enum ErrorExpressionCategory { @@ -687,8 +686,7 @@ export type ExpressionNode = | ListNode | SetNode | DecoratorNode - | FunctionAnnotationNode - | ArrowCallableNode; + | FunctionAnnotationNode; export function isExpressionNode(node: ParseNode): node is ExpressionNode { switch (node.nodeType) { @@ -720,7 +718,6 @@ export function isExpressionNode(node: ParseNode): node is ExpressionNode { case ParseNodeType.DictionaryExpandEntry: case ParseNodeType.List: case ParseNodeType.Set: - case ParseNodeType.ArrowCallable: return true; default: @@ -2247,52 +2244,6 @@ export namespace PatternValueNode { } } -export interface ArrowCallableParameter { - category: ParameterCategory; - typeAnnotation: ExpressionNode; - starToken?: Token; -} - -export interface ArrowCallableNode extends ParseNodeBase { - readonly nodeType: ParseNodeType.ArrowCallable; - isAsync?: boolean; - parameters: ArrowCallableParameter[]; - returnTypeAnnotation: ExpressionNode; -} - -export namespace ArrowCallableNode { - export function create( - openParenToken: Token, - parameters: ArrowCallableParameter[], - returnTypeAnnotation: ExpressionNode, - asyncToken?: Token - ) { - const node: ArrowCallableNode = { - start: openParenToken.start, - length: openParenToken.length, - nodeType: ParseNodeType.ArrowCallable, - id: _nextNodeId++, - parameters, - returnTypeAnnotation, - }; - - if (asyncToken) { - node.isAsync = true; - extendRange(node, asyncToken); - } - - extendRange(node, returnTypeAnnotation); - - parameters.forEach((expr) => { - expr.typeAnnotation.parent = node; - }); - - returnTypeAnnotation.parent = node; - - return node; - } -} - export type PatternAtomNode = | PatternSequenceNode | PatternLiteralNode @@ -2306,7 +2257,6 @@ export type PatternAtomNode = export type ParseNode = | ErrorNode | ArgumentNode - | ArrowCallableNode | AssertNode | AssignmentExpressionNode | AssignmentNode diff --git a/packages/pyright-internal/src/parser/parser.ts b/packages/pyright-internal/src/parser/parser.ts index 81c7a8ed7..72c024b54 100644 --- a/packages/pyright-internal/src/parser/parser.ts +++ b/packages/pyright-internal/src/parser/parser.ts @@ -25,8 +25,6 @@ import { Localizer } from '../localization/localize'; import { ArgumentCategory, ArgumentNode, - ArrowCallableNode, - ArrowCallableParameter, AssertNode, AssignmentExpressionNode, AssignmentNode, @@ -2846,14 +2844,6 @@ export class Parser { // or_test: and_test ('or' and_test)* private _parseOrTest(): ExpressionNode { - // Is the next expression possibly an arrow callable? - if (this._peekKeywordType() === KeywordType.Async || this._peekTokenType() === TokenType.OpenParenthesis) { - const possibleArrowCall = this._parseArrowCall(); - if (possibleArrowCall) { - return possibleArrowCall; - } - } - let leftExpr = this._parseAndTest(); if (leftExpr.nodeType === ParseNodeType.Error) { return leftExpr; @@ -3545,12 +3535,6 @@ export class Parser { } if (nextToken.type === TokenType.OpenParenthesis) { - const possibleArrowCall = this._parseArrowCall(); - if (possibleArrowCall) { - this._addError(Localizer.Diagnostic.arrowCallableNeedsParen(), possibleArrowCall); - return possibleArrowCall; - } - const possibleTupleNode = this._parseTupleAtom(); if ( possibleTupleNode.nodeType === ParseNodeType.Tuple && @@ -3610,14 +3594,6 @@ export class Parser { return ConstantNode.create(this._getNextToken() as KeywordToken); } - if (keywordToken.keywordType === KeywordType.Async) { - const possibleArrowCall = this._parseArrowCall(); - if (possibleArrowCall) { - this._addError(Localizer.Diagnostic.arrowCallableNeedsParen(), possibleArrowCall); - return possibleArrowCall; - } - } - // Make an identifier out of the keyword. const keywordAsIdentifier = this._getTokenIfIdentifier(); if (keywordAsIdentifier) { @@ -3685,114 +3661,6 @@ export class Parser { return this._parseLambdaExpression(allowConditional); } - // Attempts to parse an arrow call. If it is not a valid arrow call, - // it returns undefined without emitting any diagnostics. If it is - // an arrow call (as evidenced by a "->" token after the close paren), - // it returns an ArrowCallableNode. This method should be called when - // the next token is either an open paren or an "async" keyword. - // arrow_call: 'async'? '(' arrow_parameters ')' '->' test - private _parseArrowCall(): ArrowCallableNode | undefined { - let smellsLikeArrowCall = false; - - // Do a lookahead operation to see if this smells like an arrow - // call. If not, it's probably a normal parenthesis or tuple - // expression. - const curTokenIndex = this._tokenIndex; - this._consumeTokenIfKeyword(KeywordType.Async); - - if (this._consumeTokenIfType(TokenType.OpenParenthesis)) { - let parenLevel = 1; - smellsLikeArrowCall = true; - - while (parenLevel > 0) { - const nextToken = this._getNextToken(); - if (nextToken.type === TokenType.OpenParenthesis) { - parenLevel++; - } else if (nextToken.type === TokenType.CloseParenthesis) { - parenLevel--; - } else if (nextToken.type === TokenType.EndOfStream) { - smellsLikeArrowCall = false; - break; - } - } - - if (!this._consumeTokenIfType(TokenType.Arrow)) { - smellsLikeArrowCall = false; - } - } - - this._tokenIndex = curTokenIndex; - - if (!smellsLikeArrowCall) { - return undefined; - } - - let asyncToken: Token | undefined = this._peekToken(); - if (!this._consumeTokenIfKeyword(KeywordType.Async)) { - asyncToken = undefined; - } - - const openParenToken = this._peekToken(); - if (openParenToken.type !== TokenType.OpenParenthesis) { - return undefined; - } - this._getNextToken(); - - const arrowCallableParams = this._parseArrowCallableParameterList(); - - // Consume the close paren and arrow tokens. - this._getNextToken(); - this._getNextToken(); - - const returnTypeAnnotation = this._parseTypeAnnotation(); - - return ArrowCallableNode.create(openParenToken, arrowCallableParams, returnTypeAnnotation, asyncToken); - } - - private _parseArrowCallableParameterList(): ArrowCallableParameter[] { - const paramList: ArrowCallableParameter[] = []; - - while (true) { - if (this._peekTokenType() === TokenType.CloseParenthesis) { - break; - } - - const param = this._parseArrowCallableParameter(); - if (!param) { - this._consumeTokensUntilType([TokenType.CloseParenthesis]); - break; - } - - paramList.push(param); - - const foundComma = this._consumeTokenIfType(TokenType.Comma); - - if (!foundComma) { - break; - } - } - - return paramList; - } - - private _parseArrowCallableParameter(): ArrowCallableParameter { - const nextToken = this._peekToken(); - let category = ParameterCategory.Simple; - let starToken: Token | undefined; - - if (this._consumeTokenIfOperator(OperatorType.Multiply)) { - category = ParameterCategory.VarArgList; - starToken = nextToken; - } else if (this._consumeTokenIfOperator(OperatorType.Power)) { - category = ParameterCategory.VarArgDictionary; - starToken = nextToken; - } - - const typeAnnotation = this._parseTypeAnnotation(/* allowUnpack */ true); - - return { category, typeAnnotation, starToken }; - } - // ('(' [yield_expr | testlist_comp] ')' // testlist_comp: (test | star_expr) (comp_for | (',' (test | star_expr))* [',']) private _parseTupleAtom(): ExpressionNode { diff --git a/packages/pyright-internal/src/tests/samples/arrowCallable1.py b/packages/pyright-internal/src/tests/samples/arrowCallable1.py deleted file mode 100644 index 626f65e80..000000000 --- a/packages/pyright-internal/src/tests/samples/arrowCallable1.py +++ /dev/null @@ -1,128 +0,0 @@ -# This sample tests the callable syntax described in PEP 677. - -from typing import Callable, Concatenate, ParamSpec, TypeVar -from typing_extensions import TypeVarTuple, Unpack - -P = ParamSpec("P") -T = TypeVar("T") -Ts = TypeVarTuple("Ts") - -def func0( - a: (int, str) -> float, - b: (int | str) -> (int | str), - c: (...) -> (complex, str) -> int | None -) -> (int, str) -> None: - ... -reveal_type(func0, expected_text='(a: (int, str) -> float, b: (int | str) -> (int | str), c: (...) -> ((complex, str) -> int | None)) -> ((int, str) -> None)') - -def func1() -> async (int, str) -> bool: - ... -reveal_type(func1, expected_text='() -> ((int, str) -> Awaitable[bool])') - -def func2() -> ((int, str) -> bool): - ... -reveal_type(func2, expected_text='() -> ((int, str) -> bool)') - -def func3() -> (int) -> (str) -> bool: - ... -reveal_type(func3, expected_text='() -> ((int) -> ((str) -> bool))') - -def func4() -> ((int) -> ((str) -> bool)): - ... -reveal_type(func4, expectedText='() -> ((int) -> ((str) -> bool))') - -def func5() -> (T) -> T: - ... -reveal_type(func5, expected_text='() -> ((T@func5) -> T@func5)') - - -A1 = (int) -> str | bool -reveal_type(A1, expected_text='(int) -> (str | bool)') - -A2 = (int) -> (str | bool) -reveal_type(A2, expected_text='(int) -> (str | bool)') - - -B1 = (int) -> (str) -> bool -reveal_type(B1, expected_text='(int) -> ((str) -> bool)') - -B2 = (int) -> ((str) -> bool) -reveal_type(B2, expected_text='(int) -> ((str) -> bool)') - - -# This should generate an error because parens are needed. -C1 = () -> int | () -> bool - -C2 = () -> int | (() -> bool) -reveal_type(C2, expected_text='() -> (int | (() -> bool))') - -C3 = (() -> int) | (() -> bool) -reveal_type(C3, expected_text='(() -> int) | (() -> bool)') - -D0 = (int,) -> bool -reveal_type(D0, expected_text='(int) -> bool') - -D1 = (int) -> bool -reveal_type(D1, expected_text='(int) -> bool') - -D2 = (int, T, **P,) -> bool -reveal_type(D2, expected_text='(int, T@D2, **P@D2) -> bool') - -D3 = (int, T, **P) -> bool -reveal_type(D3, expected_text='(int, T@D3, **P@D3) -> bool') - -D4 = (...,) -> bool -reveal_type(D4, expected_text='(...) -> bool') - -D5 = (...) -> bool -reveal_type(D5, expected_text='(...) -> bool') - -E1 = Callable[Concatenate[int, T, P], bool] -reveal_type(E1, expected_text='(int, T@E1, **P@E1) -> bool') - -E2 = (int, T, **P) -> bool -reveal_type(E2, expected_text='(int, T@E2, **P@E2) -> bool') - -F1 = (...) -> int -reveal_type(F1, expected_text='(...) -> int') - -# This should generate an error because * can't be used with ellipsis. -F2 = (*...) -> int - -# This should generate an error because ** can't be used with ellipsis. -F3 = (**...) -> int - -# This should generate an error because ellipsis must be the only parameter. -F4 = (..., str) -> int - -# This should generate an error because ellipsis must be the only parameter. -F5 = (int, str, ...) -> int - - -G1 = (int, *Ts, str) -> int -reveal_type(G1, expected_text='(int, *Ts@G1, str) -> int') - -G2 = (int, Unpack[Ts], str) -> int -reveal_type(G2, expected_text='(int, *Ts@G2, str) -> int') - -# This should generate an error because Ts is doubly unpacked. -G3 = (int, *Unpack[Ts], str) -> int - -# This should generate an error because int isn't a TypeVarTuple -G4 = (*int, str) -> int - -# This should generate an error because P isn't a TypeVarTuple -G5 = (*P, str) -> int - - -H1 = (int, **P) -> int -reveal_type(H1, expected_text='(int, **P@H1) -> int') - -# This should generate an error because P isn't preceded by **. -H2 = (int, P) -> int - -# This should generate an error because int isn't a ParamSpec. -H3 = (int, **int) -> int - -# This should generate an error because P isn't the last parameter. -H4 = (**P, int) -> int diff --git a/packages/pyright-internal/src/tests/samples/arrowCallable2.py b/packages/pyright-internal/src/tests/samples/arrowCallable2.py deleted file mode 100644 index f55f3be27..000000000 --- a/packages/pyright-internal/src/tests/samples/arrowCallable2.py +++ /dev/null @@ -1,26 +0,0 @@ -# This sample tests the callable syntax described in PEP 677. Specifically, -# it tests that an error is generated when not using Python 3.11. - -from typing import TypeAlias, TypeVar - - -# This should generate an error when using versions of Python prior to 3.11. -A1 = (int) -> int - -A2: TypeAlias = "(int) -> int" - -def func1(a: "(int) -> (() -> None)") -> "(...) -> int": - ... - -# This should generate an error when using versions of Python prior to 3.11. -def func2(a: (int) -> int) -> int: - ... - -# This should generate an error when using versions of Python prior to 3.11. -# Although the annotation is enclosed in parentheses, the interpreter -# still attempts to parse it. -T1 = TypeVar("T1", bound="(int) -> int") - -# This should generate an error when using versions of Python prior to 3.11. -T2 = TypeVar("T2", int, "(int) -> int") - diff --git a/packages/pyright-internal/src/tests/samples/arrowCallable3.py b/packages/pyright-internal/src/tests/samples/arrowCallable3.py deleted file mode 100644 index 9ef9ebb50..000000000 --- a/packages/pyright-internal/src/tests/samples/arrowCallable3.py +++ /dev/null @@ -1,83 +0,0 @@ -# This sample tests deeply-nested parentheses, which can cause problems -# in the parser for arrow callables. - -from typing import Any - - -def func(*args: Any): - ... - - -def func2(*args: Any) -> str: - ... - - -def func3(a: str | None, b: str | None, x: str | None, y: str | None, z1: int, z2: int): - func( - ( - ( - ( - ( - ( - ( - ( - ( - ( - ( - ( - ( - ( - ( - ( - "text " - + func2( - ( - "null" - if a is None - else a - ) - + ( - "null" - if b is None - else b - ) - ) - ) - + " " - ) - + ( - "null" - if x is None - else x - ) - ) - + " " - ) - + ("null" if y is None else y) - ) - + " " - ) - + func2( - (("null" if ((y is None)) else str(y))) - ) - ) - + " " - ) - + ("null" if y is None else y) - ) - + " => " - ) - + str(z1) - ) - + " " - ) - + str(z2) - ) - + " " - ) - + str(type(z1)) - ) - ) - - -x: (((((((((((((() -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) diff --git a/packages/pyright-internal/src/tests/samples/await1.py b/packages/pyright-internal/src/tests/samples/await1.py index 5822dcb7c..0f739fa40 100644 --- a/packages/pyright-internal/src/tests/samples/await1.py +++ b/packages/pyright-internal/src/tests/samples/await1.py @@ -1,7 +1,7 @@ # This sample validates that the await keyword participates in # bidirectional type inference. -from typing import TypeVar, Generic +from typing import Callable, TypeVar, Generic T = TypeVar("T") AnyMsg = TypeVar("AnyMsg", bound="Msg") @@ -15,7 +15,7 @@ class Request: id: int -async def func1(check: "(AnyMsg) -> bool") -> AnyMsg: +async def func1(check: "Callable[[AnyMsg], bool]") -> AnyMsg: ... diff --git a/packages/pyright-internal/src/tests/samples/lambda5.py b/packages/pyright-internal/src/tests/samples/lambda5.py index a083308ef..478fa761e 100644 --- a/packages/pyright-internal/src/tests/samples/lambda5.py +++ b/packages/pyright-internal/src/tests/samples/lambda5.py @@ -2,7 +2,7 @@ # bidirectional type inference and one or more of the parameters # corresponds to a generic type. -from typing import TypeVar, Generic, Any +from typing import Callable, TypeVar, Generic, Any T = TypeVar("T") MsgT = TypeVar("MsgT", bound="Msg[Any]") @@ -16,7 +16,7 @@ class Request: ... -def check(func: "(MsgT, int) -> object") -> MsgT: +def check(func: "Callable[[MsgT, int], object]") -> MsgT: ... diff --git a/packages/pyright-internal/src/tests/typeEvaluator1.test.ts b/packages/pyright-internal/src/tests/typeEvaluator1.test.ts index a0051f2c2..2233d4808 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator1.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator1.test.ts @@ -1197,34 +1197,6 @@ test('Descriptor1', () => { TestUtils.validateResults(analysisResults, 6); }); -test('ArrowCallable1', () => { - const configOptions = new ConfigOptions('.'); - - configOptions.defaultPythonVersion = PythonVersion.V3_11; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['arrowCallable1.py'], configOptions); - TestUtils.validateResults(analysisResults, 11); -}); - -test('ArrowCallable2', () => { - const configOptions = new ConfigOptions('.'); - - configOptions.defaultPythonVersion = PythonVersion.V3_10; - const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['arrowCallable2.py'], configOptions); - TestUtils.validateResults(analysisResults1, 4); - - configOptions.defaultPythonVersion = PythonVersion.V3_11; - const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['arrowCallable2.py'], configOptions); - TestUtils.validateResults(analysisResults2, 0); -}); - -test('ArrowCallable3', () => { - const configOptions = new ConfigOptions('.'); - - configOptions.defaultPythonVersion = PythonVersion.V3_11; - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['arrowCallable3.py'], configOptions); - TestUtils.validateResults(analysisResults, 0); -}); - test('Partial1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['partial1.py']); diff --git a/packages/vscode-pyright/README.md b/packages/vscode-pyright/README.md index 2c7d8426e..ecbcb8002 100644 --- a/packages/vscode-pyright/README.md +++ b/packages/vscode-pyright/README.md @@ -30,7 +30,8 @@ Pyright supports [configuration files](/docs/configuration.md) that provide gran * [PEP 647](https://www.python.org/dev/peps/pep-0647/) user-defined type guards * [PEP 655](https://www.python.org/dev/peps/pep-0655/) required typed dictionary items * [PEP 673](https://www.python.org/dev/peps/pep-0673/) Self type -* [PEP 677](https://www.python.org/dev/peps/pep-0677/) callable type syntax +* [PEP 675](https://www.python.org/dev/peps/pep-0675/) arbitrary literal strings +* [PEP 681](https://www.python.org/dev/peps/pep-0681/) dataclass transform * Type inference for function return values, instance variables, class variables, and globals * Type guards that understand conditional code flow constructs like if/else statements