summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2010-11-30 15:38:56 +0000
committerLukas Rytz <lukas.rytz@epfl.ch>2010-11-30 15:38:56 +0000
commit4be5e11cccace4974ed9a449052455392570139f (patch)
tree88c86bc65b88df08b48584ed791acd1619983c0c /src/compiler
parent402d96dd3fab6ae677966a9a258c00b3f34a37ed (diff)
downloadscala-4be5e11cccace4974ed9a449052455392570139f.tar.gz
scala-4be5e11cccace4974ed9a449052455392570139f.tar.bz2
scala-4be5e11cccace4974ed9a449052455392570139f.zip
Deprecated the @serializable annotation, introd...
Deprecated the @serializable annotation, introduce a new trait "scala.Serializable" which has to be extended instead (cross-platform). Known issues: - Companion objects of serializable classes (including case classes) are automatically made serializable. However, they don't extend "Serializable" statically because of the known difficulty (should be done before typing, but hard). - Writing "case class C() extends Serializable" gives "error: trait Serializable is inherited twice" - Functions are serializable, but don't extend Serializable dynamically (could be fixed by making FunctionN Serializable - shouldn't we?) Note that @SerialVersionUID continues to be an annotation; it generates a static field, which is not possible otherwise in scala. Review by dragos, extempore. Question to dragos: in JavaPlatform.isMaybeBoxed, why is there a test for "JavaSerializableClass"? Is that correct?
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/JavaPlatform.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala13
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala18
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala13
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala8
12 files changed, 48 insertions, 41 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 2acfa20c50..1ac2c3442a 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -26,6 +26,7 @@ abstract class TreeGen {
def scalaUnitConstr = scalaDot(nme.Unit.toTypeName)
def scalaScalaObjectConstr = scalaDot(nme.ScalaObject.toTypeName)
def productConstr = scalaDot(nme.Product.toTypeName)
+ def serializableConstr = scalaDot(nme.Serializable.toTypeName)
private def isRootOrEmptyPackageClass(s: Symbol) = s.isRoot || s.isEmptyPackageClass
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 751c7b5d13..09f1db7249 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2498,7 +2498,7 @@ self =>
parents = parents ::: List(scalaScalaObjectConstr)
if (parents.isEmpty)
parents = List(scalaAnyRefConstr)
- if (mods.isCase) parents = parents ::: List(productConstr)
+ if (mods.isCase) parents = parents ::: List(productConstr, serializableConstr)
val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart
atPos(tstart0) {
Template(parents, self, constrMods, vparamss, argss, body, o2p(tstart))
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 7a3321f6eb..de5f342a7d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -29,6 +29,7 @@ abstract class TreeBuilder {
def scalaUnitConstr = gen.scalaUnitConstr
def scalaScalaObjectConstr = gen.scalaScalaObjectConstr
def productConstr = gen.productConstr
+ def serializableConstr = gen.serializableConstr
/** Convert all occurrences of (lower-case) variables in a pattern as follows:
* x becomes x @ _
diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
index ec367b61bb..8d77eef488 100644
--- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
+++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
@@ -36,7 +36,7 @@ trait JavaPlatform extends Platform[AbstractFile] {
def isMaybeBoxed(sym: Symbol): Boolean = {
import definitions._
(sym == ObjectClass) ||
- (sym == SerializableClass) ||
+ (sym == JavaSerializableClass) ||
(sym == ComparableClass) ||
(sym isNonBottomSubClass BoxedNumberClass) ||
(sym isNonBottomSubClass BoxedCharacterClass)
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index a468e81b3e..5a4fa51899 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -169,11 +169,12 @@ trait Definitions extends reflect.generic.StandardDefinitions {
def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements)
// classes with special meanings
- lazy val NotNullClass = getClass("scala.NotNull")
- lazy val TypeConstraintClass = getClass("scala.TypeConstraint")
- lazy val SingletonClass = newClass(ScalaPackageClass, nme.Singleton, anyparam) setFlag (ABSTRACT | TRAIT | FINAL)
- lazy val SerializableClass = getClass(sn.Serializable)
- lazy val ComparableClass = getClass("java.lang.Comparable")
+ lazy val NotNullClass = getClass("scala.NotNull")
+ lazy val TypeConstraintClass = getClass("scala.TypeConstraint")
+ lazy val SingletonClass = newClass(ScalaPackageClass, nme.Singleton, anyparam) setFlag (ABSTRACT | TRAIT | FINAL)
+ lazy val SerializableClass = getClass("scala.Serializable")
+ lazy val JavaSerializableClass = getClass(sn.JavaSerializable)
+ lazy val ComparableClass = getClass("java.lang.Comparable")
lazy val RepeatedParamClass = newCovariantPolyClass(
ScalaPackageClass,
@@ -486,7 +487,7 @@ trait Definitions extends reflect.generic.StandardDefinitions {
lazy val ScalaNumberClass: Symbol = getClass("scala.math.ScalaNumber")
lazy val ScalaStrictFPAttr: Symbol = getClass("scala.annotation.strictfp")
lazy val SerialVersionUIDAttr: Symbol = getClass("scala.SerialVersionUID")
- lazy val SerializableAttr: Symbol = getClass("scala.serializable")
+ lazy val SerializableAttr: Symbol = getClass("scala.annotation.serializable") // @serializable is deprecated
lazy val TraitSetterAnnotationClass: Symbol = getClass("scala.runtime.TraitSetter")
lazy val TransientAttr: Symbol = getClass("scala.transient")
lazy val VolatileAttr: Symbol = getClass("scala.volatile")
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 11773dae4c..64dc254f28 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -197,6 +197,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val ScalaObject = newTermName("ScalaObject")
val ScalaRunTime = newTermName("ScalaRunTime")
val Seq = newTermName("Seq")
+ val Serializable = newTermName("Serializable")
val Short = newTermName("Short")
val Singleton = newTermName("Singleton")
val Some = newTermName("Some")
@@ -379,7 +380,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val NLRControl : Name = newTermName("scala.runtime.NonLocalReturnControl")
val NPException : Name // NullPointerException
val Object : Name
- val Serializable : Name
+ val JavaSerializable : Name
val String : Name
val Throwable : Name
val ValueType : Name
@@ -446,7 +447,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
final val MethodAsObject = newTermName("System.Reflection.MethodInfo")
final val NPException = newTermName("System.NullReferenceException")
final val Object = newTermName("System.Object")
- final val Serializable = nme.NOSYMBOL
+ final val JavaSerializable = nme.NOSYMBOL
final val String = newTermName("System.String")
final val Throwable = newTermName("System.Exception")
final val ValueType = newTermName("System.ValueType")
@@ -467,7 +468,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
final val BeanProperty = newTermName("scala.reflect.BeanProperty")
final val BooleanBeanProperty = newTermName("scala.reflect.BooleanBeanProperty")
final val Code = newTermName("scala.reflect.Code")
- final val Serializable = newTermName("java.io.Serializable")
+ final val JavaSerializable = newTermName("java.io.Serializable")
}
lazy val sn: SymbolNames =
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 8aa9c716c9..824d047d6b 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -80,9 +80,6 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
annots1
}
- def setSerializable(): Unit =
- addAnnotation(AnnotationInfo(SerializableAttr.tpe, Nil, Nil))
-
def setAnnotations(annots: List[AnnotationInfoBase]): this.type = {
this.rawannots = annots
this
@@ -402,7 +399,7 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
}
def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr)
- def isSerializable = hasAnnotation(SerializableAttr)
+ def isSerializable = info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass) || hasAnnotation(SerializableAttr) // last part can be removed, @serializable annotation is deprecated
def isDeprecated = hasAnnotation(DeprecatedAttr)
def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap { _.stringArg(0) }
// !!! when annotation arguments are not literal strings, but any sort of
@@ -955,6 +952,19 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
setInfo(completer)
}
+ /**
+ * Adds the interface scala.Serializable to the parents of a ClassInfoType.
+ * Note that the tree also has to be updated accordingly.
+ */
+ def makeSerializable() {
+ info match {
+ case ci @ ClassInfoType(_, _, _) =>
+ updateInfo(ci.copy(parents = ci.parents ::: List(SerializableClass.tpe)))
+ case i =>
+ abort("Only ClassInfoTypes can be made serializable: "+ i)
+ }
+ }
+
// Comparisons ----------------------------------------------------------------
/** A total ordering between symbols that refines the class
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index f8f185e6d8..943960c3f7 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -561,19 +561,6 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
typedWithPos(theTry.pos)(BLOCK(VAL(tempVar) === EmptyTree, newTry, Ident(tempVar)))
- /* Adds @serializable annotation to anonymous function classes */
- case cdef @ ClassDef(mods, name, tparams, impl) =>
- /** XXX This check is overly specific and bound to break if it hasn't already. */
- if (settings.target.value == "jvm-1.5") {
- val sym = cdef.symbol
- // is this an anonymous function class?
- if (sym.isAnonymousFunction && !sym.isSerializable) {
- sym.setSerializable()
- sym addAnnotation serialVersionUIDAnnotation
- }
- }
- super.transform(tree)
-
/*
* This transformation should identify Scala symbol invocations in the tree and replace them
* with references to a static member. Also, whenever a class has at least a single symbol invocation
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index ed4808ebbd..34015ef092 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -346,7 +346,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
def specializeClass(clazz: Symbol, outerEnv: TypeEnv): List[Symbol] = {
def specializedClass(env: TypeEnv, normMembers: List[Symbol]): Symbol = {
- val cls = clazz.owner.newClass(clazz.pos, specializedName(clazz, env))
+ val cls = clazz.owner.newClass(clazz.pos, specializedName(clazz, env).toTypeName)
.setFlag(SPECIALIZED | clazz.flags)
.resetFlag(CASE)
cls.sourceFile = clazz.sourceFile
@@ -545,7 +545,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
} else if (m.isClass) {
val specClass: Symbol = m.cloneSymbol(cls).setFlag(SPECIALIZED)
typeEnv(specClass) = fullEnv
- specClass.name = specializedName(specClass, fullEnv)
+ specClass.name = specializedName(specClass, fullEnv).toTypeName
enterMember(specClass)
log("entered specialized class " + specClass.fullName)
info(specClass) = SpecializedInnerClass(m, fullEnv)
@@ -581,6 +581,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val spc = specializedClass(env, decls1)
log("entered " + spc + " in " + clazz.owner)
hasSubclasses = true
+ val existing = clazz.owner.info.decl(spc.name)
+ // a symbol for the specialized class already exists if there's a classfile for it.
+ // keeping both crashes the compiler on test/files/pos/spec-Function1.scala
+ if (existing != NoSymbol) {
+ log("removing existing symbol for "+ existing)
+ clazz.owner.info.decls.unlink(existing)
+ }
+
atPhase(phase.next)(clazz.owner.info.decls enter spc) //!! assumes fully specialized classes
}
if (hasSubclasses) clazz.resetFlag(FINAL)
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index ddc14cd95b..0d87ba1203 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -327,8 +327,8 @@ abstract class UnCurry extends InfoTransform with TypingTransformers with ast.Tr
val (formals, restpe) = (targs.init, targs.last)
val anonClass = owner newAnonymousFunctionClass fun.pos setFlag (FINAL | SYNTHETIC | inConstructorFlag)
def parents =
- if (isFunctionType(fun.tpe)) List(abstractFunctionForFunctionType(fun.tpe))
- else List(ObjectClass.tpe, fun.tpe)
+ if (isFunctionType(fun.tpe)) List(abstractFunctionForFunctionType(fun.tpe), SerializableClass.tpe)
+ else List(ObjectClass.tpe, fun.tpe, SerializableClass.tpe)
anonClass setInfo ClassInfoType(parents, new Scope, anonClass)
val applyMethod = anonClass.newMethod(fun.pos, nme.apply) setFlag FINAL
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index d4cb11b122..1c8414671c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -243,8 +243,6 @@ trait SyntheticMethods extends ast.TreeDSL {
if (!phase.erasedTypes) try {
if (clazz.isCase) {
val isTop = clazz.ancestors forall (x => !x.isCase)
- // case classes are automatically marked serializable
- clazz.setSerializable()
if (isTop) {
// If this case class has fields with less than public visibility, their getter at this
@@ -295,12 +293,6 @@ trait SyntheticMethods extends ast.TreeDSL {
}
if (clazz.isModuleClass) {
- if (!clazz.isSerializable) {
- val comp = companionClassOf(clazz, context)
- if (comp.isCase || comp.isSerializable)
- clazz.setSerializable()
- }
-
def hasReadResolve = {
val sym = clazz.info member nme.readResolve // any member, including private
sym.isTerm && !sym.isDeferred
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 33db7424bc..03c5d2958c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1337,10 +1337,16 @@ trait Typers { self: Analyzer =>
for (c <- linkedClass.info.decl(nme.CONSTRUCTOR).alternatives)
c.initialize
val clazz = mdef.symbol.moduleClass
+ val maybeAddSerializable = (l: List[Tree]) =>
+ if(linkedClass == NoSymbol || !linkedClass.isSerializable || clazz.isSerializable) l
+ else {
+ clazz.makeSerializable()
+ l ::: List(TypeTree(SerializableClass.tpe))
+ }
val typedMods = removeAnnotations(mdef.mods)
assert(clazz != NoSymbol)
val impl1 = newTyper(context.make(mdef.impl, clazz, new Scope))
- .typedTemplate(mdef.impl, parentTypes(mdef.impl))
+ .typedTemplate(mdef.impl, maybeAddSerializable(parentTypes(mdef.impl)))
val impl2 = typerAddSyntheticMethods(impl1, clazz, context)
if (mdef.name == nme.PACKAGEkw)