From 0e77c82c980b6c61846e6ad94f226c6367c85c7f Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 21 Mar 2022 14:16:21 +0100 Subject: [PATCH] Handle this prefix in objects (in quote patterns) Fix #14536 --- .../quoted/runtime/impl/QuoteMatcher.scala | 2 + tests/pos-macros/i14536/Macro_1.scala | 11 +++++ tests/pos-macros/i14536/Test_2.scala | 2 + tests/pos-macros/i14536b/Macro_1.scala | 48 +++++++++++++++++++ tests/pos-macros/i14536b/Test_2.scala | 1 + 5 files changed, 64 insertions(+) create mode 100644 tests/pos-macros/i14536/Macro_1.scala create mode 100644 tests/pos-macros/i14536/Test_2.scala create mode 100644 tests/pos-macros/i14536b/Macro_1.scala create mode 100644 tests/pos-macros/i14536b/Test_2.scala diff --git a/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala b/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala index daa73c0481da..06a064860ac4 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala @@ -247,6 +247,8 @@ object QuoteMatcher { case ref: Ident => ref.tpe match case TermRef(qual: TermRef, _) => tpd.ref(qual) =?= qual2 + case TermRef(qual: ThisType, _) if qual.classSymbol.is(Module, butNot = Package) => + tpd.ref(qual.classSymbol.companionModule) =?= qual2 case _ => matched /* Match reference */ case _: Ident if symbolMatch(scrutinee, pattern) => matched diff --git a/tests/pos-macros/i14536/Macro_1.scala b/tests/pos-macros/i14536/Macro_1.scala new file mode 100644 index 000000000000..660b8606dae9 --- /dev/null +++ b/tests/pos-macros/i14536/Macro_1.scala @@ -0,0 +1,11 @@ +import quoted.* + +inline def isFoo(inline x: Any): Boolean = ${ isFooImpl('x) } + +def isFooImpl(x: Expr[Any])(using Quotes): Expr[Boolean] = + x match + case '{ ($p: Parent).foo } => '{ true } + case _ => '{ false } + +trait Parent: + def foo = 0 diff --git a/tests/pos-macros/i14536/Test_2.scala b/tests/pos-macros/i14536/Test_2.scala new file mode 100644 index 000000000000..971338b0b0bd --- /dev/null +++ b/tests/pos-macros/i14536/Test_2.scala @@ -0,0 +1,2 @@ +object Child extends Parent: + def bar = isFoo(foo) diff --git a/tests/pos-macros/i14536b/Macro_1.scala b/tests/pos-macros/i14536b/Macro_1.scala new file mode 100644 index 000000000000..332c6ca77595 --- /dev/null +++ b/tests/pos-macros/i14536b/Macro_1.scala @@ -0,0 +1,48 @@ +import quoted.* +import scala.compiletime.testing.{typeChecks, typeCheckErrors} +import scala.compiletime.testing.{Error, ErrorKind} + +transparent inline def assertCompiles(inline code: String): Unit = + ${ assertCompilesImpl('code, '{typeCheckErrors(code)}) } + +given FromExpr[ErrorKind] with { + def unapply(expr: Expr[ErrorKind])(using Quotes) = expr match { + case '{ ErrorKind.Parser } => Some(ErrorKind.Parser) + case '{ ErrorKind.Typer } => Some(ErrorKind.Typer) + case _ => None + } +} + +given FromExpr[Error] with { + def unapply(expr: Expr[Error])(using Quotes) = expr match { + case '{ Error(${Expr(msg)}, ${Expr(line)}, ${Expr(col)}, ${Expr(kind)}) } => Some(Error(msg, line, col, kind)) + case _ => None + } +} + +private def assertCompilesImpl(self: Expr[_], typeChecked: Expr[List[Error]])(using Quotes): Expr[Unit] = { + import quotes.reflect._ + + def checkCompile(code: String): Expr[Unit] = { + // For some reason `typeChecked.valueOrError` is failing here, so instead we grab + // the varargs argument to List.apply and use that to extract the list of errors + val errors = typeChecked.asTerm.underlyingArgument match { + case Apply(TypeApply(Select(Ident("List"), "apply"), _), List(seq)) => + seq.asExprOf[Seq[Error]].valueOrError.toList + } + + '{} + } + + self.asTerm.underlyingArgument match { + + case Literal(StringConstant(code)) => + checkCompile(code.toString) + + case Apply(Select(_, "stripMargin"), List(Literal(StringConstant(code)))) => + checkCompile(code.toString.stripMargin) + + case _ => + report.throwError("The 'assertCompiles' function only works with String literals.") + } +} \ No newline at end of file diff --git a/tests/pos-macros/i14536b/Test_2.scala b/tests/pos-macros/i14536b/Test_2.scala new file mode 100644 index 000000000000..25d2f97b12ec --- /dev/null +++ b/tests/pos-macros/i14536b/Test_2.scala @@ -0,0 +1 @@ +def test = assertCompiles("val a: String = 2")