Search code examples
scalametaprogrammingscala-macros

Get value of a literal type passed as type parameter


I'm trying to write a macro which returns a value of a literal type passed as a type parameter and fails to compile if the parameter is not a literal type. Here are some examples:

def literalValue[SC <: String] = //...

literalValue["AB"] // returns "AB"
literalValue["C"] // returns "C"
literalValue[String] // compile error

So I started with a regular macro boilerplate and faced the following problem:

def implStringLiteral[SC <: String: c.WeakTypeTag](c: blackbox.Context): c.Expr[SC] = {
  import c.universe._
  val symbol = weakTypeOf[SC].typeSymbol //It is String
  //...
}

It seems like the literal type itself is passed as a regular String so the precise type information is unavailable through its WeakTypeTag.

Is there any workaround to fix the issue?


Solution

  • ValueOf[T] typeclass returns unique inhabitant out-of-the box

    scala> valueOf
    def valueOf[T](implicit vt: ValueOf[T]): T
    scala> valueOf["AB"]
    val res2: String = AB
    
    scala> valueOf[42]
    val res3: Int = 42
    
    scala> object Foo
    object Foo
    
    scala> valueOf[Foo.type]
    val res4: Foo.type = Foo$@6e1ad658
    
    scala> valueOf[Unit]
    
    scala> .toString
    val res6: String = ()
    
    scala> valueOf[String]
                  ^
           error: No singleton value available for String.