Macros: inspecting parent types of the enclosing type

550 views
Skip to first unread message

Adam Warski

unread,
Apr 23, 2013, 3:46:32 AM4/23/13
to scala...@googlegroups.com
Hello,

I'd like to inspect the parent classes/traits of the macro usage's enclosing type.

Surprisingly, this works if both classes are in the same package, e.g. if I have:

(first file)
package foo
trait A {
   ...
}

(second file)
package foo
trait B extends A {
   // macro invocation
}

Then in the macro I can get the enclosing class, match it to ClassDef/ModuleDef, and from there get the Template's parents tree, which then through parent.tpe gives me the type and information about all the values in the parent trait (A in this case). A bit simplified:

// c: Context
val ClassDef(_, _, _, Template(parents, _, _)) = c.enclosingClass
parents.foreach(parent => inspect(parent.tpe))
// parent.tpe is not null, parent.tpe.members gives all information about the trait

However, if the classes are in different packages, parent.tpe is null. E.g.:

(first file)
package foo.bar
trait A {
   ...
}

(second file)
package foo
trait B extends A {
   // macro invocation
}

Is it possible to get information on A in the second scenario? If not, why?

Thanks,
Adam Warski

Adam Warski

unread,
Apr 24, 2013, 12:35:28 PM4/24/13
to scala...@googlegroups.com
The solution I found is quite ugly. Actually it's more of a hack.
To get the parent's members, I create an expression that has the type of the parent (in my case - null.asInstanceOf[parent's Ident]), and do a type-check (c.typeCheck).
This works for now, but I'm sure I'm missing some other edge case :)

Overall, it would be good to have a mode of running macros as reflection-replacement, that is after all the type-checking is done (assuming macros return what is specified by the macro method), and with all information about surrounding classes/methods available. The macro would then have to generate an expression of the given type which would substitute the original macro invocation.

What do you think?

Adam

Eugene Burmako

unread,
Apr 24, 2013, 1:01:40 PM4/24/13
to Adam Warski, scala-user, Jason Zaugg, Adriaan Moors
I think that's the best that can be done right now. The API to reflect against enclosing trees and nearby compilation units is something that definitely needs improvement, as there are a lot of non-obvious interactions with the order of how things get typechecked, with the style of typechecking (in-place / functional), which varies on a per-node basis and such.

Post-typer macros are definitely appealing, because they allow for more predictable typechecking (e.g. no more macros, which refine their declared return type and no more macros which slow down the typer), which provides multiple benefits to the tools (compiler has easier time reasoning about types in the program, IDE doesn't have to expand macros to provide useful info to the user, humans can understand macro-using programs better).

Nevertheless post-typer macros have at least one (but big) problem: implicits. First of all, due to technical restrictions post-typer implicit lookup is inaccurate, which means that if a macro expands into a call to a method which requires an implicit argument (e.g. something as commonplace as a map), it will most likely run into problems. Secondly, macros can be used to conjure implicit arguments, and by doing that (or by refusing to do that) they can steer type inference, overload resolution, etc. These kinds of things can only be done during typechecking.


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Adam Warski

unread,
Apr 24, 2013, 2:01:51 PM4/24/13
to Eugene Burmako, scala-user, Jason Zaugg, Adriaan Moors
I think that's the best that can be done right now. The API to reflect against enclosing trees and nearby compilation units is something that definitely needs improvement, as there are a lot of non-obvious interactions with the order of how things get typechecked, with the style of typechecking (in-place / functional), which varies on a per-node basis and such.

Ok, thanks, I know now that I don't have to look further for a better solution.

Post-typer macros are definitely appealing, because they allow for more predictable typechecking (e.g. no more macros, which refine their declared return type and no more macros which slow down the typer), which provides multiple benefits to the tools (compiler has easier time reasoning about types in the program, IDE doesn't have to expand macros to provide useful info to the user, humans can understand macro-using programs better).

Are post-typer macros something that you are planning to add to macro-paradise? They sound so nice ;).

Nevertheless post-typer macros have at least one (but big) problem: implicits. First of all, due to technical restrictions post-typer implicit lookup is inaccurate, which means that if a macro expands into a call to a method which requires an implicit argument (e.g. something as commonplace as a map), it will most likely run into problems. Secondly, macros can be used to conjure implicit arguments, and by doing that (or by refusing to do that) they can steer type inference, overload resolution, etc. These kinds of things can only be done during typechecking.

And it's not possible to re-type-check the result of the macro? As I understand the generated code can require new implicits (not generate new implicits, as that would impact possible a lot of other things), so the "affected area" should be only the macro expansion? 

Thanks,
Adam


Eugene Burmako

unread,
Apr 25, 2013, 7:31:54 AM4/25/13
to Adam Warski, scala-user, Jason Zaugg, Adriaan Moors
Speaking of post-typer macros and macro paradise, well, anything can happen :)

As for retypechecking, as mentioned above that's currently impossible because of implementation restrictions. But even if those restrictions are lifted, retypechecking won't help with implicit macros, which have to be expanded in typer to behave correctly.


Adam Warski

unread,
Apr 25, 2013, 7:38:03 AM4/25/13
to Eugene Burmako, scala-user, Jason Zaugg, Adriaan Moors

Speaking of post-typer macros and macro paradise, well, anything can happen :)

I'll be on the lookout then

As for retypechecking, as mentioned above that's currently impossible because of implementation restrictions. But even if those restrictions are lifted, retypechecking won't help with implicit macros, which have to be expanded in typer to behave correctly.

Hmm ok, don't know yet what are implicit macros.

It seems each macro-project could in fact use a dedicated macro type ;). Just shows that there's a lot of possibilities to do meta-programming … and intersected with not-so-few Scala features, well, you get problems sometime.

Eugene Burmako

unread,
Apr 25, 2013, 7:44:27 AM4/25/13
to Adam Warski, scala-user, Jason Zaugg, Adriaan Moors
Implicit macros are implicit defs declared as macros. They can be used to generate type class instances on-the-fly, as, for example, described in section 4.3 of my recent paper: http://scalamacros.org/news/2013/04/22/let-our-powers-combine.html.


Adriaan Moors

unread,
Apr 25, 2013, 7:56:54 AM4/25/13
to Adam Warski, Eugene Burmako, scala-user, Jason Zaugg

On Thu, Apr 25, 2013 at 1:38 PM, Adam Warski <ad...@warski.org> wrote:
It seems each macro-project could in fact use a dedicated macro type ;). Just shows that there's a lot of possibilities to do meta-programming … and intersected with not-so-few Scala features, well, you get problems sometime.

Indeed. This is why I insist we focus on reducing macros in 2.11 to a small uncontroversial core. The precise definition of this core is ongoing work. 

A smaller core is better for everybody: given a fixed time budget, the smaller set of core features will be of higher quality and come with better documentation for macro authors. Fewer features to support (and thus fewer bugs to fix) in the mainstream release leave the researchers at EPFL with more time for experimentation, which will of course continue in macro paradise. When the time is right, we'll consider adding more stabilized features to the release after that (2.12).


--
See you at Scala Days (June 10–12, NYC)!

Adam Warski

unread,
Apr 25, 2013, 9:19:32 AM4/25/13
to Eugene Burmako, scala-user, Jason Zaugg, Adriaan Moors

On Apr 25, 2013, at 1:44 PM, Eugene Burmako <eugene....@epfl.ch> wrote:

Implicit macros are implicit defs declared as macros. They can be used to generate type class instances on-the-fly, as, for example, described in section 4.3 of my recent paper: http://scalamacros.org/news/2013/04/22/let-our-powers-combine.html.

Ah, modularisation of Manifest lookup - nice! 
I wonder then what will be left as "core Scala" after some features are moved to macros.

Thanks for the pointer.

Adam Warski

unread,
Apr 25, 2013, 9:23:50 AM4/25/13
to Adriaan Moors, Eugene Burmako, scala-user, Jason Zaugg
That's called agile development ;)

I wonder if there's something that would generalise all the macro types … but we would probably get Lisp or something like that.
Reply all
Reply to author
Forward
0 new messages