Skip to content

Macro can invoke constructor of a case object #17545

Closed
@arainko

Description

@arainko

Compiler version

3.2.2, 3.3.0-RC6

Minimized code

// InvokeConstructor.scala
//> using scala "3.3.0-RC6"

import scala.quoted.* 

object InvokeConstructor {
  inline def apply[A] = ${ constructorMacro[A] }

  def constructorMacro[A: Type](using Quotes) = {
    import quotes.reflect.*
    val tpe = TypeRepr.of[A]
    New(Inferred(tpe)).select(tpe.typeSymbol.primaryConstructor).appliedToArgs(Nil).asExprOf[A]
  }
}

Variant 1 - a local case object, which doesn't result in a runtime failure but we actually get a new instance of a singleton

// usage.scala
@main def main = {
  case object Whatever

  val whatever: Whatever.type = InvokeConstructor[Whatever.type]
  println(whatever eq Whatever) // evaluates to false
  println(whatever == Whatever) // evaluates to false
}

Variant 2 - a toplevel case object, this results in a runtime error

case object Whatever

/*
fails at runtime:
Exception in thread "main" java.lang.IllegalAccessError: class Usage$package$ tried to access private method 'void Whatever$.<init>()' (Usage$package$ and Whatever$ are in unnamed module of loader 'app')
        at Usage$package$.main(Usage.scala:5)
        at main.main(Usage.scala:3)
*/
@main def main = {

  val whatever: Whatever.type = InvokeConstructor[Whatever.type]
}

Expectation

Compilation failure.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions