From a7ed132d0d47b4ec8518af5e9da6e58f40cbe677 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Mon, 11 Mar 2019 17:55:11 +0100 Subject: [PATCH] Fix #6048: set missing position in value class rewiring (thanks @nicolasstucki) --- .../dotc/transform/VCInlineMethods.scala | 2 +- .../reflect-select-value-class/assert_1.scala | 47 +++++++++++++++++++ .../reflect-select-value-class/test_2.scala | 11 +++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/run-with-compiler/reflect-select-value-class/assert_1.scala create mode 100644 tests/run-with-compiler/reflect-select-value-class/test_2.scala diff --git a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala index 7f5097fd5d27..b15acb4864b4 100644 --- a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala @@ -92,7 +92,7 @@ class VCInlineMethods extends MiniPhase with IdentityDenotTransformer { tree // The rewiring will be handled by a fully-applied parent node case _ => if (isMethodWithExtension(tree.symbol)) - rewire(tree).ensureConforms(tree.tpe) + rewire(tree).ensureConforms(tree.tpe).withSpan(tree.span) else tree } diff --git a/tests/run-with-compiler/reflect-select-value-class/assert_1.scala b/tests/run-with-compiler/reflect-select-value-class/assert_1.scala new file mode 100644 index 000000000000..1a34880b00db --- /dev/null +++ b/tests/run-with-compiler/reflect-select-value-class/assert_1.scala @@ -0,0 +1,47 @@ +import scala.quoted._ +import scala.tasty._ + +object scalatest { + + inline def assert(condition: => Boolean): Unit = ${ assertImpl('condition, '{""}) } + + def assertImpl(cond: Expr[Boolean], clue: Expr[Any])(implicit refl: Reflection): Expr[Unit] = { + import refl._ + import util._ + import quoted.Toolbox.Default._ + + def isImplicitMethodType(tp: Type): Boolean = + Type.IsMethodType.unapply(tp).flatMap(tp => if tp.isImplicit then Some(true) else None).nonEmpty + + cond.unseal.underlyingArgument match { + case t @ Term.Apply(Term.Select(lhs, op), rhs :: Nil) => + let(lhs) { left => + let(rhs) { right => + val app = Term.Select.overloaded(left, op, Nil, right :: Nil) + let(app) { result => + val l = left.seal[Any] + val r = right.seal[Any] + val b = result.seal[Boolean] + val code = '{ scala.Predef.assert($b) } + code.unseal + } + } + }.seal[Unit] + case Term.Apply(f @ Term.Apply(Term.Select(Term.Apply(qual, lhs :: Nil), op), rhs :: Nil), implicits) + if isImplicitMethodType(f.tpe) => + let(lhs) { left => + let(rhs) { right => + val app = Term.Select.overloaded(Term.Apply(qual, left :: Nil), op, Nil, right :: Nil) + let(Term.Apply(app, implicits)) { result => + val l = left.seal[Any] + val r = right.seal[Any] + val b = result.seal[Boolean] + val code = '{ scala.Predef.assert($b) } + code.unseal + } + } + }.seal[Unit] + } + } + +} diff --git a/tests/run-with-compiler/reflect-select-value-class/test_2.scala b/tests/run-with-compiler/reflect-select-value-class/test_2.scala new file mode 100644 index 000000000000..f1fa2581213d --- /dev/null +++ b/tests/run-with-compiler/reflect-select-value-class/test_2.scala @@ -0,0 +1,11 @@ +object Test { + import scalatest._ + + implicit class AnyOps(x: String) extends AnyVal { + def *(y: String): String = x + ", " + y + } + + def main(args: Array[String]): Unit = { + assert(("hello" * "world") == "hello, world") + } +}