summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-06-14 11:22:29 +0200
committerJason Zaugg <jzaugg@gmail.com>2015-04-21 16:51:01 +1000
commitd12d59a178c4056fb8ea3cdf4eab5ef453c9a113 (patch)
treee1c15f8f484db26b48d1c4ae3bed4277804a450d /src
parente1895d64f87dc3c699a3ccbc8a3143b18d3b5bb1 (diff)
downloadscala-d12d59a178c4056fb8ea3cdf4eab5ef453c9a113.tar.gz
scala-d12d59a178c4056fb8ea3cdf4eab5ef453c9a113.tar.bz2
scala-d12d59a178c4056fb8ea3cdf4eab5ef453c9a113.zip
Support specialized method-handle based lambdas
``` scala> (x: Int) => {??? : Int} res2: Int => Int = $$Lambda$1371/1961176822@6ed3ccb2 scala> res2(42) scala.NotImplementedError: an implementation is missing at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225) at .$anonfun$1(<console>:8) at $$Lambda$1371/1961176822.apply$mcII$sp(Unknown Source) ... 33 elided scala> (x: Int, y: Long) => {??? : Int} res4: (Int, Long) => Int = $$Lambda$1382/1796047085@6f8e8894 scala> res4(0, 0L) scala.NotImplementedError: an implementation is missing at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225) at .$anonfun$1(<console>:8) at $$Lambda$1382/1796047085.apply$mcIIJ$sp(Unknown Source) ... 33 elided ```
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Delambdafy.scala15
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala17
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala2
3 files changed, 27 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
index 315d96d2e9..548f34d9b9 100644
--- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
+++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
@@ -308,11 +308,16 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
val functionalInterface: Symbol = {
val sym = originalFunction.tpe.typeSymbol
val pack = currentRun.runDefinitions.Scala_Java8_CompatPackage
- val returnUnit = restpe.typeSymbol == UnitClass
- val functionInterfaceArray =
- if (returnUnit) currentRun.runDefinitions.Scala_Java8_CompatPackage_JProcedure
- else currentRun.runDefinitions.Scala_Java8_CompatPackage_JFunction
- functionInterfaceArray.apply(arity)
+ val name1 = specializeTypes.specializedFunctionName(sym, originalFunction.tpe.typeArgs)
+ if (name1.toTypeName == sym.name) {
+ val returnUnit = restpe.typeSymbol == UnitClass
+ val functionInterfaceArray =
+ if (returnUnit) currentRun.runDefinitions.Scala_Java8_CompatPackage_JProcedure
+ else currentRun.runDefinitions.Scala_Java8_CompatPackage_JFunction
+ functionInterfaceArray.apply(arity)
+ } else {
+ pack.info.decl(name1.toTypeName.prepend("J"))
+ }
}
if (functionalInterface.exists) {
val captureArgs = captures.iterator.map(capture => gen.mkAttributedRef(capture) setPos originalFunction.pos).toList
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 086512677e..4f834d31ff 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -303,6 +303,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
+ def specializedFunctionName(sym: Symbol, args: List[Type]) = exitingSpecialize {
+ require(isFunctionSymbol(sym), sym)
+ val env: TypeEnv = TypeEnv.fromSpecialization(sym, args)
+ specializedClass.get((sym, env)) match {
+ case Some(x) =>
+ x.name
+ case None =>
+ sym.name
+ }
+ }
+
/** Return the specialized name of 'sym' in the given environment. It
* guarantees the same result regardless of the map order by sorting
* type variables alphabetically.
@@ -315,10 +326,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (sym.isClass) env.keySet
else specializedTypeVars(sym).intersect(env.keySet)
)
+ specializedName(sym.name, tvars, env)
+ }
+
+ private def specializedName(name: Name, tvars: immutable.Set[Symbol], env: TypeEnv): TermName = {
val (methparams, others) = tvars.toList sortBy ("" + _.name) partition (_.owner.isMethod)
// debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars)
- specializedName(sym.name, methparams map env, others map env)
+ specializedName(name, methparams map env, others map env)
}
/** Specialize name for the two list of types. The first one denotes
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 6484d96a52..836ea808ac 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -237,7 +237,7 @@ abstract class UnCurry extends InfoTransform
def canUseDelamdafyMethod = (
(inConstructorFlag == 0) // Avoiding synthesizing code prone to SI-6666, SI-8363 by using old-style lambda translation
- && !isSpecialized // DelambdafyTransformer currently only emits generic FunctionN-s, use the old style in the meantime
+ && (!isSpecialized || (settings.target.value == "jvm-1.8")) // DelambdafyTransformer currently only emits generic FunctionN-s, use the old style in the meantime
)
if (inlineFunctionExpansion || !canUseDelamdafyMethod) {
val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe))