diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/QuotedOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/QuotedOpsImpl.scala index 8d7eb49c808d..ac6a0ddb033b 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/QuotedOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/QuotedOpsImpl.scala @@ -1,9 +1,6 @@ package dotty.tools.dotc.tastyreflect -import dotty.tools.dotc.core.Contexts.FreshContext import dotty.tools.dotc.core.quoted.PickledQuotes -import dotty.tools.dotc.reporting.Reporter -import dotty.tools.dotc.reporting.diagnostic.MessageContainer trait QuotedOpsImpl extends scala.tasty.reflect.QuotedOps with CoreImpl { @@ -18,30 +15,17 @@ trait QuotedOpsImpl extends scala.tasty.reflect.QuotedOps with CoreImpl { def TermToQuoteDeco(term: Term): TermToQuotedAPI = new TermToQuotedAPI { def seal[T: scala.quoted.Type](implicit ctx: Context): scala.quoted.Expr[T] = { - typecheck(ctx) + typecheck() new scala.quoted.Exprs.TastyTreeExpr(term).asInstanceOf[scala.quoted.Expr[T]] } - private def typecheck[T: scala.quoted.Type](ctx: Context): Unit = { - implicit val ctx0: FreshContext = ctx.fresh - ctx0.setTyperState(ctx0.typerState.fresh()) - ctx0.typerState.setReporter(new Reporter { - def doReport(m: MessageContainer)(implicit ctx: Context): Unit = () - }) - val tp = QuotedTypeDeco(implicitly[scala.quoted.Type[T]]).unseal - ctx0.typer.typed(term, tp.tpe) - if (ctx0.reporter.hasErrors) { - val stack = new Exception().getStackTrace - def filter(elem: StackTraceElement) = - elem.getClassName.startsWith("dotty.tools.dotc.tasty.ReflectionImpl") || - !elem.getClassName.startsWith("dotty.tools.dotc") + private def typecheck[T: scala.quoted.Type]()(implicit ctx: Context): Unit = { + val tpt = QuotedTypeDeco(implicitly[scala.quoted.Type[T]]).unseal + if (!(term.tpe <:< tpt.tpe)) { throw new scala.tasty.TastyTypecheckError( - s"""Error during tasty reflection while typing term - |term: ${term.show} - |with expected type: ${tp.tpe.show} - | - | ${stack.takeWhile(filter).mkString("\n ")} - """.stripMargin + s"""Term: ${term.show} + |did not conform to type: ${tpt.tpe.show} + |""".stripMargin ) } } diff --git a/library/src/scala/tasty/TastyTypecheckError.scala b/library/src/scala/tasty/TastyTypecheckError.scala index fc506c1ddecb..3fdeac37ae37 100644 --- a/library/src/scala/tasty/TastyTypecheckError.scala +++ b/library/src/scala/tasty/TastyTypecheckError.scala @@ -1,3 +1,3 @@ package scala.tasty -class TastyTypecheckError(msg: String) extends Throwable +class TastyTypecheckError(msg: String) extends Throwable(msg) diff --git a/tests/run-separate-compilation/i5533.check b/tests/run-separate-compilation/i5533.check new file mode 100644 index 000000000000..27ba77ddaf61 --- /dev/null +++ b/tests/run-separate-compilation/i5533.check @@ -0,0 +1 @@ +true diff --git a/tests/run-separate-compilation/i5533/Macro_1.scala b/tests/run-separate-compilation/i5533/Macro_1.scala new file mode 100644 index 000000000000..05552fcc7513 --- /dev/null +++ b/tests/run-separate-compilation/i5533/Macro_1.scala @@ -0,0 +1,20 @@ +import scala.quoted._ +import scala.tasty._ + +object scalatest { + + def f(x: Int): Boolean = false + def f(x: String): Boolean = true + + inline def assert(condition: => Boolean): Unit = ~assertImpl('(condition)) + + def assertImpl(condition: Expr[Boolean])(implicit refl: Reflection): Expr[Unit] = { + import refl._ + + val tree = condition.unseal + + val expr = tree.seal[Boolean] + + '(println(~expr)) + } +} diff --git a/tests/run-separate-compilation/i5533/Test_2.scala b/tests/run-separate-compilation/i5533/Test_2.scala new file mode 100644 index 000000000000..e982bb0fa7e9 --- /dev/null +++ b/tests/run-separate-compilation/i5533/Test_2.scala @@ -0,0 +1,9 @@ +object Test { + + def main(args: Array[String]): Unit = { + import scalatest._ + val x = "String" + assert(f("abc")) + } + +} diff --git a/tests/run-separate-compilation/i5533b.check b/tests/run-separate-compilation/i5533b.check new file mode 100644 index 000000000000..e33d1368f00f --- /dev/null +++ b/tests/run-separate-compilation/i5533b.check @@ -0,0 +1,3 @@ +String +String +() diff --git a/tests/run-separate-compilation/i5533b/Macro_1.scala b/tests/run-separate-compilation/i5533b/Macro_1.scala new file mode 100644 index 000000000000..5a5443619fb8 --- /dev/null +++ b/tests/run-separate-compilation/i5533b/Macro_1.scala @@ -0,0 +1,34 @@ +import scala.quoted._ +import scala.tasty._ + +object scalatest { + def f(x: Int): Int = x + def f(x: String): String = x + + inline def assert(condition: => Boolean): Unit = ~assertImpl('(condition)) + + def assertImpl(condition: Expr[Boolean])(implicit refl: Reflection): Expr[Unit] = { + import refl._ + import quoted.Toolbox.Default._ + + val tree = condition.unseal + def exprStr: String = condition.show + + tree.underlyingArgument match { + case Term.Apply(Term.Select(lhs, op, _), rhs :: Nil) => + val left = lhs.seal[Any] + val right = rhs.seal[Any] + op match { + case "==" => + '{ + val _left = ~left + val _right = ~right + val _result = _left == _right + println(_left) + println(_right) + scala.Predef.assert(_result) + } + } + } + } +} \ No newline at end of file diff --git a/tests/run-separate-compilation/i5533b/Test_2.scala b/tests/run-separate-compilation/i5533b/Test_2.scala new file mode 100644 index 000000000000..3d07d155ad23 --- /dev/null +++ b/tests/run-separate-compilation/i5533b/Test_2.scala @@ -0,0 +1,9 @@ +object Test { + + def main(args: Array[String]): Unit = { + import scalatest._ + val x = "String" + println(assert(f(x) == "String")) + } + +} diff --git a/tests/run-separate-compilation/i5536/Macro_1.scala b/tests/run-separate-compilation/i5536/Macro_1.scala new file mode 100644 index 000000000000..3de01d6d445f --- /dev/null +++ b/tests/run-separate-compilation/i5536/Macro_1.scala @@ -0,0 +1,29 @@ +import scala.quoted._ +import scala.tasty._ + +object scalatest { + inline def assert(condition: => Boolean): Unit = ~assertImpl('(condition)) + + def assertImpl(condition: Expr[Boolean])(implicit refl: Reflection): Expr[Unit] = { + import refl._ + import quoted.Toolbox.Default._ + + val tree = condition.unseal + def exprStr: String = condition.show + + tree.underlyingArgument match { + case Term.Apply(Term.Select(lhs, op, _), rhs :: Nil) => + val left = lhs.seal[Any] + val right = rhs.seal[Any] + op match { + case "===" => + '{ + val _left = ~left + val _right = ~right + val _result = _left == _right + scala.Predef.assert(_result) + } + } + } + } +} diff --git a/tests/run-separate-compilation/i5536/Test_2.scala b/tests/run-separate-compilation/i5536/Test_2.scala new file mode 100644 index 000000000000..671ff6044f28 --- /dev/null +++ b/tests/run-separate-compilation/i5536/Test_2.scala @@ -0,0 +1,22 @@ + +class Equalizer[L](val leftSide: L) { + def ===(literalNull: Null): Boolean = leftSide == null +} + +object Equality { + implicit def toEqualizer[T](x: T): Equalizer[T] = new Equalizer(x) +} + + +object Test { + import scalatest._ + import Equality._ + + def main(args: Array[String]): Unit = { + val x = "String" + try assert(x === null) + catch { + case _: AssertionError => // OK + } + } +}