summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2013-02-08 14:08:30 +0100
committerEugene Burmako <xeno.by@gmail.com>2013-02-08 15:40:16 +0100
commit57c0e63ba18c5845772d737570342e4054af459f (patch)
treed912c790cea5a732abf3f1a748096789611ff7ea /src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
parentce867c74572b51cfcb6ac3e3bfa9dce36cc0b638 (diff)
downloadscala-57c0e63ba18c5845772d737570342e4054af459f.tar.gz
scala-57c0e63ba18c5845772d737570342e4054af459f.tar.bz2
scala-57c0e63ba18c5845772d737570342e4054af459f.zip
accommodates pull request feedback
https://github.com/scala/scala/pull/2072
Diffstat (limited to 'src/compiler/scala/reflect/reify/codegen/GenSymbols.scala')
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenSymbols.scala31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
index 0d795e3783..47c966ea24 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
@@ -1,6 +1,8 @@
package scala.reflect.reify
package codegen
+import scala.reflect.internal.Flags._
+
trait GenSymbols {
self: Reifier =>
@@ -100,8 +102,33 @@ trait GenSymbols {
reifyIntoSymtab(binding.symbol) { sym =>
if (reifyDebug) println("Free term" + (if (sym.isCapturedVariable) " (captured)" else "") + ": " + sym + "(" + sym.accurateKindString + ")")
val name = newTermName(nme.REIFY_FREE_PREFIX + sym.name + (if (sym.isType) nme.REIFY_FREE_THIS_SUFFIX else ""))
- // Flag <stable> is set here to make reified free value pass stability test during reflective compilation
- if (!sym.isMutable) sym setFlag reflect.internal.Flags.STABLE
+ // We need to note whether the free value being reified is stable or not to guide subsequent reflective compilation.
+ // Here's why reflection compilation needs our help.
+ //
+ // When dealing with a tree, which contain free values, toolboxes extract those and wrap the entire tree in a Function
+ // having parameters defined for every free values in the tree. For example, evaluating
+ //
+ // Ident(setTypeSignature(newFreeTerm("x", 2), <Int>))
+ //
+ // Will generate something like
+ //
+ // object wrapper {
+ // def wrapper(x: () => Int) = {
+ // x()
+ // }
+ // }
+ //
+ // Note that free values get transformed into, effectively, by-name parameters. This is done to make sure
+ // that evaluation order is kept intact. And indeed, we cannot just evaluate all free values at once in order
+ // to obtain arguments for wrapper.wrapper, because if some of the free values end up being unused during evaluation,
+ // we might end up doing unnecessary calculations.
+ //
+ // So far, so good - we didn't need any flags at all. However, if the code being reified contains path-dependent types,
+ // we're in trouble, because valid code like `free.T` ends up being transformed into `free.apply().T`, which won't compile.
+ //
+ // To overcome this glitch, we note whether a given free term is stable or not (because vars can also end up being free terms).
+ // Then, if a free term is stable, we tell the compiler to treat `free.apply()` specially and assume that it's stable.
+ if (!sym.isMutable) sym setFlag STABLE
if (sym.isCapturedVariable) {
assert(binding.isInstanceOf[Ident], showRaw(binding))
val capturedBinding = referenceCapturedVariable(sym)