diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-06-14 11:22:29 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2015-04-21 16:51:01 +1000 |
commit | d12d59a178c4056fb8ea3cdf4eab5ef453c9a113 (patch) | |
tree | e1c15f8f484db26b48d1c4ae3bed4277804a450d | |
parent | e1895d64f87dc3c699a3ccbc8a3143b18d3b5bb1 (diff) | |
download | scala-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
```
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)) |