Skip to content

Commit d359e08

Browse files
committed
Keep annotation order
This change makes sure non-repeated annotations are kept in the order they were found in the source code. The motivation is not necessarily to have them in the original order, but to have them in an order that is deterministic across rebuilds (potentially even across different machines), for reasons discussed further in #7661 and the corresponding scala/scala-dev#405 I tried adding an 'integration test' in `tests/pos` to be picked up by `IdempotencyCheck.scala`, but unfortunately couldn't reproduce the nondeterminism that way, so didn't end up including it in this commit. I didn't see an obvious place for a 'unit test' of this code, I'd be happy to add one when someone can recommend a good place to put it. This is basically the dotty equivalent of scala/scala@954c5d3 Fixes #14743
1 parent 9d6e87a commit d359e08

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import Constants._
1111
import Types._
1212
import Decorators._
1313

14+
import scala.collection.mutable
15+
1416
class RepeatableAnnotations extends MiniPhase:
1517

1618
override def phaseName: String = RepeatableAnnotations.name
@@ -28,7 +30,7 @@ class RepeatableAnnotations extends MiniPhase:
2830
tree
2931

3032
private def aggregateAnnotations(annotations: Seq[Annotation])(using Context): List[Annotation] =
31-
val annsByType = annotations.groupBy(_.symbol)
33+
val annsByType = stableGroupBy[Annotation, Symbols.Symbol](annotations, _.symbol)
3234
annsByType.flatMap {
3335
case (_, a :: Nil) => a :: Nil
3436
case (sym, anns) if sym.derivesFrom(defn.ClassfileAnnotationClass) =>
@@ -50,6 +52,14 @@ class RepeatableAnnotations extends MiniPhase:
5052
case (_, anns) => anns
5153
}.toList
5254

55+
private def stableGroupBy[A, K](ins: Seq[A], f: A => K): scala.collection.MapView[K, List[A]] =
56+
val out = new mutable.LinkedHashMap[K, mutable.ListBuffer[A]]()
57+
for (in <- ins) {
58+
val buffer = out.getOrElseUpdate(f(in), new mutable.ListBuffer)
59+
buffer += in
60+
}
61+
out.view.mapValues(_.toList)
62+
5363
object RepeatableAnnotations:
5464
val name: String = "repeatableAnnotations"
5565
val description: String = "aggregate repeatable annotations"

0 commit comments

Comments
 (0)