From 210f8c8f108aaf650a5be640c4db0d2336193f33 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 14 Sep 2012 15:23:51 +0200 Subject: SI-6372 cleans up the API of Attachments Previously Attachments allowed multiple attachments that correspond to the same attachment type. This created a potential for confusion, given that Attachments.get only searched for the first attachment of a given type. Hence I made Attachments.add overwrite previously existing attachments of a given type and renamed it to Attachments.update, so that the name suits the intention better. --- src/compiler/scala/reflect/reify/codegen/GenSymbols.scala | 2 +- src/compiler/scala/reflect/reify/utils/SymbolTables.scala | 8 ++++---- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 2 +- src/compiler/scala/tools/nsc/transform/Erasure.scala | 2 +- src/compiler/scala/tools/nsc/typechecker/Macros.scala | 4 ++-- src/compiler/scala/tools/nsc/typechecker/Namers.scala | 6 +++--- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 8 ++++---- src/library/scala/reflect/base/Attachments.scala | 11 +++++++---- src/reflect/scala/reflect/internal/StdAttachments.scala | 2 +- src/reflect/scala/reflect/internal/Symbols.scala | 2 +- src/reflect/scala/reflect/macros/Universe.scala | 2 +- 11 files changed, 26 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala index c4b674955a..22a834d2e4 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -143,7 +143,7 @@ trait GenSymbols { // produces valid Scala code (with vals in a block depending only on lexically preceding vals) val reification = reificode(sym) import reification.{name, binding} - val tree = reification.tree addAttachment ReifyBindingAttachment(binding) + val tree = reification.tree updateAttachment ReifyBindingAttachment(binding) state.symtab += (sym, name, tree) } fromSymtab diff --git a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala index 2e17558f54..3ec43c863d 100644 --- a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala +++ b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala @@ -46,8 +46,8 @@ trait SymbolTables { def symRef(sym: Symbol): Tree = symtab.get(sym) match { - case Some(FreeDef(_, name, binding, _, _)) => Ident(name) addAttachment binding - case Some(SymDef(_, name, _, _)) => Ident(name) addAttachment ReifyBindingAttachment(Ident(sym)) + case Some(FreeDef(_, name, binding, _, _)) => Ident(name) updateAttachment binding + case Some(SymDef(_, name, _, _)) => Ident(name) updateAttachment ReifyBindingAttachment(Ident(sym)) case None => EmptyTree } @@ -86,7 +86,7 @@ trait SymbolTables { newTermName(fresh.newName(name)) } val bindingAttachment = reification.attachments.get[ReifyBindingAttachment].get - add(ValDef(NoMods, freshName(name0), TypeTree(), reification) addAttachment bindingAttachment) + add(ValDef(NoMods, freshName(name0), TypeTree(), reification) updateAttachment bindingAttachment) } private def add(sym: Symbol, name: TermName): SymbolTable = { @@ -203,7 +203,7 @@ trait SymbolTables { result ++= cumulativeAliases.distinct filter (alias => alias._1 == sym && alias._2 != currtab.symName(sym)) map (alias => { val canonicalName = currtab.symName(sym) val aliasName = alias._2 - ValDef(NoMods, aliasName, TypeTree(), Ident(canonicalName)) addAttachment ReifyAliasAttachment(sym, aliasName) + ValDef(NoMods, aliasName, TypeTree(), Ident(canonicalName)) updateAttachment ReifyAliasAttachment(sym, aliasName) }) result.toList }) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index c925669444..e3755b82d5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1029,7 +1029,7 @@ self => val tok = in.token val name = ident() t = atPos(start) { - if (tok == BACKQUOTED_IDENT) Ident(name) addAttachment BackquotedIdentifierAttachment + if (tok == BACKQUOTED_IDENT) Ident(name) updateAttachment BackquotedIdentifierAttachment else Ident(name) } if (in.token == DOT) { diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 7dafc9b467..b3b0c82d38 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -1082,7 +1082,7 @@ abstract class Erasure extends AddInterfaces // println("inject derived: "+arg+" "+tpt.tpe) val List(arg) = args val attachment = new TypeRefAttachment(tree.tpe.asInstanceOf[TypeRef]) - InjectDerivedValue(arg) addAttachment attachment + InjectDerivedValue(arg) updateAttachment attachment case _ => preEraseNormalApply(tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 7e9b288853..7796c0bf1b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -713,7 +713,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { if (isNullaryInvocation(expandee)) expectedTpe = expectedTpe.finalResultType var typechecked = typecheck("macro def return type", expanded, expectedTpe) typechecked = typecheck("expected type", typechecked, pt) - typechecked addAttachment MacroExpansionAttachment(expandee) + typechecked updateAttachment MacroExpansionAttachment(expandee) } finally { popMacroContext() } @@ -762,7 +762,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { case (false, true) => macroLogLite("macro expansion is delayed: %s".format(expandee)) delayed += expandee -> undetparams - expandee addAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(macroArgs(typer, expandee).c)) + expandee updateAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(macroArgs(typer, expandee).c)) Delay(expandee) case (false, false) => import typer.TyperErrorGen._ diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 161df00220..9e66d696cb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -637,7 +637,7 @@ trait Namers extends MethodSynthesis { MaxParametersCaseClassError(tree) val m = ensureCompanionObject(tree, caseModuleDef) - m.moduleClass.addAttachment(new ClassForCaseCompanionAttachment(tree)) + m.moduleClass.updateAttachment(new ClassForCaseCompanionAttachment(tree)) } val hasDefault = impl.body exists { case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => mexists(vparamss)(_.mods.hasDefault) @@ -645,7 +645,7 @@ trait Namers extends MethodSynthesis { } if (hasDefault) { val m = ensureCompanionObject(tree) - m.addAttachment(new ConstructorDefaultsAttachment(tree, null)) + m.updateAttachment(new ConstructorDefaultsAttachment(tree, null)) } val owner = tree.symbol.owner if (settings.lint.value && owner.isPackageObjectClass && !mods.isImplicit) { @@ -1172,7 +1172,7 @@ trait Namers extends MethodSynthesis { // symbol will be re-entered in the scope but the default parameter will not. val att = meth.attachments.get[DefaultsOfLocalMethodAttachment] match { case Some(att) => att.defaultGetters += default - case None => meth.addAttachment(new DefaultsOfLocalMethodAttachment(default)) + case None => meth.updateAttachment(new DefaultsOfLocalMethodAttachment(default)) } } } else if (baseHasDefault) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8a3c509e81..5200aae8d1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2482,7 +2482,7 @@ trait Typers extends Modes with Adaptations with Tags { match_ setType B1.tpe // the default uses applyOrElse's first parameter since the scrut's type has been widened - val body = methodBodyTyper.virtualizedMatch(match_ addAttachment DefaultOverrideMatchAttachment(REF(default) APPLY (REF(x))), mode, B1.tpe) + val body = methodBodyTyper.virtualizedMatch(match_ updateAttachment DefaultOverrideMatchAttachment(REF(default) APPLY (REF(x))), mode, B1.tpe) DefDef(methodSym, body) } @@ -2500,7 +2500,7 @@ trait Typers extends Modes with Adaptations with Tags { methodSym setInfoAndEnter MethodType(paramSyms, BooleanClass.tpe) val match_ = methodBodyTyper.typedMatch(gen.mkUnchecked(selector), casesTrue, mode, BooleanClass.tpe) - val body = methodBodyTyper.virtualizedMatch(match_ addAttachment DefaultOverrideMatchAttachment(FALSE_typed), mode, BooleanClass.tpe) + val body = methodBodyTyper.virtualizedMatch(match_ updateAttachment DefaultOverrideMatchAttachment(FALSE_typed), mode, BooleanClass.tpe) DefDef(methodSym, body) } @@ -2622,7 +2622,7 @@ trait Typers extends Modes with Adaptations with Tags { // todo. investigate whether something can be done about this val att = templ.attachments.get[CompoundTypeTreeOriginalAttachment].getOrElse(CompoundTypeTreeOriginalAttachment(Nil, Nil)) templ.removeAttachment[CompoundTypeTreeOriginalAttachment] - templ addAttachment att.copy(stats = stats1) + templ updateAttachment att.copy(stats = stats1) for (stat <- stats1 if stat.isDef) { val member = stat.symbol if (!(context.owner.ancestors forall @@ -4947,7 +4947,7 @@ trait Typers extends Modes with Adaptations with Tags { //Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id) val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos) newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ) - templ addAttachment CompoundTypeTreeOriginalAttachment(parents1, Nil) // stats are set elsewhere + templ updateAttachment CompoundTypeTreeOriginalAttachment(parents1, Nil) // stats are set elsewhere tree setType self } } diff --git a/src/library/scala/reflect/base/Attachments.scala b/src/library/scala/reflect/base/Attachments.scala index 43e870fc4f..889ac0ac14 100644 --- a/src/library/scala/reflect/base/Attachments.scala +++ b/src/library/scala/reflect/base/Attachments.scala @@ -20,15 +20,18 @@ abstract class Attachments { self => /** Gets the underlying payload */ def all: Set[Any] = Set.empty + private def matchesTag[T: ClassTag](datum: Any) = + classTag[T].runtimeClass == datum.getClass + def get[T: ClassTag]: Option[T] = - (all find (_.getClass == classTag[T].runtimeClass)).asInstanceOf[Option[T]] + (all filter matchesTag[T]).headOption.asInstanceOf[Option[T]] /** Creates a copy of this attachment with its payload updated */ - def add(attachment: Any): Attachments { type Pos = self.Pos } = - new NonemptyAttachments(this.pos, all + attachment) + def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } = + new NonemptyAttachments(this.pos, remove[T].all + attachment) def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = { - val newAll = all filterNot (_.getClass == classTag[T].runtimeClass) + val newAll = all filterNot matchesTag[T] if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }] else new NonemptyAttachments(this.pos, newAll) } diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index 60b3a6f436..5f6a3bf777 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -10,7 +10,7 @@ trait StdAttachments { trait Attachable { protected var rawatt: base.Attachments { type Pos = Position } = NoPosition def attachments = rawatt - def addAttachment(attachment: Any): this.type = { rawatt = rawatt.add(attachment); this } + def updateAttachment[T: ClassTag](attachment: T): this.type = { rawatt = rawatt.update(attachment); this } def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this } // cannot be final due to SynchronizedSymbols diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 430cf58a54..be55b72623 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -1600,7 +1600,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => setInfo (this.info cloneInfo clone) setAnnotations this.annotations ) - this.attachments.all.foreach(clone.addAttachment) + this.attachments.all.foreach(clone.updateAttachment) if (clone.thisSym != clone) clone.typeOfThis = (clone.typeOfThis cloneInfo clone) diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala index 06428ee3fc..f6a4ef6c9b 100644 --- a/src/reflect/scala/reflect/macros/Universe.scala +++ b/src/reflect/scala/reflect/macros/Universe.scala @@ -10,7 +10,7 @@ abstract class Universe extends scala.reflect.api.Universe { def attachments: base.Attachments { type Pos = Position } /** ... */ - def addAttachment(attachment: Any): AttachableApi.this.type + def updateAttachment[T: ClassTag](attachment: T): AttachableApi.this.type /** ... */ def removeAttachment[T: ClassTag]: AttachableApi.this.type -- cgit v1.2.3