summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala19
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala7
-rw-r--r--test/files/run/t3667.check3
-rw-r--r--test/files/run/t3667.scala45
-rw-r--r--test/files/scalap/packageObject/result.test1
-rw-r--r--test/files/scalap/traitObject/result.test1
7 files changed, 66 insertions, 12 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 756863f8f9..5687917e46 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -360,7 +360,7 @@ trait Namers { self: Analyzer =>
} exists (_.mods hasFlag DEFAULTPARAM)
if (hasDefault) {
- val m = ensureCompanionObject(tree, companionModuleDef(tree, List(gen.scalaScalaObjectConstr)))
+ val m = ensureCompanionObject(tree, companionModuleDef(tree))
classAndNamerOfModule(m) = (tree, null)
}
case tree @ ModuleDef(mods, name, _) =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index eedf36c400..44930ffc81 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -289,14 +289,17 @@ trait SyntheticMethods extends ast.TreeDSL {
ts += impl()
}
- 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 (clazz.isModuleClass) {
+ if (!hasSerializableAnnotation(clazz))
+ clazz addAnnotation AnnotationInfo(SerializableAttr.tpe, Nil, Nil)
+
+ /** 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)
+ */
+ if (!hasImplementation(nme.readResolve))
+ ts += readResolveMethod
}
} catch {
case ex: TypeError =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 735cb4a3c4..57540fffef 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -147,14 +147,15 @@ trait Unapplies extends ast.TreeDSL
TypeTree(),
Literal(Constant(cdef.name.decode)))
- companionModuleDef(cdef, parents ::: List(gen.scalaScalaObjectConstr), List(toString))
+ companionModuleDef(cdef, parents, List(toString))
}
- def companionModuleDef(cdef: ClassDef, parents: List[Tree], body: List[Tree] = Nil): ModuleDef = atPos(cdef.pos.focus) {
+ def companionModuleDef(cdef: ClassDef, parents: List[Tree] = Nil, body: List[Tree] = Nil): ModuleDef = atPos(cdef.pos.focus) {
+ val allParents = parents ::: List( gen.scalaScalaObjectConstr)
ModuleDef(
Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin),
cdef.name.toTermName,
- Template(parents, emptyValDef, NoMods, Nil, List(Nil), body, cdef.impl.pos.focus))
+ Template(allParents, emptyValDef, NoMods, Nil, List(Nil), body, cdef.impl.pos.focus))
}
private val caseMods = Modifiers(SYNTHETIC | CASE)
diff --git a/test/files/run/t3667.check b/test/files/run/t3667.check
new file mode 100644
index 0000000000..01e79c32a8
--- /dev/null
+++ b/test/files/run/t3667.check
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/test/files/run/t3667.scala b/test/files/run/t3667.scala
new file mode 100644
index 0000000000..804432c516
--- /dev/null
+++ b/test/files/run/t3667.scala
@@ -0,0 +1,45 @@
+object Test {
+ def main(args: Array[String]) {
+ val o1 = new Outer1
+ val o2 = new Outer2
+ val o3 = new Outer3
+
+ println(1)
+ ser(new o1.Inner(1))
+ o1.Inner // make sure the Inner$module field of the Outer1 instance is initialized!
+ ser(new o1.Inner(1))
+
+ println(2)
+ ser(new o2.Inner(1))
+ o2.Inner
+ ser(new o2.Inner(1))
+
+ println(3)
+ ser(new o3.Inner(1))
+ o3.Inner
+ ser(new o3.Inner(1))
+ }
+
+ def ser(o: AnyRef) {
+ val oos = new java.io.ObjectOutputStream(new java.io.ByteArrayOutputStream())
+ oos.writeObject(o)
+ oos.close()
+ }
+
+}
+
+@serializable
+class Outer1 {
+ @serializable
+ class Inner(x: Int = 1)
+}
+
+@serializable
+class Outer2 {
+ case class Inner(x: Int = 1)
+}
+
+@serializable
+class Outer3 {
+ case class Inner(x: Int)
+}
diff --git a/test/files/scalap/packageObject/result.test b/test/files/scalap/packageObject/result.test
index 6a8d6ae1d5..324992aae1 100644
--- a/test/files/scalap/packageObject/result.test
+++ b/test/files/scalap/packageObject/result.test
@@ -2,4 +2,5 @@ package object PackageObject extends java.lang.Object with scala.ScalaObject {
def this() = { /* compiled code */ }
type A = scala.Predef.String
def foo(i : scala.Int) : scala.Int = { /* compiled code */ }
+ protected def readResolve() : java.lang.Object = { /* compiled code */ }
}
diff --git a/test/files/scalap/traitObject/result.test b/test/files/scalap/traitObject/result.test
index 0d7de1535d..8978873fc7 100644
--- a/test/files/scalap/traitObject/result.test
+++ b/test/files/scalap/traitObject/result.test
@@ -5,4 +5,5 @@ trait TraitObject extends java.lang.Object with scala.ScalaObject {
object TraitObject extends java.lang.Object with scala.ScalaObject {
def this() = { /* compiled code */ }
def bar : scala.Int = { /* compiled code */ }
+ protected def readResolve() : java.lang.Object = { /* compiled code */ }
}