2

I have a trait with a member type, and want to have a macro with signature containing this type:

trait Foo {
  class Bar[A] { ... }

  def baz[A](x: Bar[A]): Bar[A] = macro bazImpl[A]

  def bazImpl[A: c.WeakTypeTag](c: blackbox.Context)(x: c.Expr[Bar[A]]) = ...
}

This doesn't work, since bazImpl must belong either to a static (i.e. non-member) object or to a macro bundle. But in neither case do I have a foo: Foo so I could write foo.Bar[A].

One workaround I can think of is to use Foo#Bar[A] and add casts:

trait Foo {
  class Bar[A] { ... }

  def baz[A](x: Bar[A]): Bar[A] = Foo.baz1(x).asInstanceOf[Bar[A]]

  def bazImpl[A: c.WeakTypeTag](c: blackbox.Context)(x: c.Expr[Bar[A]]) = ...
}

object Foo {
  def baz1[A](x: Foo#Bar[A]): Foo#Bar[A] = macro bazImpl[A]

  def bazImpl[A: c.WeakTypeTag](c: blackbox.Context)(x: c.Expr[Foo#Bar[A]]): c.Expr[Foo#Bar[A]] = ... 
}

But I'd like to avoid it (both because it's not exactly type-safe and because the real case is more complicated). Any alternatives?

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Can you make a nested companion object along with to the nested class? In other words, make a `Bar` object nested in the `Foo` trait that contains the `bazImpl` method? – Ben Reich May 29 '15 at 20:58
  • @BenReich As said, the macro implementation has to be in a _static_ object. An object nested in `Foo` is not static (as I understand, at least). – Alexey Romanov May 30 '15 at 05:43

1 Answers1

2

If you're using Scala 2.11, just write c.Tree everywhere instead of c.Expr. That will cut down the boilerplate of specifying the very same types in macro impls as in macro defs at virtually zero cost. The only potential downside of trees in comparison with exprs is reify, which requires splicees to be exprs, but since most of metaprograms in Scala are written with quasiquotes these days, chances are that this won't matter to you.

Eugene Burmako
  • 13,028
  • 1
  • 46
  • 59
  • Can you explain more about the difference between Tree and Expr and how Tree allows for the correct nested class but Expr doesn't? – Ben Reich May 30 '15 at 05:48
  • 1
    @EugeneBurmako This might be worth mentioning in Macros Overview (if it isn't; I haven't seen it, at least). – Alexey Romanov May 30 '15 at 08:20
  • How is this an answer to the original question? – Miles Sabin May 30 '15 at 13:35
  • 1
    @BenReich When you write c.Expr, you need to provide a type argument that specifies the static type of an underlying tree. This type has to be aligned with the corresponding parameter type / return type of the macro def, and that's validated by the compiler. When you write c.Tree, it doesn't have type arguments, so the compiler doesn't validate anything. – Eugene Burmako May 30 '15 at 14:58
  • 1
    @MilesSabin I don't think that there's a good answer to the question, so I suggested a workaround that solves the underlying problem. – Eugene Burmako May 30 '15 at 14:59