summaryrefslogtreecommitdiff
path: root/test/files/run/t5903b
Commit message (Collapse)AuthorAgeFilesLines
* *boxContext => *box.Context , *boxMacro => *box.MacroEugene Burmako2014-01-121-2/+2
| | | | | | | | | | Performs the following renamings: * scala.reflect.macros.BlackboxContext to scala.reflect.macros.blackbox.Context * scala.reflect.macros.BlackboxMacro to scala.reflect.macros.blackbox.Macro * scala.reflect.macros.WhiteboxContext to scala.reflect.macros.whitebox.Context * scala.reflect.macros.WhiteboxMacro to scala.reflect.macros.whitebox.Macro https://groups.google.com/forum/#!topic/scala-internals/MX40-dM28rk
* deprecates macro def return type inferenceEugene Burmako2013-12-101-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With the new focus on quasiquotes in macro implementations, we now have to change the way how inference of macro def return types works. Previously, if the return type of a macro def wasn’t specified, we looked into the signature of its macro impl, took its return type (which could only be c.Expr[T]) and then assigned T to be the return type of the macro def. We also had a convenient special case which inferred Any in case when the body of the macro impl wasn’t an expr. That avoided reporting spurious errors if the macro impl had its body typed incorrectly (because in that case we would report a def/impl signature mismatch anyway) and also provided a convenience by letting macro impls end with `???`. However now we also allow macro impls to return c.Tree, which means that we are no longer able to do any meaningful type inference, because c.Tree could correspond to tree of any type. Unfortunately, when coupled with the type inference special case described above, this means that the users who migrate from exprs to quasiquotes are going to face an unpleasant surprise. If they haven’t provided explicit return types for their macro defs, those types are going to be silently inferred as `Any`! This commit plugs this loophole by prohibiting type inference from non-expr return types of macro impls (not counting Nothing). Moreover, it also deprecates c.Expr[T] => T inference in order to avoid confusion when switching between exprs and quasiquotes.
* blackbox restriction #1: can't refine the official return typeEugene Burmako2013-11-121-2/+2
| | | | | | | | | | | When an application of a blackbox macro expands into a tree `x`, the expansion is wrapped into a type ascription `(x: T)`, where `T` is the declared return type of the blackbox macro with type arguments and path dependencies applied in consistency with the particular macro application being expanded. This invalidates blackbox macros as an implementation vehicle of type providers.
* blackbox and whitebox macrosEugene Burmako2013-11-121-2/+2
| | | | | | | | | | | | | | | | | | This is the first commit in the series. This commit only: 1) Splits Context into BlackboxContext and WhiteboxContext 2) Splits Macro into BlackboxMacro and WhiteboxMacro 3) Introduces the isBundle property in the macro impl binding Here we just teach the compiler that macros can now be blackbox and whitebox, without actually imposing any restrictions on blackbox macros. These restrictions will come in subsequent commits. For description and documentation of the blackbox/whitebox separation see the official macro guide at the scaladoc website: http://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html Some infrastructure work to make evolving macros easier: compile partest-extras with quick so they can use latest library/reflect/...
* SI-5903 extractor macrosEugene Burmako2013-08-182-0/+31
Establishes a pattern that can be used to implement extractor macros that give the programmer control over signatures of unapplications at compile-time. === The pattern === In a nutshell, given an unapply method (for simplicity, in this example the scrutinee is of a concrete type, but it's also possible to have the extractor be polymorphic, as demonstrated in the tests): ``` def unapply(x: SomeType) = ??? ``` One can write a macro that generates extraction signatures for unapply on per-call basis, using the target of the calls (c.prefix) and the type of the scrutinee (that comes with x), and then communicate these signatures to the typechecker. For example, here's how one can define a macro that simply passes the scrutinee back to the pattern match (for information on how to express signatures that involve multiple extractees, visit https://github.com/scala/scala/pull/2848). ``` def unapply(x: SomeType) = macro impl def impl(c: Context)(x: c.Tree) = { q""" new { class Match(x: SomeType) { def isEmpty = false def get = x } def unapply(x: SomeType) = new Match(x) }.unapply($x) """ } ``` In addition to the matcher, which implements domain-specific matching logic, there's quite a bit of boilerplate here, but every part of it looks necessary to arrange a non-frustrating dialogue with the typer. Maybe something better can be done in this department, but I can't see how, without introducing modifications to the typechecker. Even though the pattern uses structural types, somehow no reflective calls are being generated (as verified by -Xlog-reflective-calls and then by manual examination of the produced code). That's a mystery to me, but that's also good news, since that means that extractor macros aren't going to induce performance penalties. Almost. Unfortunately, I couldn't turn matchers into value classes because one can't declare value classes local. Nevertheless, I'm leaving a canary in place (neg/t5903e) that will let us know once this restriction is lifted. === Use cases === In particular, the pattern can be used to implement shapeshifting pattern matchers for string interpolators without resorting to dirty tricks. For example, quasiquote unapplications can be unhardcoded now: ``` def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], ...) = { ... fun.tpe match { case ExtractorType(unapply) if mode.inPatternMode => // this hardcode in Typers.scala is no longer necessary if (unapply == QuasiquoteClass_api_unapply) macroExpandUnapply(...) else doTypedUnapply(tree, fun0, fun, args, mode, pt) } } ``` Rough implementation strategy here would involve writing an extractor macro that destructures c.prefix, analyzes parts of StringContext and then generates an appropriate matcher as outlined above. === Implementation details === No modifications to core logic of typer or patmat are necessary, as we're just piggybacking on https://github.com/scala/scala/pull/2848. The only minor change I introduced is a guard against misbehaving extractor macros that don't conform to the pattern (e.g. expand into blocks or whatever else). Without the guard we'd crash with an NPE, with the guard we get a sane compilation error.