Repository: scalameta/scalameta (scala)

Issue:
Crash on type lambda as type parameter
## Configuration (required) ##
`.scalafmt.conf`
```
runner.dialect = scala3
version = 0.0.0
```

```
$ ./scalafmt-linux-glibc --version
scalafmt 0.0.0+1-c1c9bbb3-SNAPSHOT
```

## Command-line parameters (required) ##

```
$ ./scalafmt-linux-glibc --config .scalafmt.conf
```
## Steps

Given code like this:
```scala
trait A[B[_]]
type T1 = A[[T] =>> T match
    case _ => Int]

@main def main(): Unit = println("hello")

```

## Problem

Scalafmt crashes with the return code 2
```
$ ./scalafmt-linux-glibc --config .scalafmt.conf 
main.scala:3: error: [dialect scala3] `outdent` expected but `]` found
    case _ => Int]
                 ^
$ echo $?
2
```

## Expectation

I would like the tool to not cash and I have no style preference.

## Workaround

I've found that by placing the closing `]` on its own line the problem goes away, so this file will not crash the formatter:
```scala
trait A[B[_]]
type T1 = A[[T] =>> T match
    case _ => Int
]

@main def main(): Unit = println("hello")
```

## Notes

This is also not working on the 3.8.3, the above reproduction is on the latest binary.
```
$ scalafmt --version
scalafmt 3.8.3
```

Pull request description:
Fixes #4015.

Patch:
diff --git a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
index 98552e62b9..721f5934e4 100644
--- a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
+++ b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
@@ -524,7 +524,12 @@ final class ScannerTokens(val tokens: Tokens)(implicit dialect: Dialect) {
           case _ => null
         }
       case _: LeftBracket => currRef(RegionBracket :: sepRegions)
-      case _: RightBracket => currRef(dropUntil(sepRegions)(_ eq RegionBracket))
+      case _: RightBracket => mkOutdents(sepRegions) {
+          case (r: SepRegionIndented) :: rs => OutdentInfo(r, rs)
+          case RegionBracket :: rs => OutdentInfo(null, rs, done = true)
+          case _ :: rs => OutdentInfo(null, rs)
+          case _ => null
+        }
       case _: LeftParen => currRef(RegionParen :: sepRegions)
       case _: RightParen => mkOutdents(sepRegions) {
           case (r: SepRegionIndented) :: rs => OutdentInfo(r, rs)


Test patch:
diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MatchTypeSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MatchTypeSuite.scala
index 110ea28b4c..d86f73a264 100644
--- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MatchTypeSuite.scala
+++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MatchTypeSuite.scala
@@ -237,4 +237,30 @@ class MatchTypeSuite extends BaseDottySuite {
       ))
     ))
   }
+
+  test("#4015") {
+    val code = """|type T1 = A[[T] =>> T match
+                  |    case _ => Int]
+                  |""".stripMargin
+    val layout = """|type T1 = A[[T] =>> T match {
+                    |  case _ => Int
+                    |}]
+                    |""".stripMargin
+    val tree = Defn.Type(
+      Nil,
+      pname("T1"),
+      Nil,
+      Type.Apply(
+        pname("A"),
+        List(Type.Lambda(
+          List(pparam("T")),
+          Type.Match(pname("T"), List(TypeCase(Type.PatWildcard(), pname("Int"))))
+        ))
+      ),
+      noBounds
+    )
+
+    runTestAssert[Stat](code, layout)(tree)
+  }
+
 }