-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
minimized code
import quoted._
def fooImpl(given qctx : QuoteContext) : Expr[Int] = {
import qctx.tasty.{_,given}
val fn = '{
def shouldBeHidden = ???
}.unseal match {
case Inlined(_, _, Block(List(theDefDef), _)) =>
DefDef.copy(theDefDef)("realName", Nil, Nil, '[Int].unseal, Some('{1}.unseal))
}
Block(List(fn), Ref(fn.symbol)).seal.asInstanceOf[Expr[Int]]
}
inline def foo = ${fooImpl}expectation
Referencing foo should produce the value 1 by generating both the definition of and a call to an inner function named realName that returns the corresponding value.
Instead, we get a ClassCastError at runtime because Dotty's codegen keeps using shouldBeHidden's return type of Nothing instead of the copy's updated Int type. Inspecting the bytecode shows that the name of the generated method is shouldBeHidden, not realName.
Similarly, attempting to change anything else (other than the definition body) about shouldBeHidden has little or no effect, leading to either compiler errors or incorrect codegen.
DefDef.copy seems like the easiest way to generate computed-arity (local) functions, so it's unfortunate that transforming things other than the function body does not work.