Skip to content

Commit 0072dc2

Browse files
committed
add readResolve to objects with serializable interface
If the object implements the serializable interface and not includes the readResolve method then we add it. Since it's an object we reference it to the objects singleton instance. Resolves issue #4440
1 parent 80764e0 commit 0072dc2

File tree

3 files changed

+42
-11
lines changed

3 files changed

+42
-11
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ class Definitions {
551551
case _ => false
552552
}).symbol.asTerm
553553
lazy val JavaSerializableClass = ctx.requiredClass("java.io.Serializable")
554+
def readResolve(cls: ClassSymbol, flags: FlagSet) = enterMethod(cls, nme.readResolve, MethodType(Nil, AnyRefType), flags)
555+
554556
lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable")
555557

556558
lazy val SystemClass = ctx.requiredClass("java.lang.System")

compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,13 @@ package dotty.tools.dotc
22
package transform
33

44
import core._
5-
import Symbols._, Types._, Contexts._, Names._, StdNames._, Constants._, SymUtils._
6-
import scala.collection.{ mutable, immutable }
5+
import Symbols._, Types._, Contexts._, StdNames._, Constants._, SymUtils._
76
import Flags._
8-
import MegaPhase._
97
import DenotTransformers._
10-
import ast.Trees._
11-
import ast.untpd
128
import Decorators._
139
import NameOps._
1410
import Annotations.Annotation
1511
import ValueClasses.isDerivedValueClass
16-
import scala.collection.mutable.ListBuffer
1712
import scala.language.postfixOps
1813

1914
/** Synthetic method implementations for case classes, case objects,
@@ -57,7 +52,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
5752
def caseModuleSymbols(implicit ctx: Context) = { initSymbols; myCaseModuleSymbols }
5853

5954
/** The synthetic methods of the case or value class `clazz`. */
60-
def syntheticMethods(clazz: ClassSymbol)(implicit ctx: Context): List[Tree] = {
55+
def syntheticMethods(clazz: ClassSymbol, isSerializableObject: Boolean)(implicit ctx: Context): List[Tree] = {
6156
val clazzType = clazz.appliedRef
6257
lazy val accessors =
6358
if (isDerivedValueClass(clazz)) clazz.paramAccessors.take(1) // Tail parameters can only be `erased`
@@ -261,12 +256,32 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
261256
*/
262257
def canEqualBody(that: Tree): Tree = that.isInstance(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot)))
263258

264-
symbolsToSynthesize flatMap syntheticDefIfMissing
259+
val methods = symbolsToSynthesize flatMap syntheticDefIfMissing
260+
261+
def createReadResolveMethod(implicit ctx: Context): Tree = {
262+
ctx.log(s"adding readResolve to $clazz at ${ctx.phase}")
263+
val readResolve = defn.readResolve(clazz, Private | Synthetic)
264+
DefDef(readResolve, _ => ref(clazz.sourceModule)).withPos(ctx.owner.pos.focus)
265+
}
266+
267+
if (isSerializableObject)
268+
createReadResolveMethod :: methods
269+
else
270+
methods
265271
}
266272

267-
def addSyntheticMethods(impl: Template)(implicit ctx: Context) =
268-
if (ctx.owner.is(Case) || isDerivedValueClass(ctx.owner))
269-
cpy.Template(impl)(body = impl.body ++ syntheticMethods(ctx.owner.asClass))
273+
def addSyntheticMethods(impl: Template)(implicit ctx: Context) = {
274+
val isSerializableObject =
275+
(ctx.owner.isStatic
276+
&& ctx.owner.derivesFrom(defn.JavaSerializableClass)
277+
&& !ctx.owner.asClass.membersNamed(nme.readResolve)
278+
.filterWithPredicate(s => s.signature == Signature(defn.AnyRefType, isJava = false))
279+
.exists)
280+
281+
if (ctx.owner.is(Case) || isDerivedValueClass(ctx.owner) || isSerializableObject)
282+
cpy.Template(impl)(body = impl.body ++ syntheticMethods(ctx.owner.asClass, isSerializableObject))
270283
else
271284
impl
285+
}
286+
272287
}

tests/run/serialize.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,23 @@ object Test {
88
in.readObject.asInstanceOf[T]
99
}
1010

11+
object Foo extends Serializable {}
12+
13+
object Baz extends Serializable {
14+
private def readResolve(): AnyRef = {
15+
this
16+
}
17+
}
18+
1119
def main(args: Array[String]): Unit = {
1220
val x: PartialFunction[Int, Int] = { case x => x + 1 }
1321
val adder = serializeDeserialize(x)
1422
assert(adder(1) == 2)
23+
24+
val foo = serializeDeserialize(Foo)
25+
assert(foo eq Foo)
26+
27+
val baz = serializeDeserialize(Baz)
28+
assert(baz ne Baz)
1529
}
1630
}

0 commit comments

Comments
 (0)