-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Open
Labels
itype:bugstat:needs triageEvery issue needs to have an "area" and "itype" labelEvery issue needs to have an "area" and "itype" label
Description
Scala 3.8.0-RC1
The macro below fails compiling on ScalaJs. Compiles and run ok on JVM.
scala-cli --cli-version 1.10.1 Client.scala ClientMacro.scala
Compiles and runs ok
scala-cli --cli-version 1.10.1 Client.scala ClientMacro.scala --js
Fails compilation with error:
Error: Cannot resolve delambdafy target method $anonfun at Client.scala:22
Note, both JVM and ScalaJs compile and run on Scala 3.7.4 by adding //> using options -experimental on Client.scala
File Client.scala
//> using scala 3.8.0-RC1
//> using jvm temurin:25
//> using js-version 1.20.1
trait ApiRun:
def runInt(a: Int): String
object ClientRunner:
def main(args: Array[String]): Unit =
val r = Client().client[ApiRun]
println(r.runInt(10))
class Client():
val exec: Runner = new Runner()
inline def client[API]: API = ${
ClientMacro.impl[API, Runner]('exec)
}
class Runner():
def run[IL, RL](arg: IL, lambda: IL => RL): RL = lambda(arg)File ClientMacro.scala
object ClientMacro:
import scala.quoted.*
def impl[API: Type, RUNNER: Type](runnerImpl: Expr[RUNNER])(using Quotes): Expr[API] = implBase[API, RUNNER](runnerImpl)
private def implBase[API: Type, RUNNER: Type](runnerImpl: Expr[RUNNER])(using Quotes): Expr[API] =
import quotes.reflect.*
val methods = TypeRepr.of[API].typeSymbol.methodMembers.filter(s => s.flags.is(Flags.Deferred))
def decls(cls: Symbol): List[Symbol] = methods.map { method =>
val methodType = TypeRepr.of[API].memberType(method)
Symbol.newMethod(cls, method.name, methodType, flags = Flags.EmptyFlags, privateWithin = method.privateWithin.fold(Symbol.noSymbol)(_.typeSymbol))
}
val parents = List(TypeTree.of[Object], TypeTree.of[API])
val cls = Symbol.newClass(Symbol.spliceOwner, "Anon", parents.map(_.tpe), decls, selfType = None)
val result = ValDef.let(Symbol.spliceOwner, runnerImpl.asTerm) { runnerRef =>
val body = (cls.declaredMethods).map { method =>
DefDef(
method,
args =>
val runnerImplSymb = TypeRepr.of[RUNNER].typeSymbol
val inputType = TypeTree.of[Int]
val returnType = TypeTree.of[String]
val lambda = '{ (v: Int) => s"-$v-" }
Some(
Apply(
TypeApply(
Select(runnerRef, runnerImplSymb.declaredMethod("run").head),
List(inputType, returnType)
),
List(args.flatten.head.asExpr.asTerm, lambda.asTerm)
))
)
}
val clsDef = ClassDef(cls, parents, body = body)
val newCls = Typed(
Apply(
Select(New(TypeIdent(cls)), cls.primaryConstructor),
Nil
),
TypeTree.of[API]
)
Block(List(clsDef), newCls)
}
println(result.show)
result.asExprOf[API]Metadata
Metadata
Assignees
Labels
itype:bugstat:needs triageEvery issue needs to have an "area" and "itype" labelEvery issue needs to have an "area" and "itype" label