From 73d2c0ad25305a5b3e4c5dc731cb33ea50e7ed6e Mon Sep 17 00:00:00 2001 From: Brent Westbrook Date: Fri, 4 Apr 2025 09:28:54 -0400 Subject: [PATCH 1/2] [syntax-errors] Allow `yield` in base classes and annotations Summary -- This PR fixes the issue pointed out by @JelleZijlstra in https://github.com/astral-sh/ruff/pull/17101#issuecomment-2777480204. Namely, I conflated two very different errors from CPython: ```pycon >>> def m[T](x: (yield from 1)): ... File "", line 1 def m[T](x: (yield from 1)): ... ^^^^^^^^^^^^ SyntaxError: yield expression cannot be used within the definition of a generic >>> def m(x: (yield from 1)): ... File "", line 1 def m(x: (yield from 1)): ... ^^^^^^^^^^^^ SyntaxError: 'yield from' outside function >>> def outer(): ... def m(x: (yield from 1)): ... ... >>> ``` I thought the second error was the same as the first, but `yield` (and `yield from`) is actually valid in this position when inside a function scope. The same is true for base classes, as pointed out in the original comment. We don't currently raise an error for `yield` outside of a function, but that should be handled separately. On the upside, this had the benefit of removing the `InvalidExpressionPosition::BaseClass` variant, the `InvalidExpressionPosition::TypeAnnotation` variant, and the `allow_named_expr` field from the visitor because they were all no longer used. Test Plan -- Updated inline tests. --- .../inline/err/invalid_annotation_class.py | 2 - .../inline/err/invalid_annotation_function.py | 4 - .../inline/ok/valid_annotation_class.py | 3 + .../inline/ok/valid_annotation_function.py | 5 + .../ruff_python_parser/src/semantic_errors.rs | 68 +- ...x@function_def_invalid_return_expr.py.snap | 10 - ...id_syntax@invalid_annotation_class.py.snap | 224 ++----- ...syntax@invalid_annotation_function.py.snap | 606 +++++------------- ...ntax@param_with_invalid_annotation.py.snap | 10 - ...param_with_invalid_star_annotation.py.snap | 11 - ...alid_syntax@valid_annotation_class.py.snap | 115 +++- ...d_syntax@valid_annotation_function.py.snap | 243 ++++++- 12 files changed, 611 insertions(+), 690 deletions(-) diff --git a/crates/ruff_python_parser/resources/inline/err/invalid_annotation_class.py b/crates/ruff_python_parser/resources/inline/err/invalid_annotation_class.py index 84be61ecc0972..d5de922472d7f 100644 --- a/crates/ruff_python_parser/resources/inline/err/invalid_annotation_class.py +++ b/crates/ruff_python_parser/resources/inline/err/invalid_annotation_class.py @@ -1,6 +1,4 @@ class F[T](y := list): ... -class G((yield 1)): ... -class H((yield from 1)): ... class I[T]((yield 1)): ... class J[T]((yield from 1)): ... class K[T: (yield 1)]: ... # yield in TypeVar diff --git a/crates/ruff_python_parser/resources/inline/err/invalid_annotation_function.py b/crates/ruff_python_parser/resources/inline/err/invalid_annotation_function.py index 9410d84b3572a..c16c9c0ff9906 100644 --- a/crates/ruff_python_parser/resources/inline/err/invalid_annotation_function.py +++ b/crates/ruff_python_parser/resources/inline/err/invalid_annotation_function.py @@ -1,13 +1,9 @@ def f[T]() -> (y := 3): ... def g[T](arg: (x := 1)): ... def h[T](x: (yield 1)): ... -def i(x: (yield 1)): ... def j[T]() -> (yield 1): ... -def k() -> (yield 1): ... def l[T](x: (yield from 1)): ... -def m(x: (yield from 1)): ... def n[T]() -> (yield from 1): ... -def o() -> (yield from 1): ... def p[T: (yield 1)](): ... # yield in TypeVar bound def q[T = (yield 1)](): ... # yield in TypeVar default def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default diff --git a/crates/ruff_python_parser/resources/inline/ok/valid_annotation_class.py b/crates/ruff_python_parser/resources/inline/ok/valid_annotation_class.py index 35bd80e577504..da0d319440908 100644 --- a/crates/ruff_python_parser/resources/inline/ok/valid_annotation_class.py +++ b/crates/ruff_python_parser/resources/inline/ok/valid_annotation_class.py @@ -1 +1,4 @@ class F(y := list): ... +def f(): + class G((yield 1)): ... + class H((yield from 1)): ... diff --git a/crates/ruff_python_parser/resources/inline/ok/valid_annotation_function.py b/crates/ruff_python_parser/resources/inline/ok/valid_annotation_function.py index 25add3d168954..3f370741ab269 100644 --- a/crates/ruff_python_parser/resources/inline/ok/valid_annotation_function.py +++ b/crates/ruff_python_parser/resources/inline/ok/valid_annotation_function.py @@ -1,2 +1,7 @@ def f() -> (y := 3): ... def g(arg: (x := 1)): ... +def outer(): + def i(x: (yield 1)): ... + def k() -> (yield 1): ... + def m(x: (yield from 1)): ... + def o() -> (yield from 1): ... diff --git a/crates/ruff_python_parser/src/semantic_errors.rs b/crates/ruff_python_parser/src/semantic_errors.rs index 1ed9458280bc6..37bf341ab94ba 100644 --- a/crates/ruff_python_parser/src/semantic_errors.rs +++ b/crates/ruff_python_parser/src/semantic_errors.rs @@ -120,7 +120,7 @@ impl SemanticSyntaxChecker { fn check_annotation(stmt: &ast::Stmt, ctx: &Ctx) { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { - type_params, + type_params: Some(type_params), parameters, returns, .. @@ -128,18 +128,19 @@ impl SemanticSyntaxChecker { // test_ok valid_annotation_function // def f() -> (y := 3): ... // def g(arg: (x := 1)): ... + // def outer(): + // def i(x: (yield 1)): ... + // def k() -> (yield 1): ... + // def m(x: (yield from 1)): ... + // def o() -> (yield from 1): ... // test_err invalid_annotation_function // def f[T]() -> (y := 3): ... // def g[T](arg: (x := 1)): ... // def h[T](x: (yield 1)): ... - // def i(x: (yield 1)): ... // def j[T]() -> (yield 1): ... - // def k() -> (yield 1): ... // def l[T](x: (yield from 1)): ... - // def m(x: (yield from 1)): ... // def n[T]() -> (yield from 1): ... - // def o() -> (yield from 1): ... // def p[T: (yield 1)](): ... # yield in TypeVar bound // def q[T = (yield 1)](): ... # yield in TypeVar default // def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default @@ -148,20 +149,11 @@ impl SemanticSyntaxChecker { // def u[T = (x := 1)](): ... # named expr in TypeVar default // def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default // def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default - let is_generic = type_params.is_some(); let mut visitor = InvalidExpressionVisitor { - allow_named_expr: !is_generic, - position: InvalidExpressionPosition::TypeAnnotation, + position: InvalidExpressionPosition::GenericDefinition, ctx, }; - if let Some(type_params) = type_params { - visitor.visit_type_params(type_params); - } - if is_generic { - visitor.position = InvalidExpressionPosition::GenericDefinition; - } else { - visitor.position = InvalidExpressionPosition::TypeAnnotation; - } + visitor.visit_type_params(type_params); for param in parameters .iter() .filter_map(ast::AnyParameterRef::annotation) @@ -173,36 +165,29 @@ impl SemanticSyntaxChecker { } } Stmt::ClassDef(ast::StmtClassDef { - type_params, + type_params: Some(type_params), arguments, .. }) => { // test_ok valid_annotation_class // class F(y := list): ... + // def f(): + // class G((yield 1)): ... + // class H((yield from 1)): ... // test_err invalid_annotation_class // class F[T](y := list): ... - // class G((yield 1)): ... - // class H((yield from 1)): ... // class I[T]((yield 1)): ... // class J[T]((yield from 1)): ... // class K[T: (yield 1)]: ... # yield in TypeVar // class L[T: (x := 1)]: ... # named expr in TypeVar - let is_generic = type_params.is_some(); let mut visitor = InvalidExpressionVisitor { - allow_named_expr: !is_generic, - position: InvalidExpressionPosition::TypeAnnotation, + position: InvalidExpressionPosition::TypeVarBound, ctx, }; - if let Some(type_params) = type_params { - visitor.visit_type_params(type_params); - } - if is_generic { - visitor.position = InvalidExpressionPosition::GenericDefinition; - } else { - visitor.position = InvalidExpressionPosition::BaseClass; - } + visitor.visit_type_params(type_params); if let Some(arguments) = arguments { + visitor.position = InvalidExpressionPosition::GenericDefinition; visitor.visit_arguments(arguments); } } @@ -217,7 +202,6 @@ impl SemanticSyntaxChecker { // type Y = (yield 1) # yield in value // type Y = (x := 1) # named expr in value let mut visitor = InvalidExpressionVisitor { - allow_named_expr: false, position: InvalidExpressionPosition::TypeAlias, ctx, }; @@ -625,12 +609,6 @@ impl Display for SemanticSyntaxError { write!(f, "cannot delete `__debug__` on Python {python_version} (syntax was removed in 3.9)") } }, - SemanticSyntaxErrorKind::InvalidExpression( - kind, - InvalidExpressionPosition::BaseClass, - ) => { - write!(f, "{kind} cannot be used as a base class") - } SemanticSyntaxErrorKind::InvalidExpression(kind, position) => { write!(f, "{kind} cannot be used within a {position}") } @@ -857,8 +835,6 @@ pub enum InvalidExpressionPosition { TypeVarDefault, TypeVarTupleDefault, ParamSpecDefault, - TypeAnnotation, - BaseClass, GenericDefinition, TypeAlias, } @@ -870,9 +846,7 @@ impl Display for InvalidExpressionPosition { InvalidExpressionPosition::TypeVarDefault => "TypeVar default", InvalidExpressionPosition::TypeVarTupleDefault => "TypeVarTuple default", InvalidExpressionPosition::ParamSpecDefault => "ParamSpec default", - InvalidExpressionPosition::TypeAnnotation => "type annotation", InvalidExpressionPosition::GenericDefinition => "generic definition", - InvalidExpressionPosition::BaseClass => "base class", InvalidExpressionPosition::TypeAlias => "type alias", }) } @@ -1086,16 +1060,6 @@ impl<'a, Ctx: SemanticSyntaxContext> MatchPatternVisitor<'a, Ctx> { } struct InvalidExpressionVisitor<'a, Ctx> { - /// Allow named expressions (`x := ...`) to appear in annotations. - /// - /// These are allowed in non-generic functions, for example: - /// - /// ```python - /// def foo(arg: (x := int)): ... # ok - /// def foo[T](arg: (x := int)): ... # syntax error - /// ``` - allow_named_expr: bool, - /// Context used for emitting errors. ctx: &'a Ctx, @@ -1108,7 +1072,7 @@ where { fn visit_expr(&mut self, expr: &Expr) { match expr { - Expr::Named(ast::ExprNamed { range, .. }) if !self.allow_named_expr => { + Expr::Named(ast::ExprNamed { range, .. }) => { SemanticSyntaxChecker::add_error( self.ctx, SemanticSyntaxErrorKind::InvalidExpression( diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@function_def_invalid_return_expr.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@function_def_invalid_return_expr.py.snap index f1968dedf92e5..0d1731ead85ae 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@function_def_invalid_return_expr.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@function_def_invalid_return_expr.py.snap @@ -179,13 +179,3 @@ Module( 3 | def foo() -> yield x: ... | ^^^^^^^ Syntax Error: Yield expression cannot be used here | - - -## Semantic Syntax Errors - - | -1 | def foo() -> *int: ... -2 | def foo() -> (*int): ... -3 | def foo() -> yield x: ... - | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation - | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_class.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_class.py.snap index 11cddd2d71994..a9d4fdad90edc 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_class.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_class.py.snap @@ -7,7 +7,7 @@ input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_cl ``` Module( ModModule { - range: 0..246, + range: 0..193, body: [ ClassDef( StmtClassDef { @@ -78,112 +78,22 @@ Module( ), ClassDef( StmtClassDef { - range: 27..50, - decorator_list: [], - name: Identifier { - id: Name("G"), - range: 33..34, - }, - type_params: None, - arguments: Some( - Arguments { - range: 34..45, - args: [ - Yield( - ExprYield { - range: 36..43, - value: Some( - NumberLiteral( - ExprNumberLiteral { - range: 42..43, - value: Int( - 1, - ), - }, - ), - ), - }, - ), - ], - keywords: [], - }, - ), - body: [ - Expr( - StmtExpr { - range: 47..50, - value: EllipsisLiteral( - ExprEllipsisLiteral { - range: 47..50, - }, - ), - }, - ), - ], - }, - ), - ClassDef( - StmtClassDef { - range: 51..79, - decorator_list: [], - name: Identifier { - id: Name("H"), - range: 57..58, - }, - type_params: None, - arguments: Some( - Arguments { - range: 58..74, - args: [ - YieldFrom( - ExprYieldFrom { - range: 60..72, - value: NumberLiteral( - ExprNumberLiteral { - range: 71..72, - value: Int( - 1, - ), - }, - ), - }, - ), - ], - keywords: [], - }, - ), - body: [ - Expr( - StmtExpr { - range: 76..79, - value: EllipsisLiteral( - ExprEllipsisLiteral { - range: 76..79, - }, - ), - }, - ), - ], - }, - ), - ClassDef( - StmtClassDef { - range: 80..106, + range: 27..53, decorator_list: [], name: Identifier { id: Name("I"), - range: 86..87, + range: 33..34, }, type_params: Some( TypeParams { - range: 87..90, + range: 34..37, type_params: [ TypeVar( TypeParamTypeVar { - range: 88..89, + range: 35..36, name: Identifier { id: Name("T"), - range: 88..89, + range: 35..36, }, bound: None, default: None, @@ -194,15 +104,15 @@ Module( ), arguments: Some( Arguments { - range: 90..101, + range: 37..48, args: [ Yield( ExprYield { - range: 92..99, + range: 39..46, value: Some( NumberLiteral( ExprNumberLiteral { - range: 98..99, + range: 45..46, value: Int( 1, ), @@ -218,10 +128,10 @@ Module( body: [ Expr( StmtExpr { - range: 103..106, + range: 50..53, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 103..106, + range: 50..53, }, ), }, @@ -231,22 +141,22 @@ Module( ), ClassDef( StmtClassDef { - range: 107..138, + range: 54..85, decorator_list: [], name: Identifier { id: Name("J"), - range: 113..114, + range: 60..61, }, type_params: Some( TypeParams { - range: 114..117, + range: 61..64, type_params: [ TypeVar( TypeParamTypeVar { - range: 115..116, + range: 62..63, name: Identifier { id: Name("T"), - range: 115..116, + range: 62..63, }, bound: None, default: None, @@ -257,14 +167,14 @@ Module( ), arguments: Some( Arguments { - range: 117..133, + range: 64..80, args: [ YieldFrom( ExprYieldFrom { - range: 119..131, + range: 66..78, value: NumberLiteral( ExprNumberLiteral { - range: 130..131, + range: 77..78, value: Int( 1, ), @@ -279,10 +189,10 @@ Module( body: [ Expr( StmtExpr { - range: 135..138, + range: 82..85, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 135..138, + range: 82..85, }, ), }, @@ -292,31 +202,31 @@ Module( ), ClassDef( StmtClassDef { - range: 139..165, + range: 86..112, decorator_list: [], name: Identifier { id: Name("K"), - range: 145..146, + range: 92..93, }, type_params: Some( TypeParams { - range: 146..160, + range: 93..107, type_params: [ TypeVar( TypeParamTypeVar { - range: 147..159, + range: 94..106, name: Identifier { id: Name("T"), - range: 147..148, + range: 94..95, }, bound: Some( Yield( ExprYield { - range: 151..158, + range: 98..105, value: Some( NumberLiteral( ExprNumberLiteral { - range: 157..158, + range: 104..105, value: Int( 1, ), @@ -336,10 +246,10 @@ Module( body: [ Expr( StmtExpr { - range: 162..165, + range: 109..112, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 162..165, + range: 109..112, }, ), }, @@ -349,37 +259,37 @@ Module( ), ClassDef( StmtClassDef { - range: 190..215, + range: 137..162, decorator_list: [], name: Identifier { id: Name("L"), - range: 196..197, + range: 143..144, }, type_params: Some( TypeParams { - range: 197..210, + range: 144..157, type_params: [ TypeVar( TypeParamTypeVar { - range: 198..209, + range: 145..156, name: Identifier { id: Name("T"), - range: 198..199, + range: 145..146, }, bound: Some( Named( ExprNamed { - range: 202..208, + range: 149..155, target: Name( ExprName { - range: 202..203, + range: 149..150, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { - range: 207..208, + range: 154..155, value: Int( 1, ), @@ -398,10 +308,10 @@ Module( body: [ Expr( StmtExpr { - range: 212..215, + range: 159..162, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 212..215, + range: 159..162, }, ), }, @@ -418,62 +328,42 @@ Module( | 1 | class F[T](y := list): ... | ^^^^^^^^^ Syntax Error: named expression cannot be used within a generic definition -2 | class G((yield 1)): ... -3 | class H((yield from 1)): ... +2 | class I[T]((yield 1)): ... +3 | class J[T]((yield from 1)): ... | | 1 | class F[T](y := list): ... -2 | class G((yield 1)): ... - | ^^^^^^^ Syntax Error: yield expression cannot be used as a base class -3 | class H((yield from 1)): ... -4 | class I[T]((yield 1)): ... - | - - - | -1 | class F[T](y := list): ... -2 | class G((yield 1)): ... -3 | class H((yield from 1)): ... - | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used as a base class -4 | class I[T]((yield 1)): ... -5 | class J[T]((yield from 1)): ... - | - - - | -2 | class G((yield 1)): ... -3 | class H((yield from 1)): ... -4 | class I[T]((yield 1)): ... +2 | class I[T]((yield 1)): ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition -5 | class J[T]((yield from 1)): ... -6 | class K[T: (yield 1)]: ... # yield in TypeVar +3 | class J[T]((yield from 1)): ... +4 | class K[T: (yield 1)]: ... # yield in TypeVar | | -3 | class H((yield from 1)): ... -4 | class I[T]((yield 1)): ... -5 | class J[T]((yield from 1)): ... +1 | class F[T](y := list): ... +2 | class I[T]((yield 1)): ... +3 | class J[T]((yield from 1)): ... | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition -6 | class K[T: (yield 1)]: ... # yield in TypeVar -7 | class L[T: (x := 1)]: ... # named expr in TypeVar +4 | class K[T: (yield 1)]: ... # yield in TypeVar +5 | class L[T: (x := 1)]: ... # named expr in TypeVar | | -4 | class I[T]((yield 1)): ... -5 | class J[T]((yield from 1)): ... -6 | class K[T: (yield 1)]: ... # yield in TypeVar +2 | class I[T]((yield 1)): ... +3 | class J[T]((yield from 1)): ... +4 | class K[T: (yield 1)]: ... # yield in TypeVar | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound -7 | class L[T: (x := 1)]: ... # named expr in TypeVar +5 | class L[T: (x := 1)]: ... # named expr in TypeVar | | -5 | class J[T]((yield from 1)): ... -6 | class K[T: (yield 1)]: ... # yield in TypeVar -7 | class L[T: (x := 1)]: ... # named expr in TypeVar +3 | class J[T]((yield from 1)): ... +4 | class K[T: (yield 1)]: ... # yield in TypeVar +5 | class L[T: (x := 1)]: ... # named expr in TypeVar | ^^^^^^ Syntax Error: named expression cannot be used within a TypeVar bound | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_function.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_function.py.snap index 67dae0e7c1fe8..24ce2db115f95 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_function.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_function.py.snap @@ -7,7 +7,7 @@ input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_fu ``` Module( ModModule { - range: 0..795, + range: 0..683, body: [ FunctionDef( StmtFunctionDef { @@ -245,85 +245,23 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 85..109, - is_async: false, - decorator_list: [], - name: Identifier { - id: Name("i"), - range: 89..90, - }, - type_params: None, - parameters: Parameters { - range: 90..104, - posonlyargs: [], - args: [ - ParameterWithDefault { - range: 91..103, - parameter: Parameter { - range: 91..103, - name: Identifier { - id: Name("x"), - range: 91..92, - }, - annotation: Some( - Yield( - ExprYield { - range: 95..102, - value: Some( - NumberLiteral( - ExprNumberLiteral { - range: 101..102, - value: Int( - 1, - ), - }, - ), - ), - }, - ), - ), - }, - default: None, - }, - ], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, - returns: None, - body: [ - Expr( - StmtExpr { - range: 106..109, - value: EllipsisLiteral( - ExprEllipsisLiteral { - range: 106..109, - }, - ), - }, - ), - ], - }, - ), - FunctionDef( - StmtFunctionDef { - range: 110..138, + range: 85..113, is_async: false, decorator_list: [], name: Identifier { id: Name("j"), - range: 114..115, + range: 89..90, }, type_params: Some( TypeParams { - range: 115..118, + range: 90..93, type_params: [ TypeVar( TypeParamTypeVar { - range: 116..117, + range: 91..92, name: Identifier { id: Name("T"), - range: 116..117, + range: 91..92, }, bound: None, default: None, @@ -333,56 +271,7 @@ Module( }, ), parameters: Parameters { - range: 118..120, - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, - returns: Some( - Yield( - ExprYield { - range: 125..132, - value: Some( - NumberLiteral( - ExprNumberLiteral { - range: 131..132, - value: Int( - 1, - ), - }, - ), - ), - }, - ), - ), - body: [ - Expr( - StmtExpr { - range: 135..138, - value: EllipsisLiteral( - ExprEllipsisLiteral { - range: 135..138, - }, - ), - }, - ), - ], - }, - ), - FunctionDef( - StmtFunctionDef { - range: 139..164, - is_async: false, - decorator_list: [], - name: Identifier { - id: Name("k"), - range: 143..144, - }, - type_params: None, - parameters: Parameters { - range: 144..146, + range: 93..95, posonlyargs: [], args: [], vararg: None, @@ -392,11 +281,11 @@ Module( returns: Some( Yield( ExprYield { - range: 151..158, + range: 100..107, value: Some( NumberLiteral( ExprNumberLiteral { - range: 157..158, + range: 106..107, value: Int( 1, ), @@ -409,10 +298,10 @@ Module( body: [ Expr( StmtExpr { - range: 161..164, + range: 110..113, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 161..164, + range: 110..113, }, ), }, @@ -422,23 +311,23 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 165..197, + range: 114..146, is_async: false, decorator_list: [], name: Identifier { id: Name("l"), - range: 169..170, + range: 118..119, }, type_params: Some( TypeParams { - range: 170..173, + range: 119..122, type_params: [ TypeVar( TypeParamTypeVar { - range: 171..172, + range: 120..121, name: Identifier { id: Name("T"), - range: 171..172, + range: 120..121, }, bound: None, default: None, @@ -448,84 +337,24 @@ Module( }, ), parameters: Parameters { - range: 173..192, - posonlyargs: [], - args: [ - ParameterWithDefault { - range: 174..191, - parameter: Parameter { - range: 174..191, - name: Identifier { - id: Name("x"), - range: 174..175, - }, - annotation: Some( - YieldFrom( - ExprYieldFrom { - range: 178..190, - value: NumberLiteral( - ExprNumberLiteral { - range: 189..190, - value: Int( - 1, - ), - }, - ), - }, - ), - ), - }, - default: None, - }, - ], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, - returns: None, - body: [ - Expr( - StmtExpr { - range: 194..197, - value: EllipsisLiteral( - ExprEllipsisLiteral { - range: 194..197, - }, - ), - }, - ), - ], - }, - ), - FunctionDef( - StmtFunctionDef { - range: 198..227, - is_async: false, - decorator_list: [], - name: Identifier { - id: Name("m"), - range: 202..203, - }, - type_params: None, - parameters: Parameters { - range: 203..222, + range: 122..141, posonlyargs: [], args: [ ParameterWithDefault { - range: 204..221, + range: 123..140, parameter: Parameter { - range: 204..221, + range: 123..140, name: Identifier { id: Name("x"), - range: 204..205, + range: 123..124, }, annotation: Some( YieldFrom( ExprYieldFrom { - range: 208..220, + range: 127..139, value: NumberLiteral( ExprNumberLiteral { - range: 219..220, + range: 138..139, value: Int( 1, ), @@ -546,10 +375,10 @@ Module( body: [ Expr( StmtExpr { - range: 224..227, + range: 143..146, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 224..227, + range: 143..146, }, ), }, @@ -559,23 +388,23 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 228..261, + range: 147..180, is_async: false, decorator_list: [], name: Identifier { id: Name("n"), - range: 232..233, + range: 151..152, }, type_params: Some( TypeParams { - range: 233..236, + range: 152..155, type_params: [ TypeVar( TypeParamTypeVar { - range: 234..235, + range: 153..154, name: Identifier { id: Name("T"), - range: 234..235, + range: 153..154, }, bound: None, default: None, @@ -585,54 +414,7 @@ Module( }, ), parameters: Parameters { - range: 236..238, - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, - returns: Some( - YieldFrom( - ExprYieldFrom { - range: 243..255, - value: NumberLiteral( - ExprNumberLiteral { - range: 254..255, - value: Int( - 1, - ), - }, - ), - }, - ), - ), - body: [ - Expr( - StmtExpr { - range: 258..261, - value: EllipsisLiteral( - ExprEllipsisLiteral { - range: 258..261, - }, - ), - }, - ), - ], - }, - ), - FunctionDef( - StmtFunctionDef { - range: 262..292, - is_async: false, - decorator_list: [], - name: Identifier { - id: Name("o"), - range: 266..267, - }, - type_params: None, - parameters: Parameters { - range: 267..269, + range: 155..157, posonlyargs: [], args: [], vararg: None, @@ -642,10 +424,10 @@ Module( returns: Some( YieldFrom( ExprYieldFrom { - range: 274..286, + range: 162..174, value: NumberLiteral( ExprNumberLiteral { - range: 285..286, + range: 173..174, value: Int( 1, ), @@ -657,10 +439,10 @@ Module( body: [ Expr( StmtExpr { - range: 289..292, + range: 177..180, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 289..292, + range: 177..180, }, ), }, @@ -670,32 +452,32 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 293..319, + range: 181..207, is_async: false, decorator_list: [], name: Identifier { id: Name("p"), - range: 297..298, + range: 185..186, }, type_params: Some( TypeParams { - range: 298..312, + range: 186..200, type_params: [ TypeVar( TypeParamTypeVar { - range: 299..311, + range: 187..199, name: Identifier { id: Name("T"), - range: 299..300, + range: 187..188, }, bound: Some( Yield( ExprYield { - range: 303..310, + range: 191..198, value: Some( NumberLiteral( ExprNumberLiteral { - range: 309..310, + range: 197..198, value: Int( 1, ), @@ -712,7 +494,7 @@ Module( }, ), parameters: Parameters { - range: 312..314, + range: 200..202, posonlyargs: [], args: [], vararg: None, @@ -723,10 +505,10 @@ Module( body: [ Expr( StmtExpr { - range: 316..319, + range: 204..207, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 316..319, + range: 204..207, }, ), }, @@ -736,33 +518,33 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 350..377, + range: 238..265, is_async: false, decorator_list: [], name: Identifier { id: Name("q"), - range: 354..355, + range: 242..243, }, type_params: Some( TypeParams { - range: 355..370, + range: 243..258, type_params: [ TypeVar( TypeParamTypeVar { - range: 356..369, + range: 244..257, name: Identifier { id: Name("T"), - range: 356..357, + range: 244..245, }, bound: None, default: Some( Yield( ExprYield { - range: 361..368, + range: 249..256, value: Some( NumberLiteral( ExprNumberLiteral { - range: 367..368, + range: 255..256, value: Int( 1, ), @@ -778,7 +560,7 @@ Module( }, ), parameters: Parameters { - range: 370..372, + range: 258..260, posonlyargs: [], args: [], vararg: None, @@ -789,10 +571,10 @@ Module( body: [ Expr( StmtExpr { - range: 374..377, + range: 262..265, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 374..377, + range: 262..265, }, ), }, @@ -802,32 +584,32 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 409..438, + range: 297..326, is_async: false, decorator_list: [], name: Identifier { id: Name("r"), - range: 413..414, + range: 301..302, }, type_params: Some( TypeParams { - range: 414..431, + range: 302..319, type_params: [ TypeVarTuple( TypeParamTypeVarTuple { - range: 415..430, + range: 303..318, name: Identifier { id: Name("Ts"), - range: 416..418, + range: 304..306, }, default: Some( Yield( ExprYield { - range: 422..429, + range: 310..317, value: Some( NumberLiteral( ExprNumberLiteral { - range: 428..429, + range: 316..317, value: Int( 1, ), @@ -843,7 +625,7 @@ Module( }, ), parameters: Parameters { - range: 431..433, + range: 319..321, posonlyargs: [], args: [], vararg: None, @@ -854,10 +636,10 @@ Module( body: [ Expr( StmtExpr { - range: 435..438, + range: 323..326, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 435..438, + range: 323..326, }, ), }, @@ -867,32 +649,32 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 473..503, + range: 361..391, is_async: false, decorator_list: [], name: Identifier { id: Name("s"), - range: 477..478, + range: 365..366, }, type_params: Some( TypeParams { - range: 478..496, + range: 366..384, type_params: [ ParamSpec( TypeParamParamSpec { - range: 479..495, + range: 367..383, name: Identifier { id: Name("Ts"), - range: 481..483, + range: 369..371, }, default: Some( Yield( ExprYield { - range: 487..494, + range: 375..382, value: Some( NumberLiteral( ExprNumberLiteral { - range: 493..494, + range: 381..382, value: Int( 1, ), @@ -908,7 +690,7 @@ Module( }, ), parameters: Parameters { - range: 496..498, + range: 384..386, posonlyargs: [], args: [], vararg: None, @@ -919,10 +701,10 @@ Module( body: [ Expr( StmtExpr { - range: 500..503, + range: 388..391, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 500..503, + range: 388..391, }, ), }, @@ -932,38 +714,38 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 534..559, + range: 422..447, is_async: false, decorator_list: [], name: Identifier { id: Name("t"), - range: 538..539, + range: 426..427, }, type_params: Some( TypeParams { - range: 539..552, + range: 427..440, type_params: [ TypeVar( TypeParamTypeVar { - range: 540..551, + range: 428..439, name: Identifier { id: Name("T"), - range: 540..541, + range: 428..429, }, bound: Some( Named( ExprNamed { - range: 544..550, + range: 432..438, target: Name( ExprName { - range: 544..545, + range: 432..433, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { - range: 549..550, + range: 437..438, value: Int( 1, ), @@ -979,7 +761,7 @@ Module( }, ), parameters: Parameters { - range: 552..554, + range: 440..442, posonlyargs: [], args: [], vararg: None, @@ -990,10 +772,10 @@ Module( body: [ Expr( StmtExpr { - range: 556..559, + range: 444..447, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 556..559, + range: 444..447, }, ), }, @@ -1003,39 +785,39 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 596..622, + range: 484..510, is_async: false, decorator_list: [], name: Identifier { id: Name("u"), - range: 600..601, + range: 488..489, }, type_params: Some( TypeParams { - range: 601..615, + range: 489..503, type_params: [ TypeVar( TypeParamTypeVar { - range: 602..614, + range: 490..502, name: Identifier { id: Name("T"), - range: 602..603, + range: 490..491, }, bound: None, default: Some( Named( ExprNamed { - range: 607..613, + range: 495..501, target: Name( ExprName { - range: 607..608, + range: 495..496, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { - range: 612..613, + range: 500..501, value: Int( 1, ), @@ -1050,7 +832,7 @@ Module( }, ), parameters: Parameters { - range: 615..617, + range: 503..505, posonlyargs: [], args: [], vararg: None, @@ -1061,10 +843,10 @@ Module( body: [ Expr( StmtExpr { - range: 619..622, + range: 507..510, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 619..622, + range: 507..510, }, ), }, @@ -1074,38 +856,38 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 660..688, + range: 548..576, is_async: false, decorator_list: [], name: Identifier { id: Name("v"), - range: 664..665, + range: 552..553, }, type_params: Some( TypeParams { - range: 665..681, + range: 553..569, type_params: [ TypeVarTuple( TypeParamTypeVarTuple { - range: 666..680, + range: 554..568, name: Identifier { id: Name("Ts"), - range: 667..669, + range: 555..557, }, default: Some( Named( ExprNamed { - range: 673..679, + range: 561..567, target: Name( ExprName { - range: 673..674, + range: 561..562, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { - range: 678..679, + range: 566..567, value: Int( 1, ), @@ -1120,7 +902,7 @@ Module( }, ), parameters: Parameters { - range: 681..683, + range: 569..571, posonlyargs: [], args: [], vararg: None, @@ -1131,10 +913,10 @@ Module( body: [ Expr( StmtExpr { - range: 685..688, + range: 573..576, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 685..688, + range: 573..576, }, ), }, @@ -1144,38 +926,38 @@ Module( ), FunctionDef( StmtFunctionDef { - range: 729..758, + range: 617..646, is_async: false, decorator_list: [], name: Identifier { id: Name("w"), - range: 733..734, + range: 621..622, }, type_params: Some( TypeParams { - range: 734..751, + range: 622..639, type_params: [ ParamSpec( TypeParamParamSpec { - range: 735..750, + range: 623..638, name: Identifier { id: Name("Ts"), - range: 737..739, + range: 625..627, }, default: Some( Named( ExprNamed { - range: 743..749, + range: 631..637, target: Name( ExprName { - range: 743..744, + range: 631..632, id: Name("x"), ctx: Store, }, ), value: NumberLiteral( ExprNumberLiteral { - range: 748..749, + range: 636..637, value: Int( 1, ), @@ -1190,7 +972,7 @@ Module( }, ), parameters: Parameters { - range: 751..753, + range: 639..641, posonlyargs: [], args: [], vararg: None, @@ -1201,10 +983,10 @@ Module( body: [ Expr( StmtExpr { - range: 755..758, + range: 643..646, value: EllipsisLiteral( ExprEllipsisLiteral { - range: 755..758, + range: 643..646, }, ), }, @@ -1231,7 +1013,7 @@ Module( 2 | def g[T](arg: (x := 1)): ... | ^^^^^^ Syntax Error: named expression cannot be used within a generic definition 3 | def h[T](x: (yield 1)): ... -4 | def i(x: (yield 1)): ... +4 | def j[T]() -> (yield 1): ... | @@ -1240,153 +1022,113 @@ Module( 2 | def g[T](arg: (x := 1)): ... 3 | def h[T](x: (yield 1)): ... | ^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition -4 | def i(x: (yield 1)): ... -5 | def j[T]() -> (yield 1): ... +4 | def j[T]() -> (yield 1): ... +5 | def l[T](x: (yield from 1)): ... | | 2 | def g[T](arg: (x := 1)): ... 3 | def h[T](x: (yield 1)): ... -4 | def i(x: (yield 1)): ... - | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation -5 | def j[T]() -> (yield 1): ... -6 | def k() -> (yield 1): ... +4 | def j[T]() -> (yield 1): ... + | ^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition +5 | def l[T](x: (yield from 1)): ... +6 | def n[T]() -> (yield from 1): ... | | 3 | def h[T](x: (yield 1)): ... -4 | def i(x: (yield 1)): ... -5 | def j[T]() -> (yield 1): ... - | ^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition -6 | def k() -> (yield 1): ... -7 | def l[T](x: (yield from 1)): ... +4 | def j[T]() -> (yield 1): ... +5 | def l[T](x: (yield from 1)): ... + | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition +6 | def n[T]() -> (yield from 1): ... +7 | def p[T: (yield 1)](): ... # yield in TypeVar bound | | -4 | def i(x: (yield 1)): ... -5 | def j[T]() -> (yield 1): ... -6 | def k() -> (yield 1): ... - | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation -7 | def l[T](x: (yield from 1)): ... -8 | def m(x: (yield from 1)): ... +4 | def j[T]() -> (yield 1): ... +5 | def l[T](x: (yield from 1)): ... +6 | def n[T]() -> (yield from 1): ... + | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition +7 | def p[T: (yield 1)](): ... # yield in TypeVar bound +8 | def q[T = (yield 1)](): ... # yield in TypeVar default | | -5 | def j[T]() -> (yield 1): ... -6 | def k() -> (yield 1): ... -7 | def l[T](x: (yield from 1)): ... - | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition -8 | def m(x: (yield from 1)): ... -9 | def n[T]() -> (yield from 1): ... +5 | def l[T](x: (yield from 1)): ... +6 | def n[T]() -> (yield from 1): ... +7 | def p[T: (yield 1)](): ... # yield in TypeVar bound + | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound +8 | def q[T = (yield 1)](): ... # yield in TypeVar default +9 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default | | - 6 | def k() -> (yield 1): ... - 7 | def l[T](x: (yield from 1)): ... - 8 | def m(x: (yield from 1)): ... - | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation - 9 | def n[T]() -> (yield from 1): ... -10 | def o() -> (yield from 1): ... - | - - - | - 7 | def l[T](x: (yield from 1)): ... - 8 | def m(x: (yield from 1)): ... - 9 | def n[T]() -> (yield from 1): ... - | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a generic definition -10 | def o() -> (yield from 1): ... -11 | def p[T: (yield 1)](): ... # yield in TypeVar bound - | - - - | - 8 | def m(x: (yield from 1)): ... - 9 | def n[T]() -> (yield from 1): ... -10 | def o() -> (yield from 1): ... - | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation -11 | def p[T: (yield 1)](): ... # yield in TypeVar bound -12 | def q[T = (yield 1)](): ... # yield in TypeVar default - | - - - | - 9 | def n[T]() -> (yield from 1): ... -10 | def o() -> (yield from 1): ... -11 | def p[T: (yield 1)](): ... # yield in TypeVar bound - | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound -12 | def q[T = (yield 1)](): ... # yield in TypeVar default -13 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default - | - - - | -10 | def o() -> (yield from 1): ... -11 | def p[T: (yield 1)](): ... # yield in TypeVar bound -12 | def q[T = (yield 1)](): ... # yield in TypeVar default + 6 | def n[T]() -> (yield from 1): ... + 7 | def p[T: (yield 1)](): ... # yield in TypeVar bound + 8 | def q[T = (yield 1)](): ... # yield in TypeVar default | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar default -13 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default -14 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default + 9 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default +10 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default | | -11 | def p[T: (yield 1)](): ... # yield in TypeVar bound -12 | def q[T = (yield 1)](): ... # yield in TypeVar default -13 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default + 7 | def p[T: (yield 1)](): ... # yield in TypeVar bound + 8 | def q[T = (yield 1)](): ... # yield in TypeVar default + 9 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default | ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVarTuple default -14 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default -15 | def t[T: (x := 1)](): ... # named expr in TypeVar bound +10 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default +11 | def t[T: (x := 1)](): ... # named expr in TypeVar bound | | -12 | def q[T = (yield 1)](): ... # yield in TypeVar default -13 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default -14 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default + 8 | def q[T = (yield 1)](): ... # yield in TypeVar default + 9 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default +10 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default | ^^^^^^^ Syntax Error: yield expression cannot be used within a ParamSpec default -15 | def t[T: (x := 1)](): ... # named expr in TypeVar bound -16 | def u[T = (x := 1)](): ... # named expr in TypeVar default +11 | def t[T: (x := 1)](): ... # named expr in TypeVar bound +12 | def u[T = (x := 1)](): ... # named expr in TypeVar default | | -13 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default -14 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default -15 | def t[T: (x := 1)](): ... # named expr in TypeVar bound + 9 | def r[*Ts = (yield 1)](): ... # yield in TypeVarTuple default +10 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default +11 | def t[T: (x := 1)](): ... # named expr in TypeVar bound | ^^^^^^ Syntax Error: named expression cannot be used within a TypeVar bound -16 | def u[T = (x := 1)](): ... # named expr in TypeVar default -17 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default +12 | def u[T = (x := 1)](): ... # named expr in TypeVar default +13 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default | | -14 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default -15 | def t[T: (x := 1)](): ... # named expr in TypeVar bound -16 | def u[T = (x := 1)](): ... # named expr in TypeVar default +10 | def s[**Ts = (yield 1)](): ... # yield in ParamSpec default +11 | def t[T: (x := 1)](): ... # named expr in TypeVar bound +12 | def u[T = (x := 1)](): ... # named expr in TypeVar default | ^^^^^^ Syntax Error: named expression cannot be used within a TypeVar default -17 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default -18 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default +13 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default +14 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default | | -15 | def t[T: (x := 1)](): ... # named expr in TypeVar bound -16 | def u[T = (x := 1)](): ... # named expr in TypeVar default -17 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default +11 | def t[T: (x := 1)](): ... # named expr in TypeVar bound +12 | def u[T = (x := 1)](): ... # named expr in TypeVar default +13 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default | ^^^^^^ Syntax Error: named expression cannot be used within a TypeVarTuple default -18 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default +14 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default | | -16 | def u[T = (x := 1)](): ... # named expr in TypeVar default -17 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default -18 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default +12 | def u[T = (x := 1)](): ... # named expr in TypeVar default +13 | def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default +14 | def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default | ^^^^^^ Syntax Error: named expression cannot be used within a ParamSpec default | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@param_with_invalid_annotation.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@param_with_invalid_annotation.py.snap index d799a7893971d..c63c0fdb25a9e 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@param_with_invalid_annotation.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@param_with_invalid_annotation.py.snap @@ -224,13 +224,3 @@ Module( 3 | def foo(arg: x := int): ... | ^^ Syntax Error: Expected ',', found ':=' | - - -## Semantic Syntax Errors - - | -1 | def foo(arg: *int): ... -2 | def foo(arg: yield int): ... - | ^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation -3 | def foo(arg: x := int): ... - | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@param_with_invalid_star_annotation.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@param_with_invalid_star_annotation.py.snap index 13eeeed68978f..f036adb4b7691 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@param_with_invalid_star_annotation.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@param_with_invalid_star_annotation.py.snap @@ -308,14 +308,3 @@ Module( | ^^^^^^^ Syntax Error: Yield expression cannot be used here 5 | # def foo(*args: **int): ... | - - -## Semantic Syntax Errors - - | -2 | def foo(*args: (*tuple[int])): ... -3 | def foo(*args: *int or str): ... -4 | def foo(*args: *yield x): ... - | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation -5 | # def foo(*args: **int): ... - | diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@valid_annotation_class.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@valid_annotation_class.py.snap index b94b2b72c8769..384272df707b0 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@valid_annotation_class.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@valid_annotation_class.py.snap @@ -7,7 +7,7 @@ input_file: crates/ruff_python_parser/resources/inline/ok/valid_annotation_class ``` Module( ModModule { - range: 0..24, + range: 0..94, body: [ ClassDef( StmtClassDef { @@ -59,6 +59,119 @@ Module( ], }, ), + FunctionDef( + StmtFunctionDef { + range: 24..93, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("f"), + range: 28..29, + }, + type_params: None, + parameters: Parameters { + range: 29..31, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: None, + body: [ + ClassDef( + StmtClassDef { + range: 37..60, + decorator_list: [], + name: Identifier { + id: Name("G"), + range: 43..44, + }, + type_params: None, + arguments: Some( + Arguments { + range: 44..55, + args: [ + Yield( + ExprYield { + range: 46..53, + value: Some( + NumberLiteral( + ExprNumberLiteral { + range: 52..53, + value: Int( + 1, + ), + }, + ), + ), + }, + ), + ], + keywords: [], + }, + ), + body: [ + Expr( + StmtExpr { + range: 57..60, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 57..60, + }, + ), + }, + ), + ], + }, + ), + ClassDef( + StmtClassDef { + range: 65..93, + decorator_list: [], + name: Identifier { + id: Name("H"), + range: 71..72, + }, + type_params: None, + arguments: Some( + Arguments { + range: 72..88, + args: [ + YieldFrom( + ExprYieldFrom { + range: 74..86, + value: NumberLiteral( + ExprNumberLiteral { + range: 85..86, + value: Int( + 1, + ), + }, + ), + }, + ), + ], + keywords: [], + }, + ), + body: [ + Expr( + StmtExpr { + range: 90..93, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 90..93, + }, + ), + }, + ), + ], + }, + ), + ], + }, + ), ], }, ) diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@valid_annotation_function.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@valid_annotation_function.py.snap index 5be2f67c144eb..249e0dce7b6a3 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@valid_annotation_function.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@valid_annotation_function.py.snap @@ -7,7 +7,7 @@ input_file: crates/ruff_python_parser/resources/inline/ok/valid_annotation_funct ``` Module( ModModule { - range: 0..51, + range: 0..192, body: [ FunctionDef( StmtFunctionDef { @@ -130,6 +130,247 @@ Module( ], }, ), + FunctionDef( + StmtFunctionDef { + range: 51..191, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("outer"), + range: 55..60, + }, + type_params: None, + parameters: Parameters { + range: 60..62, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: None, + body: [ + FunctionDef( + StmtFunctionDef { + range: 68..92, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("i"), + range: 72..73, + }, + type_params: None, + parameters: Parameters { + range: 73..87, + posonlyargs: [], + args: [ + ParameterWithDefault { + range: 74..86, + parameter: Parameter { + range: 74..86, + name: Identifier { + id: Name("x"), + range: 74..75, + }, + annotation: Some( + Yield( + ExprYield { + range: 78..85, + value: Some( + NumberLiteral( + ExprNumberLiteral { + range: 84..85, + value: Int( + 1, + ), + }, + ), + ), + }, + ), + ), + }, + default: None, + }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: None, + body: [ + Expr( + StmtExpr { + range: 89..92, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 89..92, + }, + ), + }, + ), + ], + }, + ), + FunctionDef( + StmtFunctionDef { + range: 97..122, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("k"), + range: 101..102, + }, + type_params: None, + parameters: Parameters { + range: 102..104, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: Some( + Yield( + ExprYield { + range: 109..116, + value: Some( + NumberLiteral( + ExprNumberLiteral { + range: 115..116, + value: Int( + 1, + ), + }, + ), + ), + }, + ), + ), + body: [ + Expr( + StmtExpr { + range: 119..122, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 119..122, + }, + ), + }, + ), + ], + }, + ), + FunctionDef( + StmtFunctionDef { + range: 127..156, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("m"), + range: 131..132, + }, + type_params: None, + parameters: Parameters { + range: 132..151, + posonlyargs: [], + args: [ + ParameterWithDefault { + range: 133..150, + parameter: Parameter { + range: 133..150, + name: Identifier { + id: Name("x"), + range: 133..134, + }, + annotation: Some( + YieldFrom( + ExprYieldFrom { + range: 137..149, + value: NumberLiteral( + ExprNumberLiteral { + range: 148..149, + value: Int( + 1, + ), + }, + ), + }, + ), + ), + }, + default: None, + }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: None, + body: [ + Expr( + StmtExpr { + range: 153..156, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 153..156, + }, + ), + }, + ), + ], + }, + ), + FunctionDef( + StmtFunctionDef { + range: 161..191, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("o"), + range: 165..166, + }, + type_params: None, + parameters: Parameters { + range: 166..168, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: Some( + YieldFrom( + ExprYieldFrom { + range: 173..185, + value: NumberLiteral( + ExprNumberLiteral { + range: 184..185, + value: Int( + 1, + ), + }, + ), + }, + ), + ), + body: [ + Expr( + StmtExpr { + range: 188..191, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 188..191, + }, + ), + }, + ), + ], + }, + ), + ], + }, + ), ], }, ) From c1ab6588a8c4a2bd41bd6c4943ea08d979fa2e59 Mon Sep 17 00:00:00 2001 From: Brent Westbrook Date: Fri, 4 Apr 2025 11:24:42 -0400 Subject: [PATCH 2/2] restore function type annotation error for future annotations, 3.14 --- crates/ruff_linter/src/checkers/ast/mod.rs | 4 + .../err/invalid_annotation_function_py314.py | 8 + .../ruff_python_parser/src/semantic_errors.rs | 33 +- crates/ruff_python_parser/tests/fixtures.rs | 4 + ...@invalid_annotation_function_py314.py.snap | 433 ++++++++++++++++++ 5 files changed, 478 insertions(+), 4 deletions(-) create mode 100644 crates/ruff_python_parser/resources/inline/err/invalid_annotation_function_py314.py create mode 100644 crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_function_py314.py.snap diff --git a/crates/ruff_linter/src/checkers/ast/mod.rs b/crates/ruff_linter/src/checkers/ast/mod.rs index 15f0d4f08a42b..8c40ab56b458d 100644 --- a/crates/ruff_linter/src/checkers/ast/mod.rs +++ b/crates/ruff_linter/src/checkers/ast/mod.rs @@ -587,6 +587,10 @@ impl SemanticSyntaxContext for Checker<'_> { fn source(&self) -> &str { self.source() } + + fn future_annotations_or_stub(&self) -> bool { + self.semantic.future_annotations_or_stub() + } } impl<'a> Visitor<'a> for Checker<'a> { diff --git a/crates/ruff_python_parser/resources/inline/err/invalid_annotation_function_py314.py b/crates/ruff_python_parser/resources/inline/err/invalid_annotation_function_py314.py new file mode 100644 index 0000000000000..8944d1f6f1b26 --- /dev/null +++ b/crates/ruff_python_parser/resources/inline/err/invalid_annotation_function_py314.py @@ -0,0 +1,8 @@ +# parse_options: {"target-version": "3.14"} +def f() -> (y := 3): ... +def g(arg: (x := 1)): ... +def outer(): + def i(x: (yield 1)): ... + def k() -> (yield 1): ... + def m(x: (yield from 1)): ... + def o() -> (yield from 1): ... diff --git a/crates/ruff_python_parser/src/semantic_errors.rs b/crates/ruff_python_parser/src/semantic_errors.rs index 37bf341ab94ba..e7cfb4832450e 100644 --- a/crates/ruff_python_parser/src/semantic_errors.rs +++ b/crates/ruff_python_parser/src/semantic_errors.rs @@ -120,7 +120,7 @@ impl SemanticSyntaxChecker { fn check_annotation(stmt: &ast::Stmt, ctx: &Ctx) { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { - type_params: Some(type_params), + type_params, parameters, returns, .. @@ -134,6 +134,16 @@ impl SemanticSyntaxChecker { // def m(x: (yield from 1)): ... // def o() -> (yield from 1): ... + // test_err invalid_annotation_function_py314 + // # parse_options: {"target-version": "3.14"} + // def f() -> (y := 3): ... + // def g(arg: (x := 1)): ... + // def outer(): + // def i(x: (yield 1)): ... + // def k() -> (yield 1): ... + // def m(x: (yield from 1)): ... + // def o() -> (yield from 1): ... + // test_err invalid_annotation_function // def f[T]() -> (y := 3): ... // def g[T](arg: (x := 1)): ... @@ -150,10 +160,20 @@ impl SemanticSyntaxChecker { // def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default // def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default let mut visitor = InvalidExpressionVisitor { - position: InvalidExpressionPosition::GenericDefinition, + position: InvalidExpressionPosition::TypeAnnotation, ctx, }; - visitor.visit_type_params(type_params); + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); + } + // the __future__ annotation error takes precedence over the generic error + if ctx.future_annotations_or_stub() || ctx.python_version() > PythonVersion::PY313 { + visitor.position = InvalidExpressionPosition::TypeAnnotation; + } else if type_params.is_some() { + visitor.position = InvalidExpressionPosition::GenericDefinition; + } else { + return; + } for param in parameters .iter() .filter_map(ast::AnyParameterRef::annotation) @@ -182,7 +202,7 @@ impl SemanticSyntaxChecker { // class K[T: (yield 1)]: ... # yield in TypeVar // class L[T: (x := 1)]: ... # named expr in TypeVar let mut visitor = InvalidExpressionVisitor { - position: InvalidExpressionPosition::TypeVarBound, + position: InvalidExpressionPosition::TypeAnnotation, ctx, }; visitor.visit_type_params(type_params); @@ -835,6 +855,7 @@ pub enum InvalidExpressionPosition { TypeVarDefault, TypeVarTupleDefault, ParamSpecDefault, + TypeAnnotation, GenericDefinition, TypeAlias, } @@ -846,6 +867,7 @@ impl Display for InvalidExpressionPosition { InvalidExpressionPosition::TypeVarDefault => "TypeVar default", InvalidExpressionPosition::TypeVarTupleDefault => "TypeVarTuple default", InvalidExpressionPosition::ParamSpecDefault => "ParamSpec default", + InvalidExpressionPosition::TypeAnnotation => "type annotation", InvalidExpressionPosition::GenericDefinition => "generic definition", InvalidExpressionPosition::TypeAlias => "type alias", }) @@ -1130,6 +1152,9 @@ pub trait SemanticSyntaxContext { /// Returns `true` if a module's docstring boundary has been passed. fn seen_docstring_boundary(&self) -> bool; + /// Returns `true` if `__future__`-style type annotations are enabled. + fn future_annotations_or_stub(&self) -> bool; + /// The target Python version for detecting backwards-incompatible syntax changes. fn python_version(&self) -> PythonVersion; diff --git a/crates/ruff_python_parser/tests/fixtures.rs b/crates/ruff_python_parser/tests/fixtures.rs index f135709fdaefc..0fbe6597d111a 100644 --- a/crates/ruff_python_parser/tests/fixtures.rs +++ b/crates/ruff_python_parser/tests/fixtures.rs @@ -490,6 +490,10 @@ impl SemanticSyntaxContext for TestContext<'_> { false } + fn future_annotations_or_stub(&self) -> bool { + false + } + fn python_version(&self) -> PythonVersion { self.python_version } diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_function_py314.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_function_py314.py.snap new file mode 100644 index 0000000000000..90d1a25695d66 --- /dev/null +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_function_py314.py.snap @@ -0,0 +1,433 @@ +--- +source: crates/ruff_python_parser/tests/fixtures.rs +input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_function_py314.py +--- +## AST + +``` +Module( + ModModule { + range: 0..236, + body: [ + FunctionDef( + StmtFunctionDef { + range: 44..68, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("f"), + range: 48..49, + }, + type_params: None, + parameters: Parameters { + range: 49..51, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: Some( + Named( + ExprNamed { + range: 56..62, + target: Name( + ExprName { + range: 56..57, + id: Name("y"), + ctx: Store, + }, + ), + value: NumberLiteral( + ExprNumberLiteral { + range: 61..62, + value: Int( + 3, + ), + }, + ), + }, + ), + ), + body: [ + Expr( + StmtExpr { + range: 65..68, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 65..68, + }, + ), + }, + ), + ], + }, + ), + FunctionDef( + StmtFunctionDef { + range: 69..94, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("g"), + range: 73..74, + }, + type_params: None, + parameters: Parameters { + range: 74..89, + posonlyargs: [], + args: [ + ParameterWithDefault { + range: 75..88, + parameter: Parameter { + range: 75..88, + name: Identifier { + id: Name("arg"), + range: 75..78, + }, + annotation: Some( + Named( + ExprNamed { + range: 81..87, + target: Name( + ExprName { + range: 81..82, + id: Name("x"), + ctx: Store, + }, + ), + value: NumberLiteral( + ExprNumberLiteral { + range: 86..87, + value: Int( + 1, + ), + }, + ), + }, + ), + ), + }, + default: None, + }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: None, + body: [ + Expr( + StmtExpr { + range: 91..94, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 91..94, + }, + ), + }, + ), + ], + }, + ), + FunctionDef( + StmtFunctionDef { + range: 95..235, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("outer"), + range: 99..104, + }, + type_params: None, + parameters: Parameters { + range: 104..106, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: None, + body: [ + FunctionDef( + StmtFunctionDef { + range: 112..136, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("i"), + range: 116..117, + }, + type_params: None, + parameters: Parameters { + range: 117..131, + posonlyargs: [], + args: [ + ParameterWithDefault { + range: 118..130, + parameter: Parameter { + range: 118..130, + name: Identifier { + id: Name("x"), + range: 118..119, + }, + annotation: Some( + Yield( + ExprYield { + range: 122..129, + value: Some( + NumberLiteral( + ExprNumberLiteral { + range: 128..129, + value: Int( + 1, + ), + }, + ), + ), + }, + ), + ), + }, + default: None, + }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: None, + body: [ + Expr( + StmtExpr { + range: 133..136, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 133..136, + }, + ), + }, + ), + ], + }, + ), + FunctionDef( + StmtFunctionDef { + range: 141..166, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("k"), + range: 145..146, + }, + type_params: None, + parameters: Parameters { + range: 146..148, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: Some( + Yield( + ExprYield { + range: 153..160, + value: Some( + NumberLiteral( + ExprNumberLiteral { + range: 159..160, + value: Int( + 1, + ), + }, + ), + ), + }, + ), + ), + body: [ + Expr( + StmtExpr { + range: 163..166, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 163..166, + }, + ), + }, + ), + ], + }, + ), + FunctionDef( + StmtFunctionDef { + range: 171..200, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("m"), + range: 175..176, + }, + type_params: None, + parameters: Parameters { + range: 176..195, + posonlyargs: [], + args: [ + ParameterWithDefault { + range: 177..194, + parameter: Parameter { + range: 177..194, + name: Identifier { + id: Name("x"), + range: 177..178, + }, + annotation: Some( + YieldFrom( + ExprYieldFrom { + range: 181..193, + value: NumberLiteral( + ExprNumberLiteral { + range: 192..193, + value: Int( + 1, + ), + }, + ), + }, + ), + ), + }, + default: None, + }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: None, + body: [ + Expr( + StmtExpr { + range: 197..200, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 197..200, + }, + ), + }, + ), + ], + }, + ), + FunctionDef( + StmtFunctionDef { + range: 205..235, + is_async: false, + decorator_list: [], + name: Identifier { + id: Name("o"), + range: 209..210, + }, + type_params: None, + parameters: Parameters { + range: 210..212, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + returns: Some( + YieldFrom( + ExprYieldFrom { + range: 217..229, + value: NumberLiteral( + ExprNumberLiteral { + range: 228..229, + value: Int( + 1, + ), + }, + ), + }, + ), + ), + body: [ + Expr( + StmtExpr { + range: 232..235, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 232..235, + }, + ), + }, + ), + ], + }, + ), + ], + }, + ), + ], + }, +) +``` +## Semantic Syntax Errors + + | +1 | # parse_options: {"target-version": "3.14"} +2 | def f() -> (y := 3): ... + | ^^^^^^ Syntax Error: named expression cannot be used within a type annotation +3 | def g(arg: (x := 1)): ... +4 | def outer(): + | + + + | +1 | # parse_options: {"target-version": "3.14"} +2 | def f() -> (y := 3): ... +3 | def g(arg: (x := 1)): ... + | ^^^^^^ Syntax Error: named expression cannot be used within a type annotation +4 | def outer(): +5 | def i(x: (yield 1)): ... + | + + + | +3 | def g(arg: (x := 1)): ... +4 | def outer(): +5 | def i(x: (yield 1)): ... + | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation +6 | def k() -> (yield 1): ... +7 | def m(x: (yield from 1)): ... + | + + + | +4 | def outer(): +5 | def i(x: (yield 1)): ... +6 | def k() -> (yield 1): ... + | ^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation +7 | def m(x: (yield from 1)): ... +8 | def o() -> (yield from 1): ... + | + + + | +5 | def i(x: (yield 1)): ... +6 | def k() -> (yield 1): ... +7 | def m(x: (yield from 1)): ... + | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation +8 | def o() -> (yield from 1): ... + | + + + | +6 | def k() -> (yield 1): ... +7 | def m(x: (yield from 1)): ... +8 | def o() -> (yield from 1): ... + | ^^^^^^^^^^^^ Syntax Error: yield expression cannot be used within a type annotation + |