mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-22 03:15:44 +00:00
[syntax-errors] Tuple unpacking in for
statement iterator clause before Python 3.9 (#16558)
Summary -- This PR reuses a slightly modified version of the `check_tuple_unpacking` method added for detecting unpacking in `return` and `yield` statements to detect the same issue in the iterator clause of `for` loops. I ran into the same issue with a bare `for x in *rest: ...` example (invalid even on Python 3.13) and added it as a comment on https://github.com/astral-sh/ruff/issues/16520. I considered just making this an additional `StarTupleKind` variant as well, but this change was in a different version of Python, so I kept it separate. Test Plan -- New inline tests.
This commit is contained in:
parent
27e9d1fe3e
commit
2382fe1f25
9 changed files with 673 additions and 6 deletions
|
@ -2130,7 +2130,10 @@ impl<'src> Parser<'src> {
|
|||
// rest = (4, 5, 6)
|
||||
// def g(): yield 1, 2, 3, *rest
|
||||
// def h(): yield 1, (yield 2, *rest), 3
|
||||
self.check_tuple_unpacking(&parsed_expr, StarTupleKind::Yield);
|
||||
self.check_tuple_unpacking(
|
||||
&parsed_expr,
|
||||
UnsupportedSyntaxErrorKind::StarTuple(StarTupleKind::Yield),
|
||||
);
|
||||
|
||||
Box::new(parsed_expr.expr)
|
||||
});
|
||||
|
|
|
@ -406,7 +406,10 @@ impl<'src> Parser<'src> {
|
|||
// # parse_options: {"target-version": "3.7"}
|
||||
// rest = (4, 5, 6)
|
||||
// def f(): return 1, 2, 3, *rest
|
||||
self.check_tuple_unpacking(&parsed_expr, StarTupleKind::Return);
|
||||
self.check_tuple_unpacking(
|
||||
&parsed_expr,
|
||||
UnsupportedSyntaxErrorKind::StarTuple(StarTupleKind::Return),
|
||||
);
|
||||
|
||||
Box::new(parsed_expr.expr)
|
||||
});
|
||||
|
@ -420,10 +423,12 @@ impl<'src> Parser<'src> {
|
|||
/// Report [`UnsupportedSyntaxError`]s for each starred element in `expr` if it is an
|
||||
/// unparenthesized tuple.
|
||||
///
|
||||
/// This method can be used to check for tuple unpacking in return and yield statements, which
|
||||
/// are only allowed in Python 3.8 and later: <https://github.com/python/cpython/issues/76298>.
|
||||
pub(crate) fn check_tuple_unpacking(&mut self, expr: &Expr, kind: StarTupleKind) {
|
||||
let kind = UnsupportedSyntaxErrorKind::StarTuple(kind);
|
||||
/// This method can be used to check for tuple unpacking in `return`, `yield`, and `for`
|
||||
/// statements, which are only allowed after [Python 3.8] and [Python 3.9], respectively.
|
||||
///
|
||||
/// [Python 3.8]: https://github.com/python/cpython/issues/76298
|
||||
/// [Python 3.9]: https://github.com/python/cpython/issues/90881
|
||||
pub(super) fn check_tuple_unpacking(&mut self, expr: &Expr, kind: UnsupportedSyntaxErrorKind) {
|
||||
if kind.is_supported(self.options.target_version) {
|
||||
return;
|
||||
}
|
||||
|
@ -1732,6 +1737,28 @@ impl<'src> Parser<'src> {
|
|||
// for target in x := 1: ...
|
||||
let iter = self.parse_expression_list(ExpressionContext::starred_bitwise_or());
|
||||
|
||||
// test_ok for_iter_unpack_py39
|
||||
// # parse_options: {"target-version": "3.9"}
|
||||
// for x in *a, b: ...
|
||||
// for x in a, *b: ...
|
||||
// for x in *a, *b: ...
|
||||
|
||||
// test_ok for_iter_unpack_py38
|
||||
// # parse_options: {"target-version": "3.8"}
|
||||
// for x in (*a, b): ...
|
||||
// for x in ( a, *b): ...
|
||||
// for x in (*a, *b): ...
|
||||
|
||||
// test_err for_iter_unpack_py38
|
||||
// # parse_options: {"target-version": "3.8"}
|
||||
// for x in *a, b: ...
|
||||
// for x in a, *b: ...
|
||||
// for x in *a, *b: ...
|
||||
self.check_tuple_unpacking(
|
||||
&iter,
|
||||
UnsupportedSyntaxErrorKind::UnparenthesizedUnpackInFor,
|
||||
);
|
||||
|
||||
self.expect(TokenKind::Colon);
|
||||
|
||||
let body = self.parse_body(Clause::For);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue