diff --git a/crates/ruff_python_parser/resources/inline/err/assign_stmt_invalid_value_expr.py b/crates/ruff_python_parser/resources/inline/err/assign_stmt_invalid_value_expr.py index c8cf8e64ee..0ffad964a2 100644 --- a/crates/ruff_python_parser/resources/inline/err/assign_stmt_invalid_value_expr.py +++ b/crates/ruff_python_parser/resources/inline/err/assign_stmt_invalid_value_expr.py @@ -1,5 +1,5 @@ -x = *a and b -x = *yield x -x = *yield from x -x = *lambda x: x +x = (*a and b,) +x = (42, *yield x) +x = (42, *yield from x) +x = (*lambda x: x,) x = x := 1 diff --git a/crates/ruff_python_parser/resources/inline/err/assign_stmt_starred_expr_value.py b/crates/ruff_python_parser/resources/inline/err/assign_stmt_starred_expr_value.py new file mode 100644 index 0000000000..8b31695407 --- /dev/null +++ b/crates/ruff_python_parser/resources/inline/err/assign_stmt_starred_expr_value.py @@ -0,0 +1,4 @@ +_ = *[42] +_ = *{42} +_ = *list() +_ = *(p + q) diff --git a/crates/ruff_python_parser/resources/inline/ok/assign_stmt_starred_expr_value.py b/crates/ruff_python_parser/resources/inline/ok/assign_stmt_starred_expr_value.py new file mode 100644 index 0000000000..2e8a1919b0 --- /dev/null +++ b/crates/ruff_python_parser/resources/inline/ok/assign_stmt_starred_expr_value.py @@ -0,0 +1,4 @@ +_ = 4 +_ = [4] +_ = (*[1],) +_ = *[1], diff --git a/crates/ruff_python_parser/resources/valid/statement/assignment.py b/crates/ruff_python_parser/resources/valid/statement/assignment.py index 992e5f8fba..7e0b458335 100644 --- a/crates/ruff_python_parser/resources/valid/statement/assignment.py +++ b/crates/ruff_python_parser/resources/valid/statement/assignment.py @@ -37,7 +37,7 @@ foo.bar = 42 foo = 42 -[] = *data -() = *data +[] = (*data,) +() = (*data,) a, b = ab a = b = c \ No newline at end of file diff --git a/crates/ruff_python_parser/src/parser/statement.rs b/crates/ruff_python_parser/src/parser/statement.rs index 7f3f0c74e2..3116fc46c5 100644 --- a/crates/ruff_python_parser/src/parser/statement.rs +++ b/crates/ruff_python_parser/src/parser/statement.rs @@ -1127,10 +1127,10 @@ impl<'src> Parser<'src> { // a + b // test_err assign_stmt_invalid_value_expr - // x = *a and b - // x = *yield x - // x = *yield from x - // x = *lambda x: x + // x = (*a and b,) + // x = (42, *yield x) + // x = (42, *yield from x) + // x = (*lambda x: x,) // x = x := 1 let mut value = diff --git a/crates/ruff_python_parser/src/semantic_errors.rs b/crates/ruff_python_parser/src/semantic_errors.rs index 149292b3b9..83366b035f 100644 --- a/crates/ruff_python_parser/src/semantic_errors.rs +++ b/crates/ruff_python_parser/src/semantic_errors.rs @@ -90,7 +90,7 @@ impl SemanticSyntaxChecker { Self::duplicate_type_parameter_name(type_params, ctx); } } - Stmt::Assign(ast::StmtAssign { targets, .. }) => { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { if let [Expr::Starred(ast::ExprStarred { range, .. })] = targets.as_slice() { // test_ok single_starred_assignment_target // (*a,) = (1,) @@ -105,6 +105,19 @@ impl SemanticSyntaxChecker { *range, ); } + + // test_ok assign_stmt_starred_expr_value + // _ = 4 + // _ = [4] + // _ = (*[1],) + // _ = *[1], + + // test_err assign_stmt_starred_expr_value + // _ = *[42] + // _ = *{42} + // _ = *list() + // _ = *(p + q) + Self::invalid_star_expression(value, ctx); } Stmt::Return(ast::StmtReturn { value, range }) => { if let Some(value) = value { diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_invalid_value_expr.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_invalid_value_expr.py.snap index 306a963769..78ea01ad7e 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_invalid_value_expr.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_invalid_value_expr.py.snap @@ -1,18 +1,17 @@ --- source: crates/ruff_python_parser/tests/fixtures.rs input_file: crates/ruff_python_parser/resources/inline/err/assign_stmt_invalid_value_expr.py -snapshot_kind: text --- ## AST ``` Module( ModModule { - range: 0..72, + range: 0..90, body: [ Assign( StmtAssign { - range: 0..12, + range: 0..15, targets: [ Name( ExprName { @@ -22,164 +21,216 @@ Module( }, ), ], - value: Starred( - ExprStarred { - range: 4..12, - value: BoolOp( - ExprBoolOp { - range: 5..12, - op: And, - values: [ - Name( - ExprName { - range: 5..6, - id: Name("a"), - ctx: Load, - }, - ), - Name( - ExprName { - range: 11..12, - id: Name("b"), - ctx: Load, - }, - ), - ], - }, - ), - ctx: Load, - }, - ), - }, - ), - Assign( - StmtAssign { - range: 13..25, - targets: [ - Name( - ExprName { - range: 13..14, - id: Name("x"), - ctx: Store, - }, - ), - ], - value: Starred( - ExprStarred { - range: 17..25, - value: Yield( - ExprYield { - range: 18..25, - value: Some( - Name( - ExprName { - range: 24..25, - id: Name("x"), - ctx: Load, - }, - ), - ), - }, - ), - ctx: Load, - }, - ), - }, - ), - Assign( - StmtAssign { - range: 26..43, - targets: [ - Name( - ExprName { - range: 26..27, - id: Name("x"), - ctx: Store, - }, - ), - ], - value: Starred( - ExprStarred { - range: 30..43, - value: YieldFrom( - ExprYieldFrom { - range: 31..43, - value: Name( - ExprName { - range: 42..43, - id: Name("x"), - ctx: Load, - }, - ), - }, - ), - ctx: Load, - }, - ), - }, - ), - Assign( - StmtAssign { - range: 44..60, - targets: [ - Name( - ExprName { - range: 44..45, - id: Name("x"), - ctx: Store, - }, - ), - ], - value: Starred( - ExprStarred { - range: 48..60, - value: Lambda( - ExprLambda { - range: 49..60, - parameters: Some( - Parameters { - range: 56..57, - posonlyargs: [], - args: [ - ParameterWithDefault { - range: 56..57, - parameter: Parameter { - range: 56..57, - name: Identifier { - id: Name("x"), - range: 56..57, + value: Tuple( + ExprTuple { + range: 4..15, + elts: [ + Starred( + ExprStarred { + range: 5..13, + value: BoolOp( + ExprBoolOp { + range: 6..13, + op: And, + values: [ + Name( + ExprName { + range: 6..7, + id: Name("a"), + ctx: Load, }, - annotation: None, - }, - default: None, - }, - ], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, - ), - body: Name( - ExprName { - range: 59..60, - id: Name("x"), - ctx: Load, - }, - ), - }, - ), + ), + Name( + ExprName { + range: 12..13, + id: Name("b"), + ctx: Load, + }, + ), + ], + }, + ), + ctx: Load, + }, + ), + ], ctx: Load, + parenthesized: true, }, ), }, ), Assign( StmtAssign { - range: 61..66, + range: 16..34, targets: [ Name( ExprName { - range: 61..62, + range: 16..17, + id: Name("x"), + ctx: Store, + }, + ), + ], + value: Tuple( + ExprTuple { + range: 20..34, + elts: [ + NumberLiteral( + ExprNumberLiteral { + range: 21..23, + value: Int( + 42, + ), + }, + ), + Starred( + ExprStarred { + range: 25..33, + value: Yield( + ExprYield { + range: 26..33, + value: Some( + Name( + ExprName { + range: 32..33, + id: Name("x"), + ctx: Load, + }, + ), + ), + }, + ), + ctx: Load, + }, + ), + ], + ctx: Load, + parenthesized: true, + }, + ), + }, + ), + Assign( + StmtAssign { + range: 35..58, + targets: [ + Name( + ExprName { + range: 35..36, + id: Name("x"), + ctx: Store, + }, + ), + ], + value: Tuple( + ExprTuple { + range: 39..58, + elts: [ + NumberLiteral( + ExprNumberLiteral { + range: 40..42, + value: Int( + 42, + ), + }, + ), + Starred( + ExprStarred { + range: 44..57, + value: YieldFrom( + ExprYieldFrom { + range: 45..57, + value: Name( + ExprName { + range: 56..57, + id: Name("x"), + ctx: Load, + }, + ), + }, + ), + ctx: Load, + }, + ), + ], + ctx: Load, + parenthesized: true, + }, + ), + }, + ), + Assign( + StmtAssign { + range: 59..78, + targets: [ + Name( + ExprName { + range: 59..60, + id: Name("x"), + ctx: Store, + }, + ), + ], + value: Tuple( + ExprTuple { + range: 63..78, + elts: [ + Starred( + ExprStarred { + range: 64..76, + value: Lambda( + ExprLambda { + range: 65..76, + parameters: Some( + Parameters { + range: 72..73, + posonlyargs: [], + args: [ + ParameterWithDefault { + range: 72..73, + parameter: Parameter { + range: 72..73, + name: Identifier { + id: Name("x"), + range: 72..73, + }, + annotation: None, + }, + default: None, + }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + ), + body: Name( + ExprName { + range: 75..76, + id: Name("x"), + ctx: Load, + }, + ), + }, + ), + ctx: Load, + }, + ), + ], + ctx: Load, + parenthesized: true, + }, + ), + }, + ), + Assign( + StmtAssign { + range: 79..84, + targets: [ + Name( + ExprName { + range: 79..80, id: Name("x"), ctx: Store, }, @@ -187,7 +238,7 @@ Module( ], value: Name( ExprName { - range: 65..66, + range: 83..84, id: Name("x"), ctx: Load, }, @@ -196,10 +247,10 @@ Module( ), Expr( StmtExpr { - range: 70..71, + range: 88..89, value: NumberLiteral( ExprNumberLiteral { - range: 70..71, + range: 88..89, value: Int( 1, ), @@ -214,44 +265,44 @@ Module( ## Errors | -1 | x = *a and b - | ^^^^^^^ Syntax Error: Boolean expression cannot be used here -2 | x = *yield x -3 | x = *yield from x +1 | x = (*a and b,) + | ^^^^^^^ Syntax Error: Boolean expression cannot be used here +2 | x = (42, *yield x) +3 | x = (42, *yield from x) | | -1 | x = *a and b -2 | x = *yield x - | ^^^^^^^ Syntax Error: Yield expression cannot be used here -3 | x = *yield from x -4 | x = *lambda x: x +1 | x = (*a and b,) +2 | x = (42, *yield x) + | ^^^^^^^ Syntax Error: Yield expression cannot be used here +3 | x = (42, *yield from x) +4 | x = (*lambda x: x,) | | -1 | x = *a and b -2 | x = *yield x -3 | x = *yield from x - | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here -4 | x = *lambda x: x +1 | x = (*a and b,) +2 | x = (42, *yield x) +3 | x = (42, *yield from x) + | ^^^^^^^^^^^^ Syntax Error: Yield expression cannot be used here +4 | x = (*lambda x: x,) 5 | x = x := 1 | | -2 | x = *yield x -3 | x = *yield from x -4 | x = *lambda x: x - | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here +2 | x = (42, *yield x) +3 | x = (42, *yield from x) +4 | x = (*lambda x: x,) + | ^^^^^^^^^^^ Syntax Error: Lambda expression cannot be used here 5 | x = x := 1 | | -3 | x = *yield from x -4 | x = *lambda x: x +3 | x = (42, *yield from x) +4 | x = (*lambda x: x,) 5 | x = x := 1 | ^^ Syntax Error: Expected a statement | diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_starred_expr_value.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_starred_expr_value.py.snap new file mode 100644 index 0000000000..fc1b615292 --- /dev/null +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@assign_stmt_starred_expr_value.py.snap @@ -0,0 +1,197 @@ +--- +source: crates/ruff_python_parser/tests/fixtures.rs +input_file: crates/ruff_python_parser/resources/inline/err/assign_stmt_starred_expr_value.py +--- +## AST + +``` +Module( + ModModule { + range: 0..45, + body: [ + Assign( + StmtAssign { + range: 0..9, + targets: [ + Name( + ExprName { + range: 0..1, + id: Name("_"), + ctx: Store, + }, + ), + ], + value: Starred( + ExprStarred { + range: 4..9, + value: List( + ExprList { + range: 5..9, + elts: [ + NumberLiteral( + ExprNumberLiteral { + range: 6..8, + value: Int( + 42, + ), + }, + ), + ], + ctx: Load, + }, + ), + ctx: Load, + }, + ), + }, + ), + Assign( + StmtAssign { + range: 10..19, + targets: [ + Name( + ExprName { + range: 10..11, + id: Name("_"), + ctx: Store, + }, + ), + ], + value: Starred( + ExprStarred { + range: 14..19, + value: Set( + ExprSet { + range: 15..19, + elts: [ + NumberLiteral( + ExprNumberLiteral { + range: 16..18, + value: Int( + 42, + ), + }, + ), + ], + }, + ), + ctx: Load, + }, + ), + }, + ), + Assign( + StmtAssign { + range: 20..31, + targets: [ + Name( + ExprName { + range: 20..21, + id: Name("_"), + ctx: Store, + }, + ), + ], + value: Starred( + ExprStarred { + range: 24..31, + value: Call( + ExprCall { + range: 25..31, + func: Name( + ExprName { + range: 25..29, + id: Name("list"), + ctx: Load, + }, + ), + arguments: Arguments { + range: 29..31, + args: [], + keywords: [], + }, + }, + ), + ctx: Load, + }, + ), + }, + ), + Assign( + StmtAssign { + range: 32..44, + targets: [ + Name( + ExprName { + range: 32..33, + id: Name("_"), + ctx: Store, + }, + ), + ], + value: Starred( + ExprStarred { + range: 36..44, + value: BinOp( + ExprBinOp { + range: 38..43, + left: Name( + ExprName { + range: 38..39, + id: Name("p"), + ctx: Load, + }, + ), + op: Add, + right: Name( + ExprName { + range: 42..43, + id: Name("q"), + ctx: Load, + }, + ), + }, + ), + ctx: Load, + }, + ), + }, + ), + ], + }, +) +``` +## Semantic Syntax Errors + + | +1 | _ = *[42] + | ^^^^^ Syntax Error: can't use starred expression here +2 | _ = *{42} +3 | _ = *list() + | + + + | +1 | _ = *[42] +2 | _ = *{42} + | ^^^^^ Syntax Error: can't use starred expression here +3 | _ = *list() +4 | _ = *(p + q) + | + + + | +1 | _ = *[42] +2 | _ = *{42} +3 | _ = *list() + | ^^^^^^^ Syntax Error: can't use starred expression here +4 | _ = *(p + q) + | + + + | +2 | _ = *{42} +3 | _ = *list() +4 | _ = *(p + q) + | ^^^^^^^^ Syntax Error: can't use starred expression here + | diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@assign_stmt_starred_expr_value.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@assign_stmt_starred_expr_value.py.snap new file mode 100644 index 0000000000..5b5bf36875 --- /dev/null +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@assign_stmt_starred_expr_value.py.snap @@ -0,0 +1,157 @@ +--- +source: crates/ruff_python_parser/tests/fixtures.rs +input_file: crates/ruff_python_parser/resources/inline/ok/assign_stmt_starred_expr_value.py +--- +## AST + +``` +Module( + ModModule { + range: 0..36, + body: [ + Assign( + StmtAssign { + range: 0..5, + targets: [ + Name( + ExprName { + range: 0..1, + id: Name("_"), + ctx: Store, + }, + ), + ], + value: NumberLiteral( + ExprNumberLiteral { + range: 4..5, + value: Int( + 4, + ), + }, + ), + }, + ), + Assign( + StmtAssign { + range: 6..13, + targets: [ + Name( + ExprName { + range: 6..7, + id: Name("_"), + ctx: Store, + }, + ), + ], + value: List( + ExprList { + range: 10..13, + elts: [ + NumberLiteral( + ExprNumberLiteral { + range: 11..12, + value: Int( + 4, + ), + }, + ), + ], + ctx: Load, + }, + ), + }, + ), + Assign( + StmtAssign { + range: 14..25, + targets: [ + Name( + ExprName { + range: 14..15, + id: Name("_"), + ctx: Store, + }, + ), + ], + value: Tuple( + ExprTuple { + range: 18..25, + elts: [ + Starred( + ExprStarred { + range: 19..23, + value: List( + ExprList { + range: 20..23, + elts: [ + NumberLiteral( + ExprNumberLiteral { + range: 21..22, + value: Int( + 1, + ), + }, + ), + ], + ctx: Load, + }, + ), + ctx: Load, + }, + ), + ], + ctx: Load, + parenthesized: true, + }, + ), + }, + ), + Assign( + StmtAssign { + range: 26..35, + targets: [ + Name( + ExprName { + range: 26..27, + id: Name("_"), + ctx: Store, + }, + ), + ], + value: Tuple( + ExprTuple { + range: 30..35, + elts: [ + Starred( + ExprStarred { + range: 30..34, + value: List( + ExprList { + range: 31..34, + elts: [ + NumberLiteral( + ExprNumberLiteral { + range: 32..33, + value: Int( + 1, + ), + }, + ), + ], + ctx: Load, + }, + ), + ctx: Load, + }, + ), + ], + ctx: Load, + parenthesized: false, + }, + ), + }, + ), + ], + }, +) +``` diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assignment.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assignment.py.snap index 8c67f41106..606a9ea324 100644 --- a/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assignment.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@statement__assignment.py.snap @@ -7,7 +7,7 @@ input_file: crates/ruff_python_parser/resources/valid/statement/assignment.py ``` Module( ModModule { - range: 0..723, + range: 0..729, body: [ Assign( StmtAssign { @@ -802,7 +802,7 @@ Module( ), Assign( StmtAssign { - range: 682..692, + range: 682..695, targets: [ List( ExprList { @@ -812,67 +812,85 @@ Module( }, ), ], - value: Starred( - ExprStarred { - range: 687..692, - value: Name( - ExprName { - range: 688..692, - id: Name("data"), - ctx: Load, - }, - ), + value: Tuple( + ExprTuple { + range: 687..695, + elts: [ + Starred( + ExprStarred { + range: 688..693, + value: Name( + ExprName { + range: 689..693, + id: Name("data"), + ctx: Load, + }, + ), + ctx: Load, + }, + ), + ], ctx: Load, + parenthesized: true, }, ), }, ), Assign( StmtAssign { - range: 693..703, + range: 696..709, targets: [ Tuple( ExprTuple { - range: 693..695, + range: 696..698, elts: [], ctx: Store, parenthesized: true, }, ), ], - value: Starred( - ExprStarred { - range: 698..703, - value: Name( - ExprName { - range: 699..703, - id: Name("data"), - ctx: Load, - }, - ), + value: Tuple( + ExprTuple { + range: 701..709, + elts: [ + Starred( + ExprStarred { + range: 702..707, + value: Name( + ExprName { + range: 703..707, + id: Name("data"), + ctx: Load, + }, + ), + ctx: Load, + }, + ), + ], ctx: Load, + parenthesized: true, }, ), }, ), Assign( StmtAssign { - range: 704..713, + range: 710..719, targets: [ Tuple( ExprTuple { - range: 704..708, + range: 710..714, elts: [ Name( ExprName { - range: 704..705, + range: 710..711, id: Name("a"), ctx: Store, }, ), Name( ExprName { - range: 707..708, + range: 713..714, id: Name("b"), ctx: Store, }, @@ -885,7 +903,7 @@ Module( ], value: Name( ExprName { - range: 711..713, + range: 717..719, id: Name("ab"), ctx: Load, }, @@ -894,18 +912,18 @@ Module( ), Assign( StmtAssign { - range: 714..723, + range: 720..729, targets: [ Name( ExprName { - range: 714..715, + range: 720..721, id: Name("a"), ctx: Store, }, ), Name( ExprName { - range: 718..719, + range: 724..725, id: Name("b"), ctx: Store, }, @@ -913,7 +931,7 @@ Module( ], value: Name( ExprName { - range: 722..723, + range: 728..729, id: Name("c"), ctx: Load, },