5

How do I get around with equivalence of two path-dependent types that I know are the same but the compiler does not?

Using Scala 2.10.0 M7 I am trying to convert an AST from one universe to another.

case class MacroBridge(context: Context) {
  def toMacroTree(tree: treehugger.forest.Tree): context.universe.Tree = ???
  def fromMacroTree(tree: context.universe.Tree): treehugger.forest.Tree = ???
}

Within a macro implementation, I can use it as:

val bridge = treehugger.MacroBridge(c)
def fromMacroTree(tree: c.universe.Tree): Tree = bridge.fromMacroTree(tree)

However, this results to a compiler error:

[error] /scalamacros-getting-started/library/Macros.scala:21: type mismatch;
[error]  found   : c.universe.Tree
[error]  required: bridge.context.universe.Tree
[error]  possible cause: missing arguments for method or constructor
[error]     def fromMacroTree(tree: c.universe.Tree): Tree = bridge.fromMacroTree(tree)

In the above code c is clearly the same value as bridge.context, but maybe because it's a value type checker cannot check it. Putting generalized type constraint did not help:

def fromMacroTree[A](tree: A)(implicit ev: A =:= context.universe.Tree): Tree =

In the macro this still resulted to an error:

[error] /scalamacros-getting-started/library/Macros.scala:21: Cannot prove that c.universe.Tree =:= bridge.context.universe.Tree.
[error]     def fromMacroTree(tree: c.universe.Tree): Tree = bridge.fromMacroTree(tree)

I need the access to context.universe so I can get to other dependent types like TermName. Is there a better work around besides casting?:

def fromMacroTree(tree: c.universe.Tree): Tree =
  bridge.fromMacroTree(tree.asInstanceOf[bridge.context.universe.Tree])
Eugene Yokota
  • 94,654
  • 45
  • 215
  • 319
  • maybe something like `def fromMacroTree[T <: Tree](tree: T): T = ???` and `fromMacroTree[tree.type](tree)` helps? – kiritsuku Aug 26 '12 at 23:21
  • I suppose both `Tree`s have some common super type, tried it? – pedrofurla Aug 26 '12 at 23:34
  • @sschaef I got the error: `type arguments [c.universe.Tree] do not conform to method fromMacroTree's type parameter bounds [T <: bridge.context.universe.Tree]` – Eugene Yokota Aug 26 '12 at 23:48

1 Answers1

9

I could the following make to work:

case class MacroBridge[C <: Context](context: C) {
  def fromMacroTree(tree: context.universe.Tree): context.universe.Tree = ???
}

trait MB {
  def meth(c: Context) {
    val bridge = MacroBridge[c.type](c)
    def fromMacroTree(tree: c.universe.Tree): c.universe.Tree =
      bridge.fromMacroTree(tree)
  }
}

I had nearly the same problem some time ago.

Community
  • 1
  • 1
kiritsuku
  • 52,967
  • 18
  • 114
  • 136