-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Summoning a FromExpr in a macro is failing #16726
-
This question follows from this issue that I incorrectly filed as a bug. More concretely I want to access the values of a Tuple and an HList of mine. Here are 2 examples from the answer of the issue I refer to above (my use case is the second one):
def getTuple2_1[T <: Tuple : Type : FromExpr](q: Expr[T])(using Quotes): Any = q.value // Uses the provided `FromExpr[T]` def getTuple2_2[T1 : Type: FromExpr, T2: Type : FromExpr](q: Expr[Tuple2[T1,T2]])(using Quotes): Any = q.value // Uses Tuple2FromExpr[T1, T2] which requires `FromExpr[T1]` and `FromExpr[T2]`
The problem is that I think that the only way to get the correct type class is to use Expr.summon. I have been struggling for some time now and cannot seem to solve this. Here is my test case (apologies for the length, but most of it are printouts to show later):
inline def testFromExpr0T[K,V](inline l: Tuple2[K,V], k: K): Any = ${ testFromExprImpl0T('l, 'k) } def testFromExprImpl0T[K:Type, V:Type](x: Expr[Tuple2[K,V]], k: Expr[K])(using Quotes): Expr[Option[V]] = import scala.quoted.* val kv = Expr.summon[FromExpr[K]] println(s"kv.isDefined = ${kv.isDefined}") val vk = Expr.summon[FromExpr[V]] println(s"vk.isDefined = ${vk.isDefined}") val tt = Expr.summon[FromExpr[Tuple2[K,V]]] println(s"tt.isDefined = ${tt.isDefined}") println(s"x.show = ${x.show}") import quotes.reflect.* val targetTpe = TypeRepr.of[FromExpr[Tuple2[K,V]]] println(s"targetTpe.show = ${targetTpe.show}") Implicits.search(targetTpe.dealias) match case iss: ImplicitSearchSuccess => println("Success") case isf: ImplicitSearchFailure => println("Fail") import quotes.reflect.report match case (Some(t), Some(c)) => val key = '{$x._1} val kc = '{$key == $k} if kc.valueOrAbort then '{Some($x._2)} else '{None} case _ => report.errorAndAbort("Expr.summon failed to match")
In another file I use:
val c2 = icollectionx.From.testFromExpr0T((1, 1), 1)
And I get the following output:
info] compiling 1 Scala source to /home/hmf/VSCodeProjects/sploty/out/meta/test/compile.dest/classes ... kv.isDefined = true vk.isDefined = true tt.isDefined = false x.show = scala.Tuple2.apply[scala.Int, scala.Int](1, 1) targetTpe.show = scala.quoted.FromExpr[scala.Tuple2[scala.Int, scala.Int]] Fail [error] -- Error: /home/hmf/VSCodeProjects/sploty/meta/test/src/icollection/IMapSpec.scala:207:45 [error] 207 | val c2 = icollectionx.From.testFromExpr0T((1, 1), 1) [error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [error] | Expr.summon failed to match
One can see from the printouts that the Tuple's case class cannot be found. Why is that?
I have asked questions in the Scala user's Discourse forum and the Discord Scalameta chat with no luck. I have scoured the Internet and the dotty docs and cannot figure out what I am doing wrong. In particular I found Adam Warski's Scala 3 macros tips & tricks (see related question in this forum), which seems to indicate that I am not too far from the solution.
EDIT:
(削除) Strangely enough I cannot get his example to work. (削除ここまで) Here is the code I used (slight change to to get it to compile):
trait MyTypeclass[T] given MyTypeclass[String] with {} def myMethod[T](using MyTypeclass[T]): Unit = () inline def test[T]: Unit = ${testImpl[T]} def testImpl[T: Type](using Quotes): Expr[Unit] = { import quotes.reflect.* // '{myMethod[T]} // (1) // or: '{myMethod[T](using ${Expr.summon[MyTypeclass[T]].get})} // (2) '{()}
And in another file, I use:
icollectionx.From.test[String]
And compilation succeeds.
Can anyone advise me on what to try next?
TIA
(削除) With the above I get (削除ここまで):
[error] -- Error: /home/hmf/VSCodeProjects/sploty/meta/src/icollection/FromExpr0.scala:565:17 [error] 565 | '{myMethod[T](${Expr.summon[MyTypeclass[T]].get})} // (2) [error] | ^ [error] |No given instance of type icollectionx.From.MyTypeclass[T] was found for parameter x$1 of method myMethod in object From
(削除) Seems like the same type of problem. The article is from May of 2021, so I wonder if something has changed since then. (削除ここまで)
Beta Was this translation helpful? Give feedback.