Skip to content

"Compiler bug" when using constValue inside an inline method #12417

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

Closed
adamw opened this issue May 11, 2021 · 13 comments
Closed

"Compiler bug" when using constValue inside an inline method #12417

adamw opened this issue May 11, 2021 · 13 comments

Comments

@adamw
Copy link
Contributor

adamw commented May 11, 2021

Compiler version

3.0.0-RC3

Minimized code

import scala.deriving.Mirror
import scala.compiletime.{constValue, error}
import scala.quoted.*

object TestMacro {
  inline def test1[CASE_CLASS <: Product](using m: Mirror.ProductOf[CASE_CLASS]): Unit = {
    error(s"Error: ${constValue[m.MirroredElemLabels]}.")
  }
}

object Test extends App {
  case class A(x: String, y: Int)
  TestMacro.test1[A]
}

This comes from an attempt to provide user-friendly error messages for inline derivations which use mirrors.

Output

[error] -- Error: Test.scala:14:2 
[error] 14 |  TestMacro.test1[A]
[error]    |  ^^^^^^^^^^^^^^^^^^
[error]    |  Compiler bug: `constValue` was not evaluated by the compiler
[error] -- Error: Test.scala:14:2 
[error] 14 |  TestMacro.test1[A]
[error]    |  ^^^^^^^^^^^^^^^^^^
[error]    |not a constant type: m$proxy1.MirroredElemLabels; cannot take constValue

Expectation

@adamw
Copy link
Contributor Author

adamw commented May 11, 2021

Sorry wrong key, adding details :)

@adamw adamw changed the title Compiler bug "Compiler bug" when using constValue inside an inline method May 11, 2021
@adamw
Copy link
Contributor Author

adamw commented May 11, 2021

Ready :)

@nicolasstucki
Copy link
Contributor

m.MirroredElemLabels is a Tuple. constValue expects values of type Int, Boolean, ..., String.

This use case is too advances for compiletime.error. In this case a macro should be used. Something like:

object TestMacro {
  inline def test1[CASE_CLASS <: Product](using m: Mirror.ProductOf[CASE_CLASS]): Unit =
    ${ code('m) }

  def code[CASE_CLASS <: Product: Type](m: Expr[Mirror.ProductOf[CASE_CLASS]])(using Quotes): Expr[Unit] =
    m match
      case '{ $_ : Mirror { type MirroredElemLabels = t } } =>
        quotes.reflect.report.error(s"Error: ${ Type.show[t] }", m)
    '{}
}

We have Type.valueOfConstant that is similar to compiletime.constValue. But we are missing a Type.valueOfTuple which would be similar to compiletime.constValueTuple

@adamw
Copy link
Contributor Author

adamw commented May 11, 2021

Ah, I though tuples of primitive types are allowed as well. I suppose the issue is then about the error message :)

So to report user-friendly errors, which include the type/ label information, I have to resort to a macro, instead of using inline+Mirror?

@adamw
Copy link
Contributor Author

adamw commented May 11, 2021

Hm reading your answer again, shouldn't constValueTuple solve the problem?

inline def test1[CASE_CLASS <: Product](using m: Mirror.ProductOf[CASE_CLASS]): Unit = {
  error(s"Error: ${constValueTuple[m.MirroredElemLabels]}.")
}

I'm getting a

[error] 14 |  TestMacro.test1[A]
[error]    |  ^^^^^^^^^^^^^^^^^^
[error]    |A literal string is expected as an argument to `compiletime.error`. Got _root_.scala.StringContext.apply(["Error: ","." : String]*).s(

@nicolasstucki
Copy link
Contributor

That is #10315

@adamw
Copy link
Contributor Author

adamw commented May 11, 2021

Ah :) Indeed - so I suppose construction of an error message which is anything above a constant string means going to a macro. Though ... maybe I can call the macro from the inline branch? 🤔 I'll have to try that.

Would you like me to close this issue as a duplicate, or keep it open to improve the error message?

@nicolasstucki
Copy link
Contributor

nicolasstucki commented May 11, 2021

What could the error message have said that would have helped you understand the issue?

@adamw
Copy link
Contributor Author

adamw commented May 11, 2021

E.g. "Not a constant: s"Error: ${constValue[m.MirroredElemLabels]}."

@adamw
Copy link
Contributor Author

adamw commented May 11, 2021

Although, maybe this is already covered by the second error, not a constant type: m$proxy1.MirroredElemLabels; cannot take constValue. I guess I got focused on the "Compiler bug" part and didn't look much further ;) That's the misleading part - it's not a compiler bug, it's my incorrect usage of inlines.

@nicolasstucki
Copy link
Contributor

Oh, I missed that part. We should not emit the first error.

@nicolasstucki
Copy link
Contributor

Ah, I missed it because it is already fixed. I remember that issue.

Now it fails with

13 |  TestMacro.test1[A]
   |  ^^^^^^^^^^^^^^^^^^
   |not a constant type: m$proxy1.MirroredElemLabels; cannot take constValue
   | This location contains code that was inlined from Foo.scala:7

@adamw
Copy link
Contributor Author

adamw commented May 11, 2021

Awesome, thank you! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants