Skip to content

Bytecode generation bug involving magnolia and runtime annotations #19303

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

Open
oyvindberg opened this issue Dec 20, 2023 · 5 comments
Open

Bytecode generation bug involving magnolia and runtime annotations #19303

oyvindberg opened this issue Dec 20, 2023 · 5 comments
Labels
area:backend itype:bug stat:needs minimization Needs a self contained minimization

Comments

@oyvindberg
Copy link

oyvindberg commented Dec 20, 2023

Compiler version

3.3.1

Minimized code

Repro here
I'll copy/paste it in here anyway for convenience.

import magnolia1.*

object Repro {
  case class Foo(id: Int) {
    @java.lang.Deprecated("foo") val foo: Int = 1
  }

  trait Default[T] {
    val value: T
  }

  object Default extends AutoDerivation[Default] {
    implicit val int: Default[Int] = new Default[Int] {
      override val value: Int = 1
    }

    override def join[T](ctx: CaseClass[Default, T]): Default[T] = new Default[T] {
      override val value: T = ctx.construct(_.typeclass.value)
    }
    override def split[T](ctx: SealedTrait[Default, T]): Default[T] =
      ctx.subtypes.headOption match {
        case Some(sub) =>
          new Default[T] {
            override val value: T = sub.typeclass.value
          }
        case None => sys.error("no subtypes")
      }
  }

  summon[Default[Foo]]
}

Output

java.util.NoSuchElementException: class Boolean
	at scala.collection.mutable.AnyRefMap$ExceptionDefault.apply(AnyRefMap.scala:508)
	at scala.collection.mutable.AnyRefMap$ExceptionDefault.apply(AnyRefMap.scala:507)
	at scala.collection.mutable.AnyRefMap.apply(AnyRefMap.scala:207)
	at dotty.tools.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder$locals$.load(BCodeSkelBuilder.scala:523)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:436)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.loop$1(BCodeBodyBuilder.scala:1202)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:1209)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:794)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genArray(BCodeBodyBuilder.scala:898)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genArrayValue(BCodeBodyBuilder.scala:881)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:470)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.loop$1(BCodeBodyBuilder.scala:1202)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:1209)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:832)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.loop$1(BCodeBodyBuilder.scala:1202)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:1209)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:832)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.loop$1(BCodeBodyBuilder.scala:1202)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:1209)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:832)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genArray(BCodeBodyBuilder.scala:898)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genArrayValue(BCodeBodyBuilder.scala:881)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:470)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.loop$1(BCodeBodyBuilder.scala:1202)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:1209)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:832)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.loop$1(BCodeBodyBuilder.scala:1202)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:1209)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:832)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:298)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadQualifier(BCodeBodyBuilder.scala:1185)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genTypeApply(BCodeBodyBuilder.scala:691)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:480)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:462)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:298)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadQualifier(BCodeBodyBuilder.scala:1185)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:830)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:298)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadQualifier(BCodeBodyBuilder.scala:1185)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genTypeApply(BCodeBodyBuilder.scala:691)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:480)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:320)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genStat(BCodeBodyBuilder.scala:117)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo$$anonfun$1(BCodeBodyBuilder.scala:1087)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo(BCodeBodyBuilder.scala:1087)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:454)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.loop$1(BCodeBodyBuilder.scala:1202)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:1209)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:832)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:298)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadQualifier(BCodeBodyBuilder.scala:1185)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genTypeApply(BCodeBodyBuilder.scala:691)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:480)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:320)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genStat(BCodeBodyBuilder.scala:117)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo$$anonfun$1(BCodeBodyBuilder.scala:1087)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo(BCodeBodyBuilder.scala:1087)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:454)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:462)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.loop$1(BCodeBodyBuilder.scala:1202)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:1209)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:832)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:382)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:462)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo(BCodeBodyBuilder.scala:1088)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:454)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo(BCodeBodyBuilder.scala:1088)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:454)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:462)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo(BCodeBodyBuilder.scala:1088)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:454)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:462)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo(BCodeBodyBuilder.scala:1088)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:454)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:462)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo(BCodeBodyBuilder.scala:1088)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:454)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadTo(BCodeBodyBuilder.scala:320)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:303)
	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genStat(BCodeBodyBuilder.scala:117)

	at dotty.tools.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genBlockTo$$anonfun$1(BCodeBodyBuilder.scala:1087)

Expectation

Should compile.

I don't have the time or knowledge to minimize away the magnolia dependency, I already extracted it from a big codebase.
I also don't know if the bug resides in magnolia or in the compiler. I'm filing it here because it's my best guess.

I'll explain the interesting thing I noticed while minimizing this. The error message refers to Boolean, which is actually a parameter to the @java.lang.Deprecated annotation. If you remove the parameter I passed:

-    @java.lang.Deprecated("foo") val foo: Int = 1
+    @java.lang.Deprecated() val foo: Int = 1

the error message refers to String. if you provide both, the example compiles. The annotation seems to have to be retained at runtime to trigger this bug.

Likely related: #15955

@oyvindberg oyvindberg added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Dec 20, 2023
@oyvindberg
Copy link
Author

oyvindberg commented Dec 20, 2023

Another update on this. I said if both parameters to java.lang.Deprecated is filled in it does compile, but it fails at runtime.

https://scastie.scala-lang.org/Xxt4t9sDTjWLV29eoB7btA

hola 
java.lang.InstantiationError: java.lang.Deprecated
	at Playground$.liftedTree1$1(main.scala:7)
	at Playground$.<clinit>(main.scala:38)
	at Main$.<clinit>(main.scala:43)
	at Main.main(main.scala)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)

@nicolasstucki nicolasstucki added stat:needs minimization Needs a self contained minimization and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Dec 20, 2023
@nicolasstucki
Copy link
Contributor

We need a minimization that does not have the "com.softwaremill.magnolia1_3" %% "magnolia" % "1.3.4" dependency.

@oyvindberg
Copy link
Author

I suppose we can dump the source code result of the call to AutoDerivation#autoDerived. is there a way to do so easily?

@nicolasstucki
Copy link
Contributor

I suppose we can dump the source code result of the call to AutoDerivation#autoDerived. is there a way to do so easily?

You may try to write explicitly the expression that autoDerived generates. If we are lucky, that may reproduce the failure. You may try to see what is generated using the -Xprint:typer,inlining compiler flag.

@xeppaka
Copy link

xeppaka commented Aug 18, 2024

Hi, I have the same problem with Java annotations.
Not sure if it's a magnolia problem or scala 3, but basically magnolia is doing something like this (simplified):

object Annotations {
  inline def getAnnotations[T]: List[Any] = ${ getAnnotationsImpl[T] }

  def getAnnotationsImpl[T: Type](using quotes: Quotes): Expr[List[Any]] = {
    import quotes.reflect.*

    val tpe: TypeRepr = TypeRepr.of[T]

    Expr.ofList {
      tpe.typeSymbol.primaryConstructor.paramSymss.flatten.flatMap(field => field.annotations).map { an => an.asExpr }
    }
  }
}

When result of this macro is used then java.lang.InstantiationError is thrown.
I think it's good at this moment to understand who is responsible for causing that problem, scala or magnolia...

full project with sbt run: https://github.com/xeppaka/macro-problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:backend itype:bug stat:needs minimization Needs a self contained minimization
Projects
None yet
Development

No branches or pull requests

3 participants