diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-10-30 11:48:08 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-10-30 11:48:08 +1000 |
commit | d056439a2762b342f66759de654f0dadb01f5e9a (patch) | |
tree | 27409f6ecd5ce1ebd855b8b5c2e4a346b881152f /src | |
parent | bdae51d6a8f18a5456a32c350cb551d42a3cb6c6 (diff) | |
download | scala-d056439a2762b342f66759de654f0dadb01f5e9a.tar.gz scala-d056439a2762b342f66759de654f0dadb01f5e9a.tar.bz2 scala-d056439a2762b342f66759de654f0dadb01f5e9a.zip |
SI-8947 Avoid cross talk between tag materializers and reify
After a macro has been expanded, the expandee are expansion are
bidirectionally linked with tree attachments. Reify uses the back
reference to replace the expansion with the expandee in the reified
tree. It also has some special cases to replace calls to macros
defined in scala-compiler.jar with `Predef.implicitly[XxxTag[T]]`.
This logic lives in `Reshape`.
However, the expansion of a macro may be `EmptyTree`. This is the case
when a tag materializer macro fails. User defined macros could do the
also expand to `EmptyTree`. In the enclosed test case, the error
message that the tag materializer issued ("cannot materialize
class tag for unsplicable type") is not displayed as the typechecker
finds another means of making the surrounding expression typecheck.
However, the macro engine attaches a backreference to the materializer
macro on `EmpytyTree`!
Later, when `reify` reshapes a tree, every occurance of `EmptyTree`
will be replaced by a call to `implicitly`.
This commit expands the domain of `CannotHaveAttrs`, which is mixed
in to `EmptyTree`. It silently ignores all attempts to mutate
attachments.
Unlike similar code that discards mutations of its type and position,
I have refrained from issuing a developer warning in this case, as
to silence this I would need to go and add a special case at any
places adding attachments.
Diffstat (limited to 'src')
-rw-r--r-- | src/reflect/scala/reflect/internal/Trees.scala | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 9dc4baee32..26e9c7f89d 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -10,6 +10,7 @@ package internal import Flags._ import pickling.PickleFormat._ import scala.collection.{ mutable, immutable } +import scala.reflect.macros.Attachments import util.Statistics trait Trees extends api.Trees { @@ -1075,6 +1076,12 @@ trait Trees extends api.Trees { override def setType(t: Type) = { requireLegal(t, NoType, "tpe"); this } override def tpe_=(t: Type) = setType(t) + // We silently ignore attempts to add attachments to `EmptyTree`. See SI-8947 for an + // example of a bug in macro expansion that this solves. + override def setAttachments(attachments: Attachments {type Pos = Position}): this.type = this + override def updateAttachment[T: ClassTag](attachment: T): this.type = this + override def removeAttachment[T: ClassTag]: this.type = this + private def requireLegal(value: Any, allowed: Any, what: String) = ( if (value != allowed) { log(s"can't set $what for $self to value other than $allowed") |