Skip to content

Commit f832965

Browse files
xeno-byadriaanm
authored andcommitted
blackbox restriction #4: can't customize pattern matching
When an application of a blackbox macro is used as an extractor in a pattern match, it triggers an unconditional compiler error, preventing customizations of pattern matching implemented with macros.
1 parent 0d5c2f7 commit f832965

File tree

8 files changed

+62
-4
lines changed

8 files changed

+62
-4
lines changed

src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,10 @@ trait PatternTypers {
409409

410410
if (fun1.tpe.isErroneous)
411411
duplErrTree
412-
else if (unapplyMethod.isMacro && !fun1.isInstanceOf[Apply])
413-
duplErrorTree(WrongShapeExtractorExpansion(tree))
414-
else
412+
else if (unapplyMethod.isMacro && !fun1.isInstanceOf[Apply]) {
413+
if (isBlackbox(unapplyMethod)) duplErrorTree(BlackboxExtractorExpansion(tree))
414+
else duplErrorTree(WrongShapeExtractorExpansion(tree))
415+
} else
415416
makeTypedUnApply()
416417
}
417418

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Test_2.scala:3: error: extractor macros can only be whitebox
2+
case Extractor(x) => println(x)
3+
^
4+
one error found
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import scala.reflect.macros.BlackboxContext
2+
import language.experimental.macros
3+
4+
object Extractor {
5+
def unapply(x: Int) = macro Macros.unapplyImpl
6+
}
7+
8+
object Macros {
9+
def unapplyImpl(c: BlackboxContext)(x: c.Tree) = {
10+
import c.universe._
11+
q"""
12+
new {
13+
class Match(x: Int) {
14+
def isEmpty = false
15+
def get = x
16+
}
17+
def unapply(x: Int) = new Match(x)
18+
}.unapply($x)
19+
"""
20+
}
21+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test extends App {
2+
42 match {
3+
case Extractor(x) => println(x)
4+
}
5+
}

test/files/neg/t5903d.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Test_2.scala:4: error: extractor macros can only expand into extractor calls
1+
Test_2.scala:4: error: extractor macros can only be whitebox
22
case t"$x" => println(x)
33
^
44
one error found
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
42
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import scala.reflect.macros.WhiteboxContext
2+
import language.experimental.macros
3+
4+
object Extractor {
5+
def unapply(x: Int) = macro Macros.unapplyImpl
6+
}
7+
8+
object Macros {
9+
def unapplyImpl(c: WhiteboxContext)(x: c.Tree) = {
10+
import c.universe._
11+
q"""
12+
new {
13+
class Match(x: Int) {
14+
def isEmpty = false
15+
def get = x
16+
}
17+
def unapply(x: Int) = new Match(x)
18+
}.unapply($x)
19+
"""
20+
}
21+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test extends App {
2+
42 match {
3+
case Extractor(x) => println(x)
4+
}
5+
}

0 commit comments

Comments
 (0)