Repository: psf/black

Issue:
Crash with preview style + line length 1
On Black 23.11.0:

```
% black -v --line-length 1 -c 'def f() -> tuple[int, int]: pass' --preview
def f() -> tuple[int, int]: pass
Traceback (most recent call last):
  File "src/black/__init__.py", line 1444, in assert_equivalent
  File "src/black/parsing.py", line 140, in parse_ast
SyntaxError: expected ':' (<unknown>, line 1)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "src/black/__init__.py", line 782, in reformat_code
  File "src/black/__init__.py", line 945, in format_stdin_to_stdout
  File "src/black/__init__.py", line 1011, in format_file_contents
  File "src/black/__init__.py", line 985, in check_stability_and_equivalence
  File "src/black/__init__.py", line 1447, in assert_equivalent
AssertionError: INTERNAL ERROR: Black produced invalid code: expected ':' (<unknown>, line 1). Please report a bug on https://github.com/psf/black/issues.  This invalid output might be helpful: /var/folders/hh/hdb5qd2x3v51v6l0gknpfjfr0000gp/T/blk_wad8_c6m.log
error: cannot format <string>: INTERNAL ERROR: Black produced invalid code: expected ':' (<unknown>, line 1). Please report a bug on https://github.com/psf/black/issues.  This invalid output might be helpful: /var/folders/hh/hdb5qd2x3v51v6l0gknpfjfr0000gp/T/blk_wad8_c6m.log
Oh no! 💥 💔 💥
```

Works without preview:

```
% black -v --line-length 1 -c 'def f() -> tuple[int, int]: pass'

def f() -> (
    tuple[
        int,
        int,
    ]
):
    pass
reformatted <string>
All done! ✨ 🍰 ✨
```

You can also make it crash with a slightly more reasonable line length if you make the identifiers longer:

```
% black -v --line-length 20 -c 'def ffffffffffffff() -> tupleeeeee[int, iiiiiiint]: pass' --preview
def ffffffffffffff() -> tupleeeeee[int, iiiiiiint]: pass
Traceback (most recent call last):
  File "src/black/__init__.py", line 1444, in assert_equivalent
  File "src/black/parsing.py", line 140, in parse_ast
SyntaxError: expected ':' (<unknown>, line 1)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "src/black/__init__.py", line 782, in reformat_code
  File "src/black/__init__.py", line 945, in format_stdin_to_stdout
  File "src/black/__init__.py", line 1011, in format_file_contents
  File "src/black/__init__.py", line 985, in check_stability_and_equivalence
  File "src/black/__init__.py", line 1447, in assert_equivalent
AssertionError: INTERNAL ERROR: Black produced invalid code: expected ':' (<unknown>, line 1). Please report a bug on https://github.com/psf/black/issues.  This invalid output might be helpful: /var/folders/hh/hdb5qd2x3v51v6l0gknpfjfr0000gp/T/blk_4f39fhc8.log
error: cannot format <string>: INTERNAL ERROR: Black produced invalid code: expected ':' (<unknown>, line 1). Please report a bug on https://github.com/psf/black/issues.  This invalid output might be helpful: /var/folders/hh/hdb5qd2x3v51v6l0gknpfjfr0000gp/T/blk_4f39fhc8.log
```

You can see with `--fast` why it crashes: it puts an illegal newline after the `->`:

```
% black --fast --line-length 1 -c 'def f() -> tuple[int, int]: pass' --preview
def f() -> 
    tuple[
    int,
    int,
]:
    pass
```

This is from the `parenthesize_long_type_hints` preview feature (#3899).


Discussion:
Correction: This is due to `respect_magic_trailing_comma_in_return_type` (#3916), not `parenthesize_long_type_hints`.
Looked into this a little today but couldn't find a fix. This variant of the test case is more effective: `def f() -> tuple[int, int,]: ...` since it doesn't rely on Black inserting a trailing comma itself first.
I'll try looking at it.

It's a shame that this didn't get caught at the time, since `assert_format` doesn't care about checking it for preview features. Maybe better if preview features had to explicitly mark themselves as not compatible with line-length=1 somewhere to skip the check?

Resolving patch:
diff --git a/src/black/linegen.py b/src/black/linegen.py
--- a/src/black/linegen.py
+++ b/src/black/linegen.py
@@ -744,7 +744,7 @@ def left_hand_split(
             if leaf.type in OPENING_BRACKETS:
                 matching_bracket = leaf
                 current_leaves = body_leaves
-    if not matching_bracket:
+    if not matching_bracket or not tail_leaves:
         raise CannotSplit("No brackets found")
 
     head = bracket_split_build_line(


Test patch:
diff --git a/tests/data/cases/return_annotation_brackets_crash_line_length_1.py b/tests/data/cases/return_annotation_brackets_crash_line_length_1.py
new file mode 100644
--- /dev/null
+++ b/tests/data/cases/return_annotation_brackets_crash_line_length_1.py
@@ -0,0 +1,9 @@
+# flags: --preview --minimum-version=3.10 --line-length=1
+
+def foo() -> tuple[int, int,]:
+    ...
+# output
+def foo() -> tuple[
+    int,
+    int,
+]: ...