-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Assertion error during macro generation for an enum #20349
Comments
Let's rewrite class Test {
object domain {
enum PaymentMethod:
case PayPal(email: String)
case Card(digits: Long, name: String)
case Cash
}
println(Macros.values[domain.PaymentMethod])
}
object Test {
lazy val script = new Test()
def main(args: Array[String]): Unit =
val _ = script.hashCode()
} Running this with -- Error: /Users/jchyb/workspace/scalabug/2/repro1.scala:8:23 ------------------
8 | println(Macros.values[domain.PaymentMethod])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|Malformed tree was found while expanding macro with -Xcheck-macros.
| |The tree does not conform to the compiler's tree invariants.
| |
| |Macro was:
| |scala.quoted.runtime.Expr.splice[scala.collection.immutable.List[Test.this.domain.PaymentMethod]](((evidence$1: scala.quoted.Quotes) ?=> Macros.valuesImpl[Test.this.domain.PaymentMethod](scala.quoted.Type.of[Test.this.domain.PaymentMethod](evidence$1), evidence$1)))
| |
| |The macro returned:
| |scala.List.apply[Test.this.domain.PaymentMethod](PaymentMethod.this.Cash)
| |
| |Error:
| |assertion failed: error while typing PaymentMethod.this, value <local Test> is not contained in object PaymentMethod
| |
|stacktrace available when compiling with `-Ydebug`
| |
|----------------------------------------------------------------------------
|Inline stack trace
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|This location contains code that was inlined from repro.scala:50
50 | inline def values[A]: List[A] = ${ valuesImpl[A] }
| ^^^^^^^^^^^^^^^^^^
---------------------------------------------------------------------------- Evidently, the macro generates us code with The issue in the macro method lies with the use of |
I did some experimentation. I found that: class OuterClass {
type InnerType
} would indeed confuse macros - make them throw
However, for case like: class Snippet { // simluating what .sc file creates
enum Foo:
case Bar(a: Int) // with parameter (separate class)
case Baz // parameterless (val with valueName.type)
} for So while use Perhaps we can consider this bug ticket solved, but I believe that some full canonical answer should be posted here, in case someone else has the same issue. |
This reminds me of #19825 - it is impossible to get the correct inner type using |
Apologies for the late reply.
|
@jchyb So, if I understand correctly, when I obtain from
I am asking because that quickly becomes rather hard to do it right. I am starting to think that perhaps it would be easier to |
I started writing a detailed response, but while trying something out I happened upon a legitimate crash, not reported by -Xcheck-macros... I am right now trying to better diagnose it. |
While writing my previous explanations here I focused on the fact that that a lot of typeRefs are used, which only work in local contexts... and I did not notice that in our minimisation: class Test {
object domain {
enum PaymentMethod:
case PayPal(email: String)
case Card(digits: Long, name: String)
case Cash
}
println(Macros.values[domain.PaymentMethod])
} we are indeed expanding the macro in a local context of class Cls{
object a {
object domain {
val value = ""
}
}
println(Macros.values[a.domain.type])
}
object Test {
lazy val script = new Cls()
def main(args: Array[String]): Unit =
val _ = script.hashCode()
???
} import scala.quoted.*
object Macros {
def valuesImpl[A: Type](using Quotes): Expr[Any] = {
import quotes.*, quotes.reflect.*
val symbol = TypeRepr.of[A].typeSymbol.fieldMember("value")
Ref(symbol).asExprOf[Any]
}
transparent inline def values[A]: Any = ${ valuesImpl[A] }
} our constructed |
Great thanks for the explanation! Should we assume that the improvement will be backported to 3.3 line or for LTS should I construct the trees manually? |
Unsure about LTS, I'd personally prefer if it was backported, and I don't see anybody relying on that generated incorrect |
Compiler version
3.3.3
Minimized code
repro.scala
repro.test.sc
Output
Expectation
repro.test.sc
should compile successfully (and print something likeList(Cash)
).The text was updated successfully, but these errors were encountered: