Skip to content

Commit 96faa3e

Browse files
Detect non Expr[..] splice patterns (#19944)
We compute the pattern using `Expr[pt]` of the prototype `pt` of the splice, but this is not enough to reject non-matching patterns. The quoted splices are encoded away before we get to the pattern matching phase where we could potentially detect that they will not match. Instead we check that all quote patterns are `Expr[..]` when typing the pattern. Fixes #19941
2 parents 6586418 + 2bcf0db commit 96faa3e

File tree

4 files changed

+15
-2
lines changed

4 files changed

+15
-2
lines changed

compiler/src/dotty/tools/dotc/quoted/QuotePatterns.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ object QuotePatterns:
2828
/** Check for restricted patterns */
2929
def checkPattern(quotePattern: QuotePattern)(using Context): Unit = new tpd.TreeTraverser {
3030
def traverse(tree: Tree)(using Context): Unit = tree match {
31-
case _: SplicePattern =>
31+
case tree: SplicePattern =>
32+
if !tree.body.typeOpt.derivesFrom(defn.QuotedExprClass) then
33+
report.error(i"Splice pattern must match an Expr[...]", tree.body.srcPos)
3234
case tdef: TypeDef if tdef.symbol.isClass =>
3335
val kind = if tdef.symbol.is(Module) then "objects" else "classes"
3436
report.error(em"Implementation restriction: cannot match $kind", tree.srcPos)

tests/neg-macros/i19941.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg-macros/i19941.scala:7:14 ---------------------------------------------------------------------------
2+
7 | case '{ ${hd *: tl} : *:[Int, EmptyTuple] } => '{ ??? } // error
3+
| ^^^^^^^^
4+
| Splice pattern must match an Expr[...]

tests/neg-macros/i19941.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.quoted.*
2+
3+
inline def expandMacro(inline from: Tuple): Any = ${ expandMacroImpl }
4+
5+
def expandMacroImpl(using Quotes): Expr[?] =
6+
'{ 1 *: EmptyTuple } match
7+
case '{ ${hd *: tl} : *:[Int, EmptyTuple] } => '{ ??? } // error

tests/pos-macros/quotedPatterns-4.scala renamed to tests/neg-macros/quotedPatterns-4.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ object Test {
33
def impl(receiver: Expr[StringContext])(using qctx: scala.quoted.Quotes) = {
44
import quotes.reflect.Repeated
55
receiver match {
6-
case '{ StringContext(${Repeated(parts, tpt)}*) } => // now OK
6+
case '{ StringContext(${Repeated(parts, tpt)}*) } => // error: Repeated is not an Expr pattern
77
}
88
}
99
}

0 commit comments

Comments
 (0)