Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Summoning a FromExpr in a macro is failing #16726

Unanswered
hmf asked this question in Metaprogramming
Discussion options

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. (削除ここまで)

You must be logged in to vote

Replies: 0 comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
1 participant

AltStyle によって変換されたページ (->オリジナル) /