-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Labels
Description
The following macro throws exception at expansion time. The code that is culprit is the 2nd case where we used Term.Select.copy
.
The usage of the method Term.Select.copy
is a walkaround because we lack proper constructors for select (#5567 ).
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 Term.Apply(sel @ Term.Select(lhs, op), rhs :: Nil) =>
val Term.IsSelect(select) = sel
val cond = Term.Apply(Term.Select.copy(select)(lhs, ">"), rhs :: Nil).seal[Boolean]
'{ scala.Predef.assert(~cond) }
case Term.Apply(f @ Term.Apply(Term.IsSelect(sel @ Term.Select(Term.Apply(qual, lhs :: Nil), op)), rhs :: Nil), implicits)
if isImplicitMethodType(f.tpe) =>
let(lhs) { left =>
let(rhs) { right =>
let(Term.Apply(Term.Apply(Term.Select.copy(sel)(Term.Apply(qual, left :: Nil), op), right :: Nil), implicits)) { result =>
val b = result.seal[Boolean]
val code = '{ scala.Predef.assert(~b) }
code.unseal
}
}
}.seal[Unit]
case _ =>
'{ scala.Predef.assert(~cond) }
}
}
inline def thisLineNumber = ~thisLineNumberImpl
def thisLineNumberImpl(implicit refl: Reflection): Expr[Int] = {
import refl._
refl.rootPosition.startLine.toExpr
}
}
object Test {
import scalatest._
trait EqInt
implicit val eq: EqInt = new EqInt {}
implicit class IntOps(x: Int) {
def === (y: Int)(implicit c: EqInt) = x == y
}
def main(args: Array[String]): Unit = {
val a: Int = 100
assert(a === 5)
}
}