diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-02-23 13:40:14 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-05-11 18:37:10 +0200 |
commit | 8168f118c9f71d63404880de89f20471043949fe (patch) | |
tree | acaa51210ad494e2ee018a68508e5c602484d88a /src/reflect | |
parent | bb73b9669a96410bc9c513d061d090f5bd3c075e (diff) | |
download | scala-8168f118c9f71d63404880de89f20471043949fe.tar.gz scala-8168f118c9f71d63404880de89f20471043949fe.tar.bz2 scala-8168f118c9f71d63404880de89f20471043949fe.zip |
[nomaster] SI-7167 implicit macros decide what is divergence
Imagine a macro writer which wants to synthesize a complex implicit
Complex[T] by making recursive calls to Complex[U] for its parts.
E.g. if we have `class Foo(val bar: Bar)` and `class Bar(val x: Int)`,
then it's quite reasonable for the macro writer to synthesize
Complex[Foo] by calling `inferImplicitValue(typeOf[Complex[Bar])`.
However if we didn't insert `info.sym.isMacro` check in `typedImplicit`,
then under some circumstances (e.g. as described in http://groups.google.com/group/scala-internals/browse_thread/thread/545462b377b0ac0a)
`dominates` might decide that `Bar` dominates `Foo` and therefore a
recursive implicit search should be prohibited.
Now when we yield control of divergent expansions to the macro writer,
what happens next? In the worst case, if the macro writer is careless,
we'll get a StackOverflowException from repeated macro calls. Otherwise,
the macro writer could check `c.openMacros` and `c.openImplicits` and
do `c.abort` when expansions are deemed to be divergent. Upon receiving
`c.abort` the typechecker will decide that the corresponding implicit
search has failed which will fail the entire stack of implicit searches,
producing a nice error message provided by the macro writer.
NOTE: the original commit from macro paradise also introduced a new
class, which encapsulates information about implicits in flight.
Unfortunately we cannot do that in 2.10.x, because of binary compatibility
concerns, therefore I'm marking this commit as [nomaster] and will be
resubmitting its full version in a separate pull request exclusively
targetting master.
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/macros/Enclosures.scala | 6 | ||||
-rw-r--r-- | src/reflect/scala/reflect/macros/Typers.scala | 6 |
2 files changed, 10 insertions, 2 deletions
diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala index c48656b366..a4ad71c348 100644 --- a/src/reflect/scala/reflect/macros/Enclosures.scala +++ b/src/reflect/scala/reflect/macros/Enclosures.scala @@ -29,8 +29,12 @@ trait Enclosures { */ val enclosingMacros: List[Context] - /** Types along with corresponding trees for which implicit arguments are currently searched. + /** Information about one of the currently considered implicit candidates. + * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, + * hence implicit searches can recursively trigger other implicit searches. + * * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion. + * If we're in an implicit macro being expanded, it's included in this list. * * Unlike `openImplicits`, this is a val, which means that it gets initialized when the context is created * and always stays the same regardless of whatever happens during macro expansion. diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index 427e7854b2..d36636a6d2 100644 --- a/src/reflect/scala/reflect/macros/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -24,8 +24,12 @@ trait Typers { */ def openMacros: List[Context] - /** Types along with corresponding trees for which implicit arguments are currently searched. + /** Information about one of the currently considered implicit candidates. + * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, + * hence implicit searches can recursively trigger other implicit searches. + * * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion. + * If we're in an implicit macro being expanded, it's included in this list. * * Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation, * so it might change depending on what is going on during macro expansion. |