-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Milestone
Description
Compiler version
3.0.0-RC1
also on 3.0.0-RC2-bin-20210227-07d9dd2-NIGHTLY
Minimized code
Create some kind of typeclass with an implementation inside of a class-instance
trait MyEncoder[T] {
def encode(t: T): String
}
class MyContext {
given intEncoder: MyEncoder[Int] = new MyEncoder[Int] { def encode(t: Int) = s"${t}" }
}
Then make a macro that summons this using Expr.summon.
object MyMacro {
inline def getAndEncode[T](t: T): String = ${ getAndEncodeImpl('t) }
def getAndEncodeImpl[T: Type](t: Expr[T])(using qctx: Quotes): Expr[String] = {
import qctx.reflect._
val enc =
Expr.summon[MyEncoder[T]] match
case Some(enc) => enc
case None => report.throwError("Can't find encoder")
'{ $enc.encode($t) }
}
}
Then import the context and use the macro:
def doEncoding: Unit = {
val ctx = new MyContext()
import ctx.{*, given}
println(MyMacro.getAndEncode(123))
}
Output
Compilation fails, report error case "Can't find encoder" is hit.
[error] 15 | println(MyMacro.getAndEncode(123))
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^
[error] | Can't find encoder
Expectation
Compile should work and the given should be correctly summoned.
Note that if instead of using a macro I use a regular method, it will work:
def encodeIt[T](t: T)(using enc: MyEncoder[T]) = enc.encode(t)
def doEncoding: Unit = {
val ctx = new MyContext()
import ctx.{*, given}
println(encodeIt(123))
}
Why the discrepancy?
Also, note that if you declare the given directly in the doEncoding method it will work:
def doEncoding: Unit = {
val ctx = new MyContext()
given intEncoder: MyEncoder[Int] = new MyEncoder[Int] { def encode(t: Int) = s"${t}" }
println(MyMacro.getAndEncode(123))
}
Why the discrepancy?
Code
Full code sample is available here:
https://github.com/deusaquilus/expr_summon_issue
Metadata
Metadata
Assignees
Labels
No labels