summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Iry <james.iry@typesafe.com>2013-08-28 20:48:47 -0700
committerJames Iry <james.iry@typesafe.com>2013-11-06 12:28:20 -0800
commit13ea5909ea25e4bad184e9e4581d94230dc11d9f (patch)
tree9e7ccbe84eeb38c7f0e6d897e40b57fb05e1d040
parentf27f2d80d759130597b652d6cc9d789f8c472e5a (diff)
downloadscala-13ea5909ea25e4bad184e9e4581d94230dc11d9f.tar.gz
scala-13ea5909ea25e4bad184e9e4581d94230dc11d9f.tar.bz2
scala-13ea5909ea25e4bad184e9e4581d94230dc11d9f.zip
Make specialization aware of anonymous functions.
During development of late delmabdafying there was a problem where specialization would undo some of the work done in uncurry if the body of the lambda had a constant type. That would result in a compiler crash as when the delambdafy phase got a tree shape it didn't understand. This commit has a fix and a test.
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala13
-rw-r--r--test/files/specialized/constant_lambda.check2
-rw-r--r--test/files/specialized/constant_lambda.scala16
4 files changed, 36 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 2d4269a3bc..4cf3bef939 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -55,6 +55,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
import definitions._
import Flags._
+ private val inlineFunctionExpansion = settings.Ydelambdafy.value == "inline"
+
/** the name of the phase: */
val phaseName: String = "specialize"
@@ -1318,7 +1320,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
private def isAccessible(sym: Symbol): Boolean =
- (currentClass == sym.owner.enclClass) && (currentClass != targetClass)
+ if (currentOwner.isAnonymousFunction) {
+ if (inlineFunctionExpansion) devWarning("anonymous function made it to specialization even though inline expansion is set.")
+ false
+ }
+ else (currentClass == sym.owner.enclClass) && (currentClass != targetClass)
private def shouldMakePublic(sym: Symbol): Boolean =
sym.hasFlag(PRIVATE | PROTECTED) && (addressFields || !nme.isLocalName(sym.name))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index 396f3407f3..69ae6ec0c8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -136,8 +136,8 @@ abstract class Duplicators extends Analyzer {
sym
private def invalidate(tree: Tree, owner: Symbol = NoSymbol) {
- debuglog("attempting to invalidate " + tree.symbol)
- if (tree.isDef && tree.symbol != NoSymbol) {
+ debuglog(s"attempting to invalidate symbol = ${tree.symbol}")
+ if ((tree.isDef || tree.isInstanceOf[Function]) && tree.symbol != NoSymbol) {
debuglog("invalid " + tree.symbol)
invalidSyms(tree.symbol) = tree
@@ -166,6 +166,11 @@ abstract class Duplicators extends Analyzer {
invalidateAll(tparams ::: vparamss.flatten)
tree.symbol = NoSymbol
+ case Function(vparams, _) =>
+ // invalidate parameters
+ invalidateAll(vparams)
+ tree.symbol = NoSymbol
+
case _ =>
tree.symbol = NoSymbol
}
@@ -226,6 +231,10 @@ abstract class Duplicators extends Analyzer {
ddef.tpt modifyType fixType
super.typed(ddef.clearType(), mode, pt)
+ case fun: Function =>
+ debuglog("Clearing the type and retyping Function: " + fun)
+ super.typed(fun.clearType, mode, pt)
+
case vdef @ ValDef(mods, name, tpt, rhs) =>
// log("vdef fixing tpe: " + tree.tpe + " with sym: " + tree.tpe.typeSymbol + " and " + invalidSyms)
//if (mods.hasFlag(Flags.LAZY)) vdef.symbol.resetFlag(Flags.MUTABLE) // Martin to Iulian: lazy vars can now appear because they are no longer boxed; Please check that deleting this statement is OK.
diff --git a/test/files/specialized/constant_lambda.check b/test/files/specialized/constant_lambda.check
new file mode 100644
index 0000000000..4b095fd0ff
--- /dev/null
+++ b/test/files/specialized/constant_lambda.check
@@ -0,0 +1,2 @@
+false
+false
diff --git a/test/files/specialized/constant_lambda.scala b/test/files/specialized/constant_lambda.scala
new file mode 100644
index 0000000000..bb9a97403e
--- /dev/null
+++ b/test/files/specialized/constant_lambda.scala
@@ -0,0 +1,16 @@
+// during development of late delmabdafying there was a problem where
+// specialization would undo some of the work done in uncurry if the body of the
+// lambda had a constant type. That would result in a compiler crash as
+// when the delambdafy phase got a tree shape it didn't understand
+class X[@specialized(Int) A] {
+ val f = { x: A => false }
+}
+
+object Test {
+ def main(args: Array[String]) {
+ val xInt = new X[Int]
+ println(xInt.f(42))
+ val xString = new X[String]
+ println(xString.f("hello"))
+ }
+} \ No newline at end of file