@@ -52,27 +52,6 @@ trait Namers extends MethodSynthesis {
5252 def newNamerFor (context : Context , tree : Tree ): Namer =
5353 newNamer(context.makeNewScope(tree, tree.symbol))
5454
55- // In the typeCompleter (templateSig) of a case class (resp it's module),
56- // synthetic `copy` (reps `apply`, `unapply`) methods are added. To compute
57- // their signatures, the corresponding ClassDef is needed.
58- // During naming, for each case class module symbol, the corresponding ClassDef
59- // is stored in this map. The map is cleared lazily, i.e. when the new symbol
60- // is created with the same name, the old one (if present) is wiped out, or the
61- // entry is deleted when it is used and no longer needed.
62- private val classOfModuleClass = perRunCaches.newWeakMap[Symbol , WeakReference [ClassDef ]]()
63-
64- // Default getters of constructors are added to the companion object in the
65- // typeCompleter of the constructor (methodSig). To compute the signature,
66- // we need the ClassDef. To create and enter the symbols into the companion
67- // object, we need the templateNamer of that module class.
68- // This map is extended during naming of classes, the Namer is added in when
69- // it's available, i.e. in the type completer (templateSig) of the module class.
70- private [typechecker] val classAndNamerOfModule = perRunCaches.newMap[Symbol , (ClassDef , Namer )]()
71-
72- def resetNamer () {
73- classAndNamerOfModule.clear()
74- }
75-
7655 abstract class Namer (val context : Context ) extends MethodSynth with NamerContextErrors { thisNamer =>
7756
7857 import NamerErrorGen ._
@@ -621,15 +600,15 @@ trait Namers extends MethodSynthesis {
621600 MaxParametersCaseClassError (tree)
622601
623602 val m = ensureCompanionObject(tree, caseModuleDef)
624- classOfModuleClass( m.moduleClass) = new WeakReference (tree)
603+ m.moduleClass.addAttachment( new ClassForCaseCompanionAttachment (tree) )
625604 }
626605 val hasDefault = impl.body exists {
627606 case DefDef (_, nme.CONSTRUCTOR , _, vparamss, _, _) => mexists(vparamss)(_.mods.hasDefault)
628607 case _ => false
629608 }
630609 if (hasDefault) {
631610 val m = ensureCompanionObject(tree)
632- classAndNamerOfModule(m) = (tree, null )
611+ m.addAttachment( new ConstructorDefaultsAttachment (tree, null ) )
633612 }
634613 val owner = tree.symbol.owner
635614 if (settings.lint.value && owner.isPackageObjectClass && ! mods.isImplicit) {
@@ -660,7 +639,8 @@ trait Namers extends MethodSynthesis {
660639 if (sym.isLazy)
661640 sym.lazyAccessor andAlso enterIfNotThere
662641
663- defaultParametersOfMethod(sym) foreach { symRef => enterIfNotThere(symRef()) }
642+ for (defAtt <- sym.attachments.get[DefaultsOfLocalMethodAttachment ])
643+ defAtt.defaultGetters foreach enterIfNotThere
664644 }
665645 this .context
666646 }
@@ -849,23 +829,20 @@ trait Namers extends MethodSynthesis {
849829 // add apply and unapply methods to companion objects of case classes,
850830 // unless they exist already; here, "clazz" is the module class
851831 if (clazz.isModuleClass) {
852- Namers . this .classOfModuleClass get clazz foreach { cdefRef =>
853- val cdef = cdefRef()
854- if (cdef.mods.isCase) addApplyUnapply(cdef, templateNamer )
855- classOfModuleClass -= clazz
832+ clazz.attachments. get[ ClassForCaseCompanionAttachment ] foreach { cma =>
833+ val cdef = cma.caseClass
834+ assert (cdef.mods.isCase, " expected case class: " + cdef )
835+ addApplyUnapply(cdef, templateNamer)
856836 }
857837 }
858838
859839 // add the copy method to case classes; this needs to be done here, not in SyntheticMethods, because
860840 // the namer phase must traverse this copy method to create default getters for its parameters.
861841 // here, clazz is the ClassSymbol of the case class (not the module).
862- // @check: this seems to work only if the type completer of the class runs before the one of the
863- // module class: the one from the module class removes the entry from classOfModuleClass (see above).
864842 if (clazz.isClass && ! clazz.hasModuleFlag) {
865843 val modClass = companionSymbolOf(clazz, context).moduleClass
866- Namers .this .classOfModuleClass get modClass map { cdefRef =>
867- val cdef = cdefRef()
868-
844+ modClass.attachments.get[ClassForCaseCompanionAttachment ] foreach { cma =>
845+ val cdef = cma.caseClass
869846 def hasCopy (decls : Scope ) = (decls lookup nme.copy) != NoSymbol
870847 if (cdef.mods.isCase && ! hasCopy(decls) &&
871848 ! parents.exists(p => hasCopy(p.typeSymbol.info.decls)) &&
@@ -877,9 +854,8 @@ trait Namers extends MethodSynthesis {
877854 // if default getters (for constructor defaults) need to be added to that module, here's the namer
878855 // to use. clazz is the ModuleClass. sourceModule works also for classes defined in methods.
879856 val module = clazz.sourceModule
880- classAndNamerOfModule get module foreach {
881- case (cdef, _) =>
882- classAndNamerOfModule(module) = (cdef, templateNamer)
857+ for (cda <- module.attachments.get[ConstructorDefaultsAttachment ]) {
858+ cda.companionModuleClassNamer = templateNamer
883859 }
884860 ClassInfoType (parents, decls, clazz)
885861 }
@@ -1100,13 +1076,15 @@ trait Namers extends MethodSynthesis {
11001076 val module = companionSymbolOf(clazz, context)
11011077 module.initialize // call type completer (typedTemplate), adds the
11021078 // module's templateNamer to classAndNamerOfModule
1103- classAndNamerOfModule get module match {
1104- case s @ Some ((cdef, nmr)) if nmr != null =>
1105- moduleNamer = s
1106- (cdef, nmr)
1079+ module.attachments.get[ConstructorDefaultsAttachment ] match {
1080+ // by martin: the null case can happen in IDE; this is really an ugly hack on top of an ugly hack but it seems to work
1081+ // later by lukas: disabled when fixing SI-5975, i think it cannot happen anymore
1082+ case Some (cda) /* if cma.companionModuleClassNamer == null*/ =>
1083+ val p = (cda.classWithDefault, cda.companionModuleClassNamer)
1084+ moduleNamer = Some (p)
1085+ p
11071086 case _ =>
11081087 return // fix #3649 (prevent crash in erroneous source code)
1109- // nmr == null can happen in IDE; this is really an ugly hack on top[ of an ugly hack but it seems to work
11101088 }
11111089 }
11121090 deftParams = cdef.tparams map copyUntypedInvariant
@@ -1144,11 +1122,14 @@ trait Namers extends MethodSynthesis {
11441122 clazz.resetFlag(INTERFACE ) // there's a concrete member now
11451123 val default = parentNamer.enterSyntheticSym(defaultTree)
11461124 if (forInteractive && default.owner.isTerm) {
1147- // enter into map from method symbols to default arguments.
1148- // if compiling the same local block several times (which can happen in interactive mode)
1149- // we might otherwise not find the default symbol, because the second time it the
1150- // method symbol will be re-entered in the scope but the default parameter will not.
1151- defaultParametersOfMethod(meth) += new WeakReference (default)
1125+ // save the default getters as attachments in the method symbol. if compiling the
1126+ // same local block several times (which can happen in interactive mode) we might
1127+ // otherwise not find the default symbol, because the second time it the method
1128+ // symbol will be re-entered in the scope but the default parameter will not.
1129+ val att = meth.attachments.get[DefaultsOfLocalMethodAttachment ] match {
1130+ case Some (att) => att.defaultGetters += default
1131+ case None => meth.addAttachment(new DefaultsOfLocalMethodAttachment (default))
1132+ }
11521133 }
11531134 } else if (baseHasDefault) {
11541135 // the parameter does not have a default itself, but the
0 commit comments