diff --git a/compiler/src/dotty/tools/dotc/transform/RepeatableAnnotations.scala b/compiler/src/dotty/tools/dotc/transform/RepeatableAnnotations.scala index 24c46cd98e4c..a9957815d5a5 100644 --- a/compiler/src/dotty/tools/dotc/transform/RepeatableAnnotations.scala +++ b/compiler/src/dotty/tools/dotc/transform/RepeatableAnnotations.scala @@ -11,6 +11,8 @@ import Constants._ import Types._ import Decorators._ +import scala.collection.mutable + class RepeatableAnnotations extends MiniPhase: override def phaseName: String = RepeatableAnnotations.name @@ -28,7 +30,7 @@ class RepeatableAnnotations extends MiniPhase: tree private def aggregateAnnotations(annotations: Seq[Annotation])(using Context): List[Annotation] = - val annsByType = annotations.groupBy(_.symbol) + val annsByType = stableGroupBy[Annotation, Symbols.Symbol](annotations, _.symbol) annsByType.flatMap { case (_, a :: Nil) => a :: Nil case (sym, anns) if sym.derivesFrom(defn.ClassfileAnnotationClass) => @@ -50,6 +52,14 @@ class RepeatableAnnotations extends MiniPhase: case (_, anns) => anns }.toList + private def stableGroupBy[A, K](ins: Seq[A], f: A => K): scala.collection.MapView[K, List[A]] = + val out = new mutable.LinkedHashMap[K, mutable.ListBuffer[A]]() + for (in <- ins) { + val buffer = out.getOrElseUpdate(f(in), new mutable.ListBuffer) + buffer += in + } + out.view.mapValues(_.toList) + object RepeatableAnnotations: val name: String = "repeatableAnnotations" val description: String = "aggregate repeatable annotations" diff --git a/tests/pos/Annotations.scala b/tests/pos/Annotations.scala new file mode 100644 index 000000000000..322cf2eafb06 --- /dev/null +++ b/tests/pos/Annotations.scala @@ -0,0 +1,8 @@ +package foo.bar + +import jdk.jfr.Enabled + +@Enabled +@Deprecated +final class Annotations { +}