Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does type equality fail, but type conformance succeed in this macro?

I'm trying to determine the type of a parameter passed into a macro at compile time. It seems to work when I use <:< but not when I use =:=. I'm not sure why. Can anyone point me in the right direction? I've included 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

Returns:

string: Hi
int: 1
any: Blah

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

any: Hi
any: 1
any: Blah

Any help would be much appreciated.

like image 590
Matt Roberts Avatar asked May 30 '13 21:05

Matt Roberts


1 Answers

That is because type of "Hi" is not just String, it's more specific type - String("Hi"), which means this type contains information that it represents concrete string literal.

The same situation occurs with literal 1 - it's type is Int(1), not just Int.

You can use widen method on Type to strip information about constant values:

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) }
    }
  }
}
like image 156
ghik Avatar answered Nov 01 '22 11:11

ghik