Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symbol#overridingSymbol returns NoSymbol for correct arguments #17349

Open
Iltotore opened this issue Apr 26, 2023 · 2 comments
Open

Symbol#overridingSymbol returns NoSymbol for correct arguments #17349

Iltotore opened this issue Apr 26, 2023 · 2 comments
Labels
area:metaprogramming:reflection Issues related to the quotes reflection API itype:bug

Comments

@Iltotore
Copy link
Contributor

Iltotore commented Apr 26, 2023

Compiler version

3.3.1-RC1-bin-20230425-c9ca7ce-NIGHTLY

Minimized code

//> using scala "3.3.1-RC1-bin-20230425-c9ca7ce-NIGHTLY"

import scala.quoted.*

abstract class Foo:

  def test: String

inline def showExpr(inline value: Any): String = ${showExprImpl('value)}

def showExprImpl(expr: Expr[Any])(using Quotes): Expr[String] =
  import quotes.reflect.*

  Expr(
    s"""${expr.asTerm.show}
       |
       |${expr.asTerm.show(using Printer.TreeStructure)}""".stripMargin)

inline def generateFooOverride: Foo = ${generateFooImpl}

def generateFooImpl(using Quotes): Expr[Foo] =
  import quotes.reflect.*

  val fooRepr = TypeRepr.of[Foo]
  val fooSymbol = fooRepr.dealias.classSymbol.get

  val overridingSymbol = Symbol.newClass(Symbol.spliceOwner, Symbol.freshName("Foo"), List(fooRepr), _ => Nil, None)
  def newInstance(clazz: Symbol, args: List[Term]): Term = Apply(Select(New(TypeTree.ref(clazz)), clazz.primaryConstructor), args)

  val fooTestSymbol = fooSymbol.declaredMethod("test").head
  val overridingTestSymbol = fooTestSymbol.overridingSymbol(overridingSymbol)

  println(fooTestSymbol.flags.is(Flags.Private).toString) //false as expected
  println(fooTestSymbol.isClassConstructor.toString) //false as expected
  println(fooTestSymbol.maybeOwner.isClassDef.toString) //true as expected
  println(overridingSymbol.isClassDef.toString) //true as expected
  println(overridingTestSymbol.isNoSymbol.toString) //true but should be false

  def overridingTestDef(term: Term): DefDef =
    DefDef( //java.lang.AssertionError: assertion failed: expected a term symbol but received val <none>
      overridingTestSymbol,
      _ => Some(term)
    )

  def overridingClassDef(term: Term): ClassDef =
    ClassDef(
      overridingSymbol,
      List(newInstance(fooSymbol, Nil)),
      List(overridingTestDef(term))
    )

  def instance(term: Term): Term =
    Block(
      List(overridingClassDef(term)),
      newInstance(overridingSymbol, Nil)
    )

  instance(Literal(StringConstant("hello"))).asExprOf[Foo]

In another file call generateFooOverride

Output

overridingTestSymbol is NoSymbol causing the DefDef in overridingTestDef to throw the following error:

[error] java.lang.AssertionError: assertion failed: expected a term symbol but received val <none>
[error]         at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
[error]         at scala.quoted.runtime.impl.QuotesImpl$reflect$DefDef$.apply(QuotesImpl.scala:279)
[error]         at scala.quoted.runtime.impl.QuotesImpl$reflect$DefDef$.apply(QuotesImpl.scala:278)
[error]         at ClassGen$package$.overridingTestDef$1(ClassGen.scala:41)
[error]         at ClassGen$package$.overridingClassDef$1(ClassGen.scala:48)
[error]         at ClassGen$package$.instance$1(ClassGen.scala:53)
[error]         at ClassGen$package$.generateFooImpl(ClassGen.scala:57)

Expectation

I'd expect overridingTestSymbol to not be NoSymbol and generate this code:

class Foo$macro$1 extends Foo:

  override def test: String = "hello"

new Foo$macro$1

mostly like:

new Foo:

  override def test: String = "hello"

Notes

  • I use the low-level term API because in my current use case I need to generate this code for a generic type (T instead of Foo). I'm trying to reproduce this macro.
  • After diving into the compiler codebase, I checked if my arguments satisfy the criterias needed by Symbol#overridingSymbol (see line 34). They all pass.
@Iltotore Iltotore added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 26, 2023
@Kordyjan Kordyjan added area:metaprogramming:reflection Issues related to the quotes reflection API and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 26, 2023
@Kordyjan
Copy link
Contributor

For some reasons, Scala CLI does not log println/report.info messages in macros.

If you run it with --server=false, you will see the output.

@Kordyjan Kordyjan added this to the Future versions milestone Apr 26, 2023
@Iltotore
Copy link
Contributor Author

Iltotore commented Apr 26, 2023

Thank you for the tip. I updated my message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:metaprogramming:reflection Issues related to the quotes reflection API itype:bug
Projects
None yet
Development

No branches or pull requests

2 participants