diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-09-16 15:32:34 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-09-16 15:32:34 +1000 |
commit | 3307e44a9d980eef5a442a688ef22765556f609f (patch) | |
tree | 4ed3921c46e13138a0e16735461128ebbe479ce4 /src | |
parent | 0e2be38f05a6d3fadd0a6c800604503c72401117 (diff) | |
parent | 63207e115a46634d47446a87a7f4bc3c2651b0e7 (diff) | |
download | scala-3307e44a9d980eef5a442a688ef22765556f609f.tar.gz scala-3307e44a9d980eef5a442a688ef22765556f609f.tar.bz2 scala-3307e44a9d980eef5a442a688ef22765556f609f.zip |
Merge pull request #3972 from lrytz/BCodeDelambdafyFix
isAnonymousClass/Function for delambdafy classes is not true
Diffstat (limited to 'src')
4 files changed, 34 insertions, 31 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala index e5b4c4a6c2..0c0d726630 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala @@ -22,14 +22,11 @@ final class BCodeAsmCommon[G <: Global](val global: G) { * null. */ def isAnonymousOrLocalClass(classSym: Symbol): Boolean = { - def isDelambdafyLambdaClass(classSym: Symbol): Boolean = { - classSym.isAnonymousFunction && (settings.Ydelambdafy.value == "method") - } - assert(classSym.isClass, s"not a class: $classSym") - - !isDelambdafyLambdaClass(classSym) && - (classSym.isAnonymousClass || !classSym.originalOwner.isClass) + val res = (classSym.isAnonymousClass || !classSym.originalOwner.isClass) + // lambda classes are always top-level classes. + if (res) assert(!classSym.isDelambdafyFunction) + res } /** @@ -81,7 +78,7 @@ final class BCodeAsmCommon[G <: Global](val global: G) { final case class EnclosingMethodEntry(owner: String, name: String, methodDescriptor: String) /** - * If data for emitting an EnclosingMethod attribute. None if `classSym` is a member class (not + * Data for emitting an EnclosingMethod attribute. None if `classSym` is a member class (not * an anonymous or local class). See doc in BTypes. * * The class is parametrized by two functions to obtain a bytecode class descriptor for a class diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 9cc8d779a0..12e7b23f48 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -245,18 +245,22 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // - make `anonClass.isAnonymousClass` true. // - use `newAnonymousClassSymbol` or push the required variations into a similar factory method // - reinstate the assertion in `Erasure.resolveAnonymousBridgeClash` - val suffix = "$lambda$" + ( + val suffix = nme.DELAMBDAFY_LAMBDA_CLASS_NAME + "$" + ( if (funOwner.isPrimaryConstructor) "" else "$" + funOwner.name + "$" ) - val name = unit.freshTypeName(s"${oldClass.name.decode}$suffix") + val oldClassPart = oldClass.name.decode + // make sure the class name doesn't contain $anon, otherwsie isAnonymousClass/Function may be true + val name = unit.freshTypeName(s"$oldClassPart$suffix".replace("$anon", "$nestedInAnon")) - val anonClass = pkg newClassSymbol(name, originalFunction.pos, FINAL | SYNTHETIC) addAnnotation SerialVersionUIDAnnotation - anonClass setInfo ClassInfoType(parents, newScope, anonClass) + val lambdaClass = pkg newClassSymbol(name, originalFunction.pos, FINAL | SYNTHETIC) addAnnotation SerialVersionUIDAnnotation + lambdaClass setInfo ClassInfoType(parents, newScope, lambdaClass) + assert(!lambdaClass.isAnonymousClass && !lambdaClass.isAnonymousFunction, "anonymous class name: "+ lambdaClass.name) + assert(lambdaClass.isDelambdafyFunction, "not lambda class name: " + lambdaClass.name) val captureProxies2 = new LinkedHashMap[Symbol, TermSymbol] captures foreach {capture => - val sym = anonClass.newVariable(capture.name.toTermName, capture.pos, SYNTHETIC) + val sym = lambdaClass.newVariable(capture.name.toTermName, capture.pos, SYNTHETIC) sym setInfo capture.info captureProxies2 += ((capture, sym)) } @@ -266,30 +270,30 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val thisProxy = { val target = targetMethod(originalFunction) if (thisReferringMethods contains target) { - val sym = anonClass.newVariable(nme.FAKE_LOCAL_THIS, originalFunction.pos, SYNTHETIC) + val sym = lambdaClass.newVariable(nme.FAKE_LOCAL_THIS, originalFunction.pos, SYNTHETIC) sym.info = oldClass.tpe sym } else NoSymbol } - val decapturify = new DeCapturifyTransformer(captureProxies2, unit, oldClass, anonClass, originalFunction.symbol.pos, thisProxy) + val decapturify = new DeCapturifyTransformer(captureProxies2, unit, oldClass, lambdaClass, originalFunction.symbol.pos, thisProxy) val accessorMethod = createAccessorMethod(thisProxy, originalFunction) val decapturedFunction = decapturify.transform(originalFunction).asInstanceOf[Function] val members = (optionSymbol(thisProxy).toList ++ (captureProxies2 map (_._2))) map {member => - anonClass.info.decls enter member + lambdaClass.info.decls enter member ValDef(member, gen.mkZero(member.tpe)) setPos decapturedFunction.pos } // constructor - val constr = createConstructor(anonClass, members) + val constr = createConstructor(lambdaClass, members) // apply method with same arguments and return type as original lambda. - val applyMethodDef = createApplyMethod(anonClass, decapturedFunction, accessorMethod, thisProxy) + val applyMethodDef = createApplyMethod(lambdaClass, decapturedFunction, accessorMethod, thisProxy) - val bridgeMethod = createBridgeMethod(anonClass, originalFunction, applyMethodDef) + val bridgeMethod = createBridgeMethod(lambdaClass, originalFunction, applyMethodDef) def fulldef(sym: Symbol) = if (sym == NoSymbol) sym.toString @@ -305,7 +309,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val body = members ++ List(constr, applyMethodDef) ++ bridgeMethod // TODO if member fields are private this complains that they're not accessible - (localTyper.typedPos(decapturedFunction.pos)(ClassDef(anonClass, body)).asInstanceOf[ClassDef], thisProxy, accessorMethod) + (localTyper.typedPos(decapturedFunction.pos)(ClassDef(lambdaClass, body)).asInstanceOf[ClassDef], thisProxy, accessorMethod) } val (anonymousClassDef, thisProxy, accessorMethod) = makeAnonymousClass diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index d203218c09..99ff6a10b4 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -99,17 +99,18 @@ trait StdNames { val SINGLETON_SUFFIX: String = ".type" - val ANON_CLASS_NAME: NameType = "$anon" - val ANON_FUN_NAME: NameType = "$anonfun" - val EMPTY: NameType = "" - val EMPTY_PACKAGE_NAME: NameType = "<empty>" - val IMPL_CLASS_SUFFIX = "$class" - val IMPORT: NameType = "<import>" - val MODULE_SUFFIX_NAME: NameType = MODULE_SUFFIX_STRING - val MODULE_VAR_SUFFIX: NameType = "$module" - val PACKAGE: NameType = "package" - val ROOT: NameType = "<root>" - val SPECIALIZED_SUFFIX: NameType = "$sp" + val ANON_CLASS_NAME: NameType = "$anon" + val DELAMBDAFY_LAMBDA_CLASS_NAME: NameType = "$lambda" + val ANON_FUN_NAME: NameType = "$anonfun" + val EMPTY: NameType = "" + val EMPTY_PACKAGE_NAME: NameType = "<empty>" + val IMPL_CLASS_SUFFIX = "$class" + val IMPORT: NameType = "<import>" + val MODULE_SUFFIX_NAME: NameType = MODULE_SUFFIX_STRING + val MODULE_VAR_SUFFIX: NameType = "$module" + val PACKAGE: NameType = "package" + val ROOT: NameType = "<root>" + val SPECIALIZED_SUFFIX: NameType = "$sp" // value types (and AnyRef) are all used as terms as well // as (at least) arguments to the @specialize annotation. diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 2670faa22d..44fce2c9ab 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -789,6 +789,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) && !isMacro && !isSpecialized final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME) + final def isDelambdafyFunction = isSynthetic && (name containsName tpnme.DELAMBDAFY_LAMBDA_CLASS_NAME) final def isDefinedInPackage = effectiveOwner.isPackageClass final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass |