Skip to content

Commit a97974c

Browse files
authored
Fix #21721: make case TypeBlock(_, _) not match non-type Block (#21722)
`TypeBlock`s are represented as normal `Blocks` in the Quotes API's implementation. The current `TypeTest` for `TypeBlock` is exactly the same as the `TypeTest` for `Block`, which means that `case TypeBlock(_, _)` "matches" every block. The implementation of `unapply` on `TypeBlockModule`, however, gives back `(List[TypeDef], TypeTree)`. It constructs the `List[TypeDef]` by mapping over every statement of the block, trying to turn it into a `TypeDef` by using a match with the pattern ```scala case alias: TypeDef => alias ``` This seems fine since `TypeBlock`s are supposed to be just a list of `TypeDefs` followed by a type as the last expression. Since the `TypeTest` matches any `Block` and not only `Blocks` that are `TypeBlocks`, the statements can be anything, not just `TypeDef`s, which lets the whole `case TypeBlock(_, _)` pattern die with a `MatchError`. This commit fixes the problem by making the `TypeTest` check whether the `Block` is a type (which in turns checks whether the `Block`s expression is a type) Closes #21721
2 parents 86b59aa + 147f562 commit a97974c

File tree

3 files changed

+18
-1
lines changed

3 files changed

+18
-1
lines changed

Diff for: compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1413,7 +1413,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
14131413

14141414
object TypeBlockTypeTest extends TypeTest[Tree, TypeBlock]:
14151415
def unapply(x: Tree): Option[TypeBlock & x.type] = x match
1416-
case tpt: (tpd.Block & x.type) => Some(tpt)
1416+
case tpt: (tpd.Block & x.type) if x.isType => Some(tpt)
14171417
case _ => None
14181418
end TypeBlockTypeTest
14191419

Diff for: tests/pos/i21721/Macro.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import quoted.*
2+
3+
object Macro:
4+
inline def impl(inline expr: Any): Any =
5+
${implImpl('expr)}
6+
7+
def implImpl(expr: Expr[Any])(using q: Quotes): Expr[Any] =
8+
import q.reflect.*
9+
expr.asTerm.asInstanceOf[Inlined].body match
10+
// this should not fail with a MatchError
11+
case TypeBlock(_, _) => '{ "TypeBlock" }
12+
case _ => '{ "Nothing" }

Diff for: tests/pos/i21721/Test.scala

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test:
2+
// give a Block(...) to the macro
3+
Macro.impl:
4+
val a = 3
5+
a

0 commit comments

Comments
 (0)