From 147f5622f822d5084fe03420cb0e2a6d593856ff Mon Sep 17 00:00:00 2001 From: Felix Herrmann Date: Mon, 7 Oct 2024 18:55:42 +0200 Subject: [PATCH] Fix #21721: make case TypeBlock(_, _) not match non-type Block TypeBlocks are represented as normal Blocks in the Quotes API. 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, turning it into a TypeDef by using a match with the pattern case alias: TypeDef => alias Since the TypeTest matches any Block and not only Blocks that are TypeBlocks, the statemnts can be anything, not just TypeDefs, which lets the whole case TypeBlock(_, _) pattern fail 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 blocks expression is a type) --- .../src/scala/quoted/runtime/impl/QuotesImpl.scala | 2 +- tests/pos/i21721/Macro.scala | 12 ++++++++++++ tests/pos/i21721/Test.scala | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i21721/Macro.scala create mode 100644 tests/pos/i21721/Test.scala diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index ce8d19aae46a..237ab8448fd4 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -1413,7 +1413,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler object TypeBlockTypeTest extends TypeTest[Tree, TypeBlock]: def unapply(x: Tree): Option[TypeBlock & x.type] = x match - case tpt: (tpd.Block & x.type) => Some(tpt) + case tpt: (tpd.Block & x.type) if x.isType => Some(tpt) case _ => None end TypeBlockTypeTest diff --git a/tests/pos/i21721/Macro.scala b/tests/pos/i21721/Macro.scala new file mode 100644 index 000000000000..dfdbff6a659b --- /dev/null +++ b/tests/pos/i21721/Macro.scala @@ -0,0 +1,12 @@ +import quoted.* + +object Macro: + inline def impl(inline expr: Any): Any = + ${implImpl('expr)} + + def implImpl(expr: Expr[Any])(using q: Quotes): Expr[Any] = + import q.reflect.* + expr.asTerm.asInstanceOf[Inlined].body match + // this should not fail with a MatchError + case TypeBlock(_, _) => '{ "TypeBlock" } + case _ => '{ "Nothing" } diff --git a/tests/pos/i21721/Test.scala b/tests/pos/i21721/Test.scala new file mode 100644 index 000000000000..ebe91bae9ef4 --- /dev/null +++ b/tests/pos/i21721/Test.scala @@ -0,0 +1,5 @@ +object Test: + // give a Block(...) to the macro + Macro.impl: + val a = 3 + a