Open joan38 opened 1 month ago
Sounds like it's the same with summonInline
instead of Expr.summon
Also another thing I experimented with to make it even simplier:
import scala.quoted.*
import types.Hello
inline def summonHello: Hello = ${ summonHelloImpl }
private def summonHelloImpl(using Quotes): Expr[Hello] =
import quotes.reflect.*
Symbol.requiredModule("types").typeMember("Hello").typeRef.asType match
case '[t] => Expr.summon[t].getOrElse(report.errorAndAbort(s"Cannot summon a value of type ${TypeRepr.of[Hello]}")).asExprOf[Hello]
and:
object types:
opaque type Hello = String
def Hello(s: String): Hello = s
import types.*
@main def run =
given Hello = Hello("dummy")
println(summonHello)
Which fails with:
% ./scala -Xcheck-macros .
Compiling project (Scala 3.4.2, JVM (17))
[error] ./run.scala:8:11
[error] Cannot summon a value of type TypeRef(TermRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <root>)),module class <empty>)),types),Hello)
[error] println(summonHello)
[error] ^^^^^^^^^^^
Error compiling project (Scala 3.4.2, JVM (17))
seems pretty clearly broken, thanks for the minimisation
Thanks. If I change the line:
case '[t] => Expr.summon[t].getOrElse(report.errorAndAbort(s"Cannot summon a value of type ${TypeRepr.of[Hello]}")).asExprOf[Hello]
by
case '[t] => Expr.summon[t].getOrElse(report.errorAndAbort(s"Cannot summon a value of type ${TypeRepr.of[t]}")).asExprOf[Hello]
then it prints:
Cannot summon a value of type TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),class String)
So that means it looks for a String
instead of Hello?
Here another conclusion:
import scala.quoted.*
import types.Hello
inline def summonHello: Hello = ${ summonHelloImpl }
private def summonHelloImpl(using Quotes): Expr[Hello] =
import quotes.reflect.*
val tpe = Symbol.requiredPackage("types").typeMember("Hello").typeRef
val value = Implicits.search(tpe) match
case iss: ImplicitSearchSuccess => Some(iss.tree.asExprOf[Hello])
case isf: ImplicitSearchFailure => None
value.getOrElse(report.errorAndAbort(s"Cannot summon a value of type ${tpe.typeSymbol.fullName} - ${tpe}"))
and:
package types:
opaque type Hello = String
object Hello:
def apply(s: String): Hello = s
given Hello = Hello("dummy") // Some instance in the companion object
import types.*
@main def run =
// import Hello.given // Uncomment this line and it works
println(summonHello)
Fails to resolve the implicit but with an import of the givens from the companion object, it works. So that means it's not able to resolve givens from companion objects of opaque types.
Also:
val tpe = Symbol.requiredPackage("types").typeMember("MyCaseClass").typeRef
println(tpe.typeSymbol.companionModule.exists.toString)
Would return true
if there is a case class MyCaseClass
declared in the package types
.
But false
for an opaque type
.
I wonder why?
BTW I'm happy to look into this issue but not sure where to start from.
I'm actually surprised it does not work because it sounds like Expr.summon
plugs into the compiler's code
Compiler version
Issue reproduced in
3.4.2
and3.5.0-RC4
.Minimized code
Please check the min repro repo https://github.com/joan38/macro-summon-bug
Output
Gives only
MyCaseClass
instances (not sure why 3 times but that's a different issue):Expectation
Expr.summon[t]
should resolve opaque type too:Thanks