I need to generate random signleton type on every macro invocation in scala 2.13
I tried something like this, but I can't change macro def return type
def randomSingletonInt: Int = macro randomImpl
def randomImpl(c: blackbox.Context): c.Tree = {
import c.universe.*
val number = c.freshName().hashCode
q"$number"
}
I need something like this
val a = randomSingletonInt // a: 42 = 42
val b = randomSingletonInt // b: -112 = -112
How can I achieve that?
My use case is that I want to use it with implicit resolution and type inference
def randomTag[K <: Int & Singleton](implicit tag: K): CustomType[K]
implicit val a = randomSingletonInt
val tagged = randomTag // tagged: CustomType[42]
You can generate
42of singleton type42instead of typeIntwith a whitebox macroIn this sense Scala 2 whitebox macros are similar to Scala 3 transparent inline methods
https://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html#blackbox-and-whitebox-macros
https://docs.scala-lang.org/scala3/reference/metaprogramming/inline.html#transparent-inline-methods-1
The problem is that if you assign a value of a singleton type to a variable then this doesn't mean that the type of the variable is singleton
Solution is to add extra
{ }(i.e. empty type refinement, this makes impact on type inference)This is what Shapeless
.narrowdoeshttps://github.com/milessabin/shapeless/blob/main/core/shared/src/main/scala/shapeless/syntax/singletons.scala#L33
Next problem is that this not always will work further on (with implicits for example)
So you should better add code you want to compile with
a,band we'll see whether this is possible.For example in implicits a type can be cleaned from refinements before comparing with
=:=Also solution can be to generate a singleton type rather than a value of singleton type.