From 9a47e8124aaa2a94737ea3f01ef2fa1e95f91c49 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 29 Jul 2015 11:39:04 +0200 Subject: [backport] SI-9375 add synthetic readResolve only for static modules For inner modules, the synthetic readResolve method would cause the module constructor to be invoked on de-serialization in certain situations. See the discussion in the ticket. Adds a comprehensive test around serializing and de-serializing modules. --- src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 16 ++++++++++++++-- .../scala/tools/nsc/typechecker/SyntheticMethods.scala | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 90ac1f466d..c5abd756f8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1182,11 +1182,23 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans private def eliminateModuleDefs(moduleDef: Tree): List[Tree] = exitingRefchecks { val ModuleDef(_, _, impl) = moduleDef val module = moduleDef.symbol + val moduleClass = module.moduleClass val site = module.owner val moduleName = module.name.toTermName // The typer doesn't take kindly to seeing this ClassDef; we have to // set NoType so it will be ignored. - val cdef = ClassDef(module.moduleClass, impl) setType NoType + val cdef = ClassDef(moduleClass, impl) setType NoType + + // This code is related to the fix of SI-9375, which stops adding `readResolve` methods to + // non-static (nested) modules. Before the fix, the method would cause the module accessor + // to become notPrivate. To prevent binary changes in the 2.11.x branch, we mimic that behavior. + // There is a bit of code duplication between here and SyntheticMethods. We cannot call + // makeNotPrivate already in SyntheticMethod: that is during type checking, and not all references + // are resolved yet, so we cannot rename a definition. This code doesn't exist in the 2.12.x branch. + def hasConcreteImpl(name: Name) = moduleClass.info.member(name).alternatives exists (m => !m.isDeferred) + val hadReadResolveBeforeSI9375 = moduleClass.isSerializable && !hasConcreteImpl(nme.readResolve) + if (hadReadResolveBeforeSI9375) + moduleClass.sourceModule.makeNotPrivate(moduleClass.sourceModule.owner) // Create the module var unless the immediate owner is a class and // the module var already exists there. See SI-5012, SI-6712. @@ -1210,7 +1222,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } def matchingInnerObject() = { val newFlags = (module.flags | STABLE) & ~MODULE - val newInfo = NullaryMethodType(module.moduleClass.tpe) + val newInfo = NullaryMethodType(moduleClass.tpe) val accessor = site.newMethod(moduleName, module.pos, newFlags) setInfoAndEnter newInfo DefDef(accessor, Select(This(site), module)) :: Nil diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 966e8f1abe..1b3f066fc1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -322,6 +322,7 @@ trait SyntheticMethods extends ast.TreeDSL { clazz.isModuleClass && clazz.isSerializable && !hasConcreteImpl(nme.readResolve) + && clazz.isStatic ) def synthesize(): List[Tree] = { -- cgit v1.2.3