Skip to content

Macro-generated object and class with the same name in the same scope are not considered companions #16993

Open
@pweisenburger

Description

@pweisenburger

Compiler version

3.3.1-RC1-bin-20230216-2507577-NIGHTLY

Minimized code

The following (lengthy) code just creates an object o with a private field x and a class o with a method that accesses o.x and puts all object and class definitions into the same block:

import scala.quoted.*

inline def test = ${ testImpl }

def testImpl(using Quotes) =
  import quotes.reflect.*

  val name: String = "o"
  val parents = List(TypeTree.of[Object])

  // create module

  def moddecls(cls: Symbol): List[Symbol] =
    List(Symbol.newVal(cls, "x", TypeRepr.of[Int], Flags.PrivateLocal, Symbol.noSymbol))

  val mod = Symbol.newModule(Symbol.spliceOwner, name, Flags.EmptyFlags, Flags.EmptyFlags, parents.map(_.tpe), moddecls, Symbol.noSymbol)
  val fieldSym = mod.moduleClass.declaredField("x")

  val runDef = ValDef(fieldSym, Some(Literal(IntConstant(1))))
  val modDef = ClassDef.module(mod, parents, body = List(runDef))

  // create class

  def clsdecls(cls: Symbol): List[Symbol] =
    List(Symbol.newMethod(cls, "foo", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Int])))

  val cls = Symbol.newClass(Symbol.spliceOwner, name, parents = parents.map(_.tpe), clsdecls, selfType = None)
  val fooSym = cls.declaredMethod("foo").head

  val fooDef = DefDef(fooSym, _ => Some(Ref(mod).select(fieldSym)))
  val clsDef = ClassDef(cls, parents, body = List(fooDef))

  // put module and class with the same name in the same scope

  Block(modDef.toList :+ clsDef, Literal(UnitConstant())).asExprOf[Unit]

Output

Compiler error: value x cannot be accessed as a member of o.type from class o

Expectation

As both object and class have the same name and are in the same block, I would expect them to be companions, i.e., the class should be able to access the private field of the companion object. I think that there should be either an API to create companions or the macro system should automatically register the object and the class to be companions (e.g., by calling registerCompanion maybe ...?)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions