Skip to content

Commit

Permalink
Always treat underscores as type bounds inside patterns
Browse files Browse the repository at this point in the history
Always treat underscores as type bounds inside patterns, even when `ctx.settings.XkindProjector.value == "underscores"`.

Fixes #14952 and #21400.

[Cherry-picked 374cd4f][modified]
  • Loading branch information
WojciechMazur committed Dec 9, 2024
1 parent 120a786 commit dd86f42
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
14 changes: 11 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,14 @@ object Parsers {
finally inEnum = saved
}

private var inMatchPattern = false
private def withinMatchPattern[T](body: => T): T = {
val saved = inMatchPattern
inMatchPattern = true
try body
finally inMatchPattern = saved
}

private var staged = StageKind.None
def withinStaged[T](kind: StageKind)(op: => T): T = {
val saved = staged
Expand Down Expand Up @@ -1857,7 +1865,7 @@ object Parsers {
if isSimpleLiteral then
SingletonTypeTree(simpleLiteral())
else if in.token == USCORE then
if ctx.settings.YkindProjector.value == "underscores" then
if ctx.settings.YkindProjector.value == "underscores" && !inMatchPattern then
val start = in.skipToken()
Ident(tpnme.USCOREkw).withSpan(Span(start, in.lastOffset, start))
else
Expand Down Expand Up @@ -2883,7 +2891,7 @@ object Parsers {
def caseClause(exprOnly: Boolean = false): CaseDef = atSpan(in.offset) {
val (pat, grd) = inSepRegion(InCase) {
accept(CASE)
(pattern(), guard())
(withinMatchPattern(pattern()), guard())
}
CaseDef(pat, grd, atSpan(accept(ARROW)) {
if exprOnly then
Expand All @@ -2907,7 +2915,7 @@ object Parsers {
val start = in.skipToken()
Ident(tpnme.WILDCARD).withSpan(Span(start, in.lastOffset, start))
case _ =>
rejectWildcardType(infixType())
withinMatchPattern(rejectWildcardType(infixType()))
}
}
CaseDef(pat, EmptyTree, atSpan(accept(ARROW)) {
Expand Down
9 changes: 9 additions & 0 deletions tests/pos/14952.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//> using options -Ykind-projector:underscores

import Tuple.*

type LiftP[F[_], T] <: Tuple =
T match {
case _ *: _ => F[Head[T]] *: LiftP[F, Tail[T]]
case _ => EmptyTuple
}
7 changes: 7 additions & 0 deletions tests/pos/21400.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//> using options -Ykind-projector:underscores

import scala.compiletime.ops.int.S

type IndexOf[T <: Tuple, E] <: Int = T match
case E *: _ => 0
case _ *: es => 1 // S[IndexOf[es, E]]
10 changes: 10 additions & 0 deletions tests/pos/21400b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//> using options -Ykind-projector:underscores

import scala.quoted.Type
import scala.quoted.Quotes

def x[A](t: Type[A])(using Quotes): Boolean = t match
case '[_ *: _] =>
true
case _ =>
false

0 comments on commit dd86f42

Please sign in to comment.