Skip to content

DefDef.copy does not allow changing anything other than function body #7626

Closed
@fhackett

Description

@fhackett

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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions