Why does type inequality fail, but does type matching match this macro?

I am trying to determine the type of parameter passed to the macro at compile time. It seems to work when I use <:< , but not when I use =:= . I do not know why. Can someone point me in the right direction? I gave an example code below.

This macro:

 import language.experimental.macros import scala.reflect.macros.Context object Macros { def say(param: Any): Unit = macro impl def impl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = { if (param.actualType.<:<(c.universe.typeOf[String])) { c.universe.reify { printf("string: %s\n", param.splice) } } else if (param.actualType.<:<(c.universe.typeOf[Int])) { c.universe.reify { printf("int: %d\n", param.splice) } } else { c.universe.reify { printf("any: %s\n", param.splice) } } } } 

Called by this code:

 object Test extends App { Macros.say("Hi") Macros.say(1) Macros.say(Blah) } case object Blah 

Return:

 string: Hi int: 1 any: Blah 

But if I check for equality of type ( =:= ), the macro returns:

 any: Hi any: 1 any: Blah 

Any help would be greatly appreciated.

+6
source share
1 answer

This is because the type "Hi" not just a String , it is a more specific type - String("Hi") , which means that this type contains information that is a specific string literal.

The same thing happens with literal 1 - it is type Int(1) , not just Int .

You can use the widen method on Type to separate constant value information:

 object Macros { def say(param: Any): Unit = macro impl def impl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = { if (param.actualType.widen.=:=(c.universe.typeOf[String])) { c.universe.reify { printf("string: %s\n", param.splice) } } else if (param.actualType.widen.=:=(c.universe.typeOf[Int])) { c.universe.reify { printf("int: %d\n", param.splice) } } else { c.universe.reify { printf("any: %s\n", param.splice) } } } } 
+7
source

Source: https://habr.com/ru/post/946212/


All Articles