Repository: psf/black

Issue:
Star operator without enclosing within parentheses
**Describe the bug**

Returning a tuple containing star operator without enclosing with parentheses leads to a `Cannot parse` error.

Oh no! 💥 💔 💥

**To Reproduce**

```python
def apply_to_last(input, func):
    *header, last = input
    return *header, func(last)

# which is valid code doing this:
assert apply_to_last([1,2,3], lambda x: x+10) == (1, 2, 13)
```

And try to blackify...

**Expected behavior**

I expect it to not choke. 

There is a *workaround* -- enclosing in parentheses

```python
def apply_to_last(input, func):
    *header, last = input
    return (*header, func(last))
```

But doing this makes the linter complain that _"Remove redundant parentheses"._

**Environment (please complete the following information):**

- Version: `axblack 20210720`
- MacOS 10.15.7
- Python 3.8.6




Discussion:
What python version do you have in your settings? This code is invalid in 3.6.
As in `python --version` right? 

I ask because I mentioned it above:

```
3.8.6
```

No, I mean Black's target-version setting. By default Black assumes your code is 3.6-compatible. Does it work if you limit your target-version to 3.8+.

We could perhaps autodetect this grammar change though and detect that the code is 3.8+.

Resolving patch:
diff --git a/src/black/__init__.py b/src/black/__init__.py
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -1210,6 +1210,14 @@ def get_features_used(  # noqa: C901
                         if argch.type in STARS:
                             features.add(feature)
 
+        elif (
+            n.type in {syms.return_stmt, syms.yield_expr}
+            and len(n.children) >= 2
+            and n.children[1].type == syms.testlist_star_expr
+            and any(child.type == syms.star_expr for child in n.children[1].children)
+        ):
+            features.add(Feature.UNPACKING_ON_FLOW)
+
         # Python 2 only features (for its deprecation) except for integers, see above
         elif n.type == syms.print_stmt:
             features.add(Feature.PRINT_STMT)
diff --git a/src/black/mode.py b/src/black/mode.py
--- a/src/black/mode.py
+++ b/src/black/mode.py
@@ -49,6 +49,7 @@ class Feature(Enum):
     POS_ONLY_ARGUMENTS = 9
     RELAXED_DECORATORS = 10
     PATTERN_MATCHING = 11
+    UNPACKING_ON_FLOW = 12
     FORCE_OPTIONAL_PARENTHESES = 50
 
     # __future__ flags
@@ -116,6 +117,7 @@ class Feature(Enum):
         Feature.FUTURE_ANNOTATIONS,
         Feature.ASSIGNMENT_EXPRESSIONS,
         Feature.POS_ONLY_ARGUMENTS,
+        Feature.UNPACKING_ON_FLOW,
     },
     TargetVersion.PY39: {
         Feature.UNICODE_LITERALS,
@@ -128,6 +130,7 @@ class Feature(Enum):
         Feature.ASSIGNMENT_EXPRESSIONS,
         Feature.RELAXED_DECORATORS,
         Feature.POS_ONLY_ARGUMENTS,
+        Feature.UNPACKING_ON_FLOW,
     },
     TargetVersion.PY310: {
         Feature.UNICODE_LITERALS,
@@ -140,6 +143,7 @@ class Feature(Enum):
         Feature.ASSIGNMENT_EXPRESSIONS,
         Feature.RELAXED_DECORATORS,
         Feature.POS_ONLY_ARGUMENTS,
+        Feature.UNPACKING_ON_FLOW,
         Feature.PATTERN_MATCHING,
     },
 }


Test patch:
diff --git a/tests/test_black.py b/tests/test_black.py
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -810,6 +810,14 @@ def test_get_features_used(self) -> None:
         self.assertEqual(black.get_features_used(node), {Feature.POS_ONLY_ARGUMENTS})
         node = black.lib2to3_parse("def fn(a, /, b): ...")
         self.assertEqual(black.get_features_used(node), {Feature.POS_ONLY_ARGUMENTS})
+        node = black.lib2to3_parse("def fn(): yield a, b")
+        self.assertEqual(black.get_features_used(node), set())
+        node = black.lib2to3_parse("def fn(): return a, b")
+        self.assertEqual(black.get_features_used(node), set())
+        node = black.lib2to3_parse("def fn(): yield *b, c")
+        self.assertEqual(black.get_features_used(node), {Feature.UNPACKING_ON_FLOW})
+        node = black.lib2to3_parse("def fn(): return a, *b, c")
+        self.assertEqual(black.get_features_used(node), {Feature.UNPACKING_ON_FLOW})
 
     def test_get_features_used_for_future_flags(self) -> None:
         for src, features in [