From 84bb943a9d4297c65cb6ba6f3a2dda33987f46ea Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 7 Apr 2009 15:56:59 +0000 Subject: fixed #1775 by making all anonymous functions s... fixed #1775 by making all anonymous functions serializable. Small cleanups elsewhere. --- src/compiler/scala/tools/nsc/javac/JavaParsers.scala | 11 +++-------- src/compiler/scala/tools/nsc/symtab/Names.scala | 7 +++++++ src/compiler/scala/tools/nsc/symtab/Symbols.scala | 20 +++++++++----------- src/compiler/scala/tools/nsc/symtab/Types.scala | 2 +- src/compiler/scala/tools/nsc/transform/CleanUp.scala | 4 +--- .../tools/nsc/typechecker/SyntheticMethods.scala | 6 ++++-- 6 files changed, 25 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index da6726d743..688aff8fd9 100755 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -387,29 +387,24 @@ trait JavaParsers extends JavaScanners { def modifiers(inInterface: Boolean): Modifiers = { var flags: Long = Flags.JAVA // assumed true unless we see public/private/protected - see bug #1240 - var defaultAccess = true var privateWithin: Name = if (inInterface) nme.EMPTY.toTypeName else thisPackageName while (true) { - // if any explicit access modifier is present, we set privateWithin - // to the empty package so the flag is correctly interpreted. - if (List(PUBLIC, PROTECTED, PRIVATE) contains in.token) { - defaultAccess = false - privateWithin = nme.EMPTY.toTypeName - } - in.token match { case AT if (in.lookaheadToken != INTERFACE) => in.nextToken annotation() case PUBLIC => + privateWithin = nme.EMPTY.toTypeName in.nextToken case PROTECTED => flags |= Flags.PROTECTED + //privateWithin = thisPackageName in.nextToken case PRIVATE => flags |= Flags.PRIVATE + privateWithin = nme.EMPTY.toTypeName in.nextToken case STATIC => flags |= Flags.STATIC diff --git a/src/compiler/scala/tools/nsc/symtab/Names.scala b/src/compiler/scala/tools/nsc/symtab/Names.scala index fbc67d51d0..c692f20761 100644 --- a/src/compiler/scala/tools/nsc/symtab/Names.scala +++ b/src/compiler/scala/tools/nsc/symtab/Names.scala @@ -348,6 +348,13 @@ class Names { i > suffix.length } + final def containsName(subname: Name): Boolean = { + var start = 0 + val last = len - subname.length + while (start <= last && !startsWith(subname, start)) start += 1 + start <= last + } + /** Return the subname with characters from start to end-1. * * @param from ... diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 4e1710284b..021a3e1dbe 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -336,9 +336,9 @@ trait Symbols { // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR) - final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME) - // startsWith necessary because name may grow when lifted and also because of anonymous function classes - def isAnonymousFunction = hasFlag(SYNTHETIC) && (originalName startsWith nme.ANON_FUN_NAME) + final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME) // todo: find out why we can't use containsName here. + final def isAnonymousFunction = hasFlag(SYNTHETIC) && (name containsName nme.ANON_FUN_NAME) + final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes final def isModuleClass = isClass && hasFlag(MODULE) final def isPackageClass = isClass && hasFlag(PACKAGE) @@ -378,6 +378,12 @@ trait Symbols { originalName == nme.OUTER } + /** Is this symbol an accessor method for outer? */ + final def isOuterField = { + hasFlag(SYNTHETIC) && + originalName == nme.OUTER_LOCAL + } + /** Does this symbol denote a stable value? */ final def isStable = isTerm && @@ -532,14 +538,6 @@ trait Symbols { else if (isContravariant) -1 else 0 - def isSerializable: Boolean = isMethod || { - val typeSym = info.typeSymbol - isValueType(typeSym) || - typeSym.hasAttribute(SerializableAttr) || - (info.baseClasses exists { bc => (bc hasAttribute SerializableAttr) || (bc == SerializableClass) }) || - (isClass && info.members.forall(_.isSerializable)) - } - // Flags, owner, and name attributes -------------------------------------------------------------- def owner: Symbol = rawowner diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index d61d56474c..dab101a15f 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -3774,7 +3774,7 @@ A type's typeSymbol should never be inspected directly. }) || { val tp1n = normalizePlus(tp1) val tp2n = normalizePlus(tp2) - ((tp1n ne tp1) || (tp2n ne tp2)) && isSubType0(tp1n, tp2n, depth) + ((tp1n ne tp1) || (tp2n ne tp2)) && isSubType(tp1n, tp2n, depth) } } diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 23496807d8..bdf5bede41 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -758,9 +758,7 @@ abstract class CleanUp extends Transform { if (settings.target.value == "jvm-1.4" || settings.target.value == "jvm-1.5") { val sym = cdef.symbol // is this an anonymous function class? - if (sym.hasFlag(SYNTHETIC) && (sym.name.toString.indexOf("anonfun") != -1) && - !sym.hasAttribute(SerializableAttr) && - sym.isSerializable) + if (sym.isAnonymousFunction && !sym.hasAttribute(SerializableAttr)) sym.attributes = AnnotationInfo(definitions.SerializableAttr.tpe, List(), List()) :: sym.attributes } diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 55e484e203..6e55404414 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -208,7 +208,7 @@ trait SyntheticMethods { self: Analyzer => localTyper.typed(methodDef) } - def isSerializable(clazz: Symbol): Boolean = + def hasSerializableAnnotation(clazz: Symbol): Boolean = !clazz.getAttributes(definitions.SerializableAttr).isEmpty def readResolveMethod: Tree = { @@ -314,11 +314,13 @@ trait SyntheticMethods { self: Analyzer => ts += productElementMethod(accessors) } - if (clazz.isModuleClass && isSerializable(clazz)) { + if (clazz.isModuleClass && hasSerializableAnnotation(clazz)) { // If you serialize a singleton and then deserialize it twice, // you will have two instances of your singleton, unless you implement // the readResolve() method (see http://www.javaworld.com/javaworld/ // jw-04-2003/jw-0425-designpatterns_p.html) + // question: should we do this for all serializable singletons, or (as currently done) + // only for those that carry a @serializable annotation? if (!hasImplementation(nme.readResolve)) ts += readResolveMethod } if (!forCLDC && !forMSIL) -- cgit v1.2.3