summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenSymbols.scala2
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTrees.scala24
-rw-r--r--src/compiler/scala/reflect/reify/utils/Extractors.scala8
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala7
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala2
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala6
-rw-r--r--test/files/run/reify_newimpl_30.check3
-rw-r--r--test/files/run/reify_newimpl_30.scala7
-rw-r--r--test/files/run/t6591_1.check1
-rw-r--r--test/files/run/t6591_1.scala19
-rw-r--r--test/files/run/t6591_2.check1
-rw-r--r--test/files/run/t6591_2.scala19
-rw-r--r--test/files/run/t6591_3.check1
-rw-r--r--test/files/run/t6591_3.scala17
-rw-r--r--test/files/run/t6591_5.check1
-rw-r--r--test/files/run/t6591_5.scala23
-rw-r--r--test/files/run/t6591_6.check1
-rw-r--r--test/files/run/t6591_6.scala24
-rw-r--r--test/pending/run/t6591_4.check1
-rw-r--r--test/pending/run/t6591_4.scala17
21 files changed, 165 insertions, 20 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
index 22a834d2e4..0d795e3783 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
@@ -100,6 +100,8 @@ 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
if (sym.isCapturedVariable) {
assert(binding.isInstanceOf[Ident], showRaw(binding))
val capturedBinding = referenceCapturedVariable(sym)
diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
index 06e287f62f..7c7a79e774 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
@@ -163,11 +163,11 @@ trait GenTrees {
}
}
- private def reifyBoundType(tree: Tree): Tree = {
+ private def reifyBoundType(tree: RefTree): Tree = {
val sym = tree.symbol
val tpe = tree.tpe
- def reifyBoundType(tree: Tree): Tree = {
+ def reifyBoundType(tree: RefTree): Tree = {
assert(tpe != null, "unexpected: bound type that doesn't have a tpe: " + showRaw(tree))
// if a symbol or a type of the scrutinee are local to reifee
@@ -196,13 +196,19 @@ trait GenTrees {
mirrorBuildCall(nme.TypeTree, spliced)
}
}
- else if (sym.isLocatable) {
- if (reifyDebug) println("tpe is locatable: reify as Ident(%s)".format(sym))
- mirrorBuildCall(nme.Ident, reify(sym))
- }
- else {
- if (reifyDebug) println("tpe is not locatable: reify as TypeTree(%s)".format(tpe))
- mirrorBuildCall(nme.TypeTree, reify(tpe))
+ else tree match {
+ case Select(qual, name) if !qual.symbol.isPackage && !qual.symbol.isPackageObject && qual.symbol != definitions.PredefModule =>
+ if (reifyDebug) println(s"reifying Select($qual, $name)")
+ mirrorCall(nme.Select, reify(qual), reify(name))
+ case SelectFromTypeTree(qual, name) =>
+ if (reifyDebug) println(s"reifying SelectFromTypeTree($qual, $name)")
+ mirrorCall(nme.SelectFromTypeTree, reify(qual), reify(name))
+ case _ if sym.isLocatable =>
+ if (reifyDebug) println(s"tpe is locatable: reify as Ident($sym)")
+ mirrorBuildCall(nme.Ident, reify(sym))
+ case _ =>
+ if (reifyDebug) println(s"tpe is not locatable: reify as TypeTree($tpe)")
+ mirrorBuildCall(nme.TypeTree, reify(tpe))
}
}
}
diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala
index ebbcb95481..134ae13890 100644
--- a/src/compiler/scala/reflect/reify/utils/Extractors.scala
+++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala
@@ -263,12 +263,12 @@ trait Extractors {
}
object BoundType {
- def unapply(tree: Tree): Option[Tree] = tree match {
- case Select(_, name) if name.isTypeName =>
+ def unapply(tree: Tree): Option[RefTree] = tree match {
+ case tree @ Select(_, name) if name.isTypeName =>
Some(tree)
- case SelectFromTypeTree(_, name) if name.isTypeName =>
+ case tree @ SelectFromTypeTree(_, _) =>
Some(tree)
- case Ident(name) if name.isTypeName =>
+ case tree @ Ident(name) if name.isTypeName =>
Some(tree)
case _ =>
None
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 95135b84e0..fdc790a920 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -212,7 +212,11 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName))
def makeParam(schema: (FreeTermSymbol, TermName)) = {
val (fv, name) = schema
- meth.newValueParameter(name) setInfo appliedType(definitions.FunctionClass(0).tpe, List(fv.tpe.resultType))
+ /* Free term symbol `fv` can contain flag <stable> which was set by
+ * `scala.reflect.reify.codegen.GenSymbols.reifyFreeTerm` method.
+ * It is recovered here, so value parameter can pass `isExprSafeToInline`
+ * test in `scala.reflect.internal.TreeInfo`. */
+ meth.newValueParameter(name, newFlags = if (fv.hasStableFlag) Flags.STABLE else 0) setInfo appliedType(definitions.FunctionClass(0).tpe, List(fv.tpe.resultType))
}
meth setInfo MethodType(freeTerms.map(makeParam).toList, AnyClass.tpe)
minfo.decls enter meth
@@ -418,4 +422,3 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
def eval(tree: u.Tree): Any = compile(tree)()
}
}
-
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index a0362c8921..5853315479 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -274,7 +274,7 @@ class Flags extends ModifierFlags {
* from Modifiers. Others which may be applied at creation time are:
* SYNTHETIC.
*/
- final val ValueParameterFlags = BYNAMEPARAM | IMPLICIT | DEFAULTPARAM
+ final val ValueParameterFlags = BYNAMEPARAM | IMPLICIT | DEFAULTPARAM | STABLE
final val BeanPropertyFlags = DEFERRED | OVERRIDE | STATIC
final val VarianceFlags = COVARIANT | CONTRAVARIANT
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index ddc5d94e70..bcda2bc1ae 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -607,6 +607,7 @@ trait StdNames {
val RootPackage: NameType = "RootPackage"
val RootClass: NameType = "RootClass"
val Select: NameType = "Select"
+ val SelectFromTypeTree: NameType = "SelectFromTypeTree"
val StringContext: NameType = "StringContext"
val This: NameType = "This"
val ThisType: NameType = "ThisType"
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 8b5dc80c83..f83106aaef 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -89,6 +89,12 @@ abstract class TreeInfo {
tree.symbol.isStable && isExprSafeToInline(qual)
case TypeApply(fn, _) =>
isExprSafeToInline(fn)
+ /* Special case for reified free terms. During reflective compilation,
+ * reified value recovered flag <stable> from free term and wrapped into a
+ * Function object, so it can pass stability check here to become a stable
+ * identifier.*/
+ case Apply(Select(free @ Ident(_), nme.apply), _) if free.symbol.name endsWith nme.REIFY_FREE_VALUE_SUFFIX =>
+ free.symbol.hasStableFlag && isExprSafeToInline(free)
case Apply(fn, List()) =>
/* Note: After uncurry, field accesses are represented as Apply(getter, Nil),
* so an Apply can also be pure.
diff --git a/test/files/run/reify_newimpl_30.check b/test/files/run/reify_newimpl_30.check
index c23af69b08..29baac911e 100644
--- a/test/files/run/reify_newimpl_30.check
+++ b/test/files/run/reify_newimpl_30.check
@@ -1 +1,2 @@
-List(2)
+reflective toolbox has failed:
+unresolved free type variables (namely: C defined by <local Test> in reify_newimpl_30.scala:7:11). have you forgot to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types
diff --git a/test/files/run/reify_newimpl_30.scala b/test/files/run/reify_newimpl_30.scala
index 573d05a630..bc34f1bb6c 100644
--- a/test/files/run/reify_newimpl_30.scala
+++ b/test/files/run/reify_newimpl_30.scala
@@ -1,5 +1,5 @@
import scala.reflect.runtime.universe._
-import scala.tools.reflect.ToolBox
+import scala.tools.reflect.{ ToolBox, ToolBoxError }
import scala.tools.reflect.Eval
object Test extends App {
@@ -9,9 +9,10 @@ object Test extends App {
val code = reify {
List[C#T](2)
}
- println(code.eval)
+ try { println(code.eval) }
+ catch { case e: ToolBoxError => println(e.getMessage) }
}
new C
}
-} \ No newline at end of file
+}
diff --git a/test/files/run/t6591_1.check b/test/files/run/t6591_1.check
new file mode 100644
index 0000000000..b6cb6c286d
--- /dev/null
+++ b/test/files/run/t6591_1.check
@@ -0,0 +1 @@
+Block(List(ValDef(Modifiers(), newTermName("v"), Select(Ident(A), newTypeName("I")), Select(Ident(A), newTermName("impl")))), Ident(newTermName("v")))
diff --git a/test/files/run/t6591_1.scala b/test/files/run/t6591_1.scala
new file mode 100644
index 0000000000..6dd9a1d9fb
--- /dev/null
+++ b/test/files/run/t6591_1.scala
@@ -0,0 +1,19 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.ToolBox
+import scala.tools.reflect.Eval
+
+trait O { trait I }
+
+object A extends O {
+ val impl = new I {}
+}
+
+object Test extends App {
+ val code = reify {
+ val v: A.I = A.impl
+ v
+ }
+ println(showRaw(code.tree))
+
+ val v: A.I = code.eval
+}
diff --git a/test/files/run/t6591_2.check b/test/files/run/t6591_2.check
new file mode 100644
index 0000000000..b2d5797cbf
--- /dev/null
+++ b/test/files/run/t6591_2.check
@@ -0,0 +1 @@
+Block(List(ValDef(Modifiers(), newTermName("v"), SelectFromTypeTree(Ident(A), newTypeName("I")), Select(Apply(Select(New(Ident(A)), nme.CONSTRUCTOR), List()), newTermName("impl")))), Ident(newTermName("v")))
diff --git a/test/files/run/t6591_2.scala b/test/files/run/t6591_2.scala
new file mode 100644
index 0000000000..6214308dab
--- /dev/null
+++ b/test/files/run/t6591_2.scala
@@ -0,0 +1,19 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.ToolBox
+import scala.tools.reflect.Eval
+
+trait O { trait I }
+
+class A extends O {
+ val impl = new I {}
+}
+
+object Test extends App {
+ val code = reify {
+ val v: A#I = (new A).impl
+ v
+ }
+ println(showRaw(code.tree))
+
+ val v: A#I = code.eval
+}
diff --git a/test/files/run/t6591_3.check b/test/files/run/t6591_3.check
new file mode 100644
index 0000000000..a7b594ba65
--- /dev/null
+++ b/test/files/run/t6591_3.check
@@ -0,0 +1 @@
+Block(List(ValDef(Modifiers(), newTermName("v"), Select(This(newTypeName("A")), newTypeName("I")), Apply(Select(New(Select(This(newTypeName("A")), newTypeName("I"))), nme.CONSTRUCTOR), List()))), Ident(newTermName("v")))
diff --git a/test/files/run/t6591_3.scala b/test/files/run/t6591_3.scala
new file mode 100644
index 0000000000..b73a7baf48
--- /dev/null
+++ b/test/files/run/t6591_3.scala
@@ -0,0 +1,17 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.ToolBox
+import scala.tools.reflect.Eval
+
+class O { class I }
+
+object A extends O {
+ val code = reify {
+ val v: I = new I
+ v
+ }
+ println(showRaw(code.tree))
+}
+
+object Test extends App {
+ val v: A.I = A.code.eval
+}
diff --git a/test/files/run/t6591_5.check b/test/files/run/t6591_5.check
new file mode 100644
index 0000000000..8f1c2b3ede
--- /dev/null
+++ b/test/files/run/t6591_5.check
@@ -0,0 +1 @@
+Expr(Block(List(ValDef(Modifiers(), newTermName("v"), Select(Select(This(newTypeName("A")), newTermName("x")), newTypeName("I")), Select(Select(This(newTypeName("scala")), newTermName("Predef")), newTermName("$qmark$qmark$qmark")))), Ident(newTermName("v"))))
diff --git a/test/files/run/t6591_5.scala b/test/files/run/t6591_5.scala
new file mode 100644
index 0000000000..18d6f90a9b
--- /dev/null
+++ b/test/files/run/t6591_5.scala
@@ -0,0 +1,23 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.ToolBox
+import scala.tools.reflect.Eval
+import java.lang.reflect.InvocationTargetException
+
+class O { class I }
+
+object A extends O {
+ val x = new O
+ val code = reify {
+ val v: x.I = ???
+ v
+ }
+ println(showRaw(code))
+}
+
+object Test extends App {
+ try {
+ val v: A.x.I = A.code.eval
+ } catch {
+ case ex: InvocationTargetException if ex.getCause.isInstanceOf[NotImplementedError] =>
+ }
+}
diff --git a/test/files/run/t6591_6.check b/test/files/run/t6591_6.check
new file mode 100644
index 0000000000..5ddf7600f1
--- /dev/null
+++ b/test/files/run/t6591_6.check
@@ -0,0 +1 @@
+Expr(Block(List(ValDef(Modifiers(), newTermName("v"), Select(Select(Ident(newTermName("A")), newTermName("x")), newTypeName("I")), Select(Select(This(newTypeName("scala")), newTermName("Predef")), newTermName("$qmark$qmark$qmark")))), Ident(newTermName("v"))))
diff --git a/test/files/run/t6591_6.scala b/test/files/run/t6591_6.scala
new file mode 100644
index 0000000000..2eee87928d
--- /dev/null
+++ b/test/files/run/t6591_6.scala
@@ -0,0 +1,24 @@
+import scala.language.existentials
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.ToolBox
+import scala.tools.reflect.Eval
+import java.lang.reflect.InvocationTargetException
+
+class O { class I }
+
+class A extends O {
+ val x = new O
+ val code = reify {
+ val v: x.I = ???
+ v
+ }
+ println(showRaw(code))
+}
+
+object Test extends App {
+ try {
+ val v = (new A).code.eval
+ } catch {
+ case ex: InvocationTargetException if ex.getCause.isInstanceOf[NotImplementedError] =>
+ }
+}
diff --git a/test/pending/run/t6591_4.check b/test/pending/run/t6591_4.check
new file mode 100644
index 0000000000..0f1c0489e9
--- /dev/null
+++ b/test/pending/run/t6591_4.check
@@ -0,0 +1 @@
+Expr(Block(List(ValDef(Modifiers(), newTermName("v"), Select(Ident(newTermName("A")), newTypeName("I")), Apply(Select(New(Select(Ident(newTermName("A")), newTypeName("I"))), nme.CONSTRUCTOR), List()))), Ident(newTermName("v"))))
diff --git a/test/pending/run/t6591_4.scala b/test/pending/run/t6591_4.scala
new file mode 100644
index 0000000000..f20c8e6127
--- /dev/null
+++ b/test/pending/run/t6591_4.scala
@@ -0,0 +1,17 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.ToolBox
+import scala.tools.reflect.Eval
+
+class O { class I }
+
+class A extends O {
+ val code = reify {
+ val v: I = new I
+ v
+ }
+ println(showRaw(code))
+}
+
+object Test extends App {
+ val v: A#I = (new A).code.eval
+}