- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1.1k
Open
Labels
area:metaprogramming:reflectionIssues related to the quotes reflection APIIssues related to the quotes reflection APIitype:bug
Milestone
Description
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$1mostly 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 (Tinstead ofFoo). 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.
Metadata
Metadata
Assignees
Labels
area:metaprogramming:reflectionIssues related to the quotes reflection APIIssues related to the quotes reflection APIitype:bug