Skip to content

Commit 4d772b4

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 An 'integration test' `Annotations.scala` was added in `tests/pos` to be picked up by `IdempotencyCheck.scala`, but unfortunately I haven't successfully reproduced the nondeterminism that way. 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 4d772b4

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-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"

tests/pos/Annotations.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package foo.bar
2+
3+
import jdk.jfr.Enabled
4+
5+
@Enabled
6+
@Deprecated
7+
final class Annotations {
8+
}

0 commit comments

Comments
 (0)