diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-02-08 14:08:30 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-02-08 15:40:16 +0100 |
commit | 57c0e63ba18c5845772d737570342e4054af459f (patch) | |
tree | d912c790cea5a732abf3f1a748096789611ff7ea /src/compiler/scala/reflect/reify/codegen/GenSymbols.scala | |
parent | ce867c74572b51cfcb6ac3e3bfa9dce36cc0b638 (diff) | |
download | scala-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.scala | 31 |
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) |