-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Labels
area:metaprogramming:reflectionIssues related to the quotes reflection APIIssues related to the quotes reflection APIitype:bug
Description
Compiler version
3.0.2
Minimized code
File 1:
package bug
import scala.quoted.*
object Macros { inline def mk[T]: T = ${ MacroImpl.mk[T] } }
object MacroImpl { def mk[T](using Quotes, Type[T]): Expr[T] = new Maker[T].make }
class Maker[T](using Quotes, Type[T]) {
import quotes.reflect.*
def make: Expr[T] = new TreeMap {
override def transformTerm(tree: Term)(owner: Symbol): Term = {
tree match {
case Block(stats, Typed(expr, tpt)) =>
Block.copy(tree)(transformStats(stats)(owner), Typed(expr, TypeTree.of[T]))
case other => super.transformTerm(tree)(owner)
}
}
override def transformStatement(tree: Statement)(owner: Symbol): Statement = {
tree match {
case c @ ClassDef(name, cstr, lsel, self, body) =>
ClassDef.copy(c)(name, cstr, lsel :+ TypeTree.of[T], self, body)
case other => super.transformStatement(tree)(owner)
}
}
}.transformTree('{ new {} }.asTerm)(Symbol.spliceOwner).asExprOf[T]
}File 2:
package bug
import Macros._
trait Foo {}
object M extends App {
val x = mk[Foo]
}Output
[info] running bug.M
[error] (run-main-0) java.lang.ExceptionInInitializerError
[error] java.lang.ExceptionInInitializerError
[error] at java.base/java.lang.J9VMInternals.ensureError(J9VMInternals.java:184)
[error] at java.base/java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:173)
[error] at bug.M.main(Main.scala)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[error] Caused by: java.lang.ClassCastException: bug.M$$anon$1 incompatible with bug.Foo
[error] at bug.M$.<clinit>(Main.scala:10)
[error] at bug.M.main(Main.scala)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:566)Expectation
My expectation was that I would be able to use this approach to build some stub objects for various traits -- the expr tree certainly looks like what I was hoping for -
{
final class $anon() extends bug.Foo
(new $anon(): bug.Foo)
}
- however it didn't. This is quite possibly not a bug and simply a case of me abusing the API to try to do what was never intended, but it had the feel of one. Attempting to add new statements to the body in a ClassDef.copy call also caused some additional failures, but I've excluded that from this example to keep things more minimal, and in case this isn't a bug but a misunderstanding of the feature.
Metadata
Metadata
Assignees
Labels
area:metaprogramming:reflectionIssues related to the quotes reflection APIIssues related to the quotes reflection APIitype:bug