Closed
Description
Compiler version
3.0.0-RC1
Minimized code
X.scala
import scala.quoted.*
object X:
inline def blah(inline b: Boolean = true): Unit =
${ _blah('b) }
private def _blah(b: Expr[Boolean])(using Quotes): Expr[Unit] =
import quotes.reflect.*
println("="*120)
println(b.asTerm)
println(b.valueOrError)
'{()}
Y.scala
object Y:
X.blah(true) // ok
X.blah() // error
Output
========================================================================================================================
Inlined(EmptyTree,List(),Literal(Constant(true)))
true
========================================================================================================================
Inlined(EmptyTree,List(),Select(Ident(X),blah$default$1))
[error] -- Error: Y.scala:3:4
[error] 3 | X.blah()
[error] | ^^^^^^
[error] |Expected a known value.
[error] |
[error] |The value of: X.blah$default$1
[error] |could not be extracted using scala.quoted.FromExpr$PrimitiveFromExpr@1b05809c
[error] | This location contains code that was inlined from Y.scala:3
Expectation
Expr.valueOrError
should work for inline default arguments (or at least those with constants as values). It seems that the compiler is generating a blah$default$1
rather than just keeping the Literal(Constant(true))
.
The use case here is being able to have macros with configuration flags. The flags have defaults that users can optionally override (i.e. specify) when calling the inline macro method.
It would be easier than trying unwrap Expr
s, if we could pass inline arguments directly from the public inline method to the non-inline quoted one like this:
inline def blah(inline b: Boolean = true): Unit =
${ _blah(b) }
private def _blah(b: Boolean)(using Quotes): Expr[Unit] =
'{()}