-
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)
}
}