Suppose I have a trait Foo
as follows:
trait Foo {
def foo[T](x: T): Etc = someDefaultImpl(x)
}
This may be extended:
trait SubFoo extends Foo {
override def foo[T](x: T): Etc = differentImpl(x)
}
How might I write a macro that calls foo
? The macro itself won’t have foo
in scope, because the macro implementer won’t extend Foo
. I tried something like the following:
def findFoo(owner: Symbol): List[Symbol] =
if (owner.isNoSymbol) Nil
else {
owner.methodMember("foo") ++ owner.companionClass.methodMember("foo") match {
case Nil => findFoo("foo", owner.maybeOwner)
case results => results
}
}
which will give me the relevant symbol that I can then apply with quoted.Apply
. However, doing something like Apply(Ref(fooSymb), List(the, params))
doesn’t work, presumably because foo
takes a type parameter (I get an error saying that the method does not take parameters).
I feel like there should be a way to get the typed symbol and have type inference do the work for me, but I could not find a way in the documentation.
Additionally, I was having trouble ensuring that this is the right foo
- namely, it should take whatever foo
is immediately in scope at the point the code is being rewritten. Ideally, I’d like to do something like
@rewriteFoo
class X {
object A extends Foo {
def invokeFoo(x: Int) = // macro will insert a call to Foo.foo here
}
object B extends SubFoo {
def invokeFoo(x: Int) = // macro will insert a call to SubFoo.foo here
}
}
However, it’s also acceptable if the macro invocation needs to be moved to the individual SubFoo
or even invokeFoo
calls.
If the macro is invoked incorrectly, I’m happy to either error at macro expansion time or insert a dummy implementation.