From 0303a436af16495f1f349107d0dba9c142da9f26 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Tue, 18 Jun 2024 17:00:49 +0200 Subject: [PATCH] Fix deterministically adding additional interfaces When a class contains calls to 'super' for traits it does not directly implement, these are added to the list of interfaces of the generated class. Previously, because these interfaces were determined using set logic, the ordering of that list was not deterministic. This makes the order deterministic assuming the order in which these calls are registered using `registerSuperCall` in the `CollectSuperCalls` phase is deterministic within each class. This seems likely to me but it'd be great if someone could confirm. To add a test for this change, creating a class that has many 'additional' traits and checking they are generated in the right order would make sense, but I couldn't find an obvious place for such a test. Any recommendations? Fixes #20496 --- .../src/dotty/tools/backend/jvm/BTypesFromSymbols.scala | 7 ++++--- .../dotty/tools/backend/jvm/DottyBackendInterface.scala | 2 +- compiler/src/dotty/tools/backend/jvm/GenBCode.scala | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala b/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala index b8d7ee04c870..97934935f352 100644 --- a/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala +++ b/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala @@ -113,11 +113,12 @@ class BTypesFromSymbols[I <: DottyBackendInterface](val int: I, val frontendAcce val directlyInheritedTraits = sym.directlyInheritedTraits val directlyInheritedTraitsSet = directlyInheritedTraits.toSet val allBaseClasses = directlyInheritedTraits.iterator.flatMap(_.asClass.baseClasses.drop(1)).toSet - val superCalls = superCallsMap.getOrElse(sym, Set.empty) - val additional = (superCalls -- directlyInheritedTraitsSet).filter(_.is(Trait)) + val superCalls = superCallsMap.getOrElse(sym, List.empty) + val superCallsSet = superCalls.toSet + val additional = superCalls.filter(t => !directlyInheritedTraitsSet(t) && t.is(Trait)) // if (additional.nonEmpty) // println(s"$fullName: adding supertraits $additional") - directlyInheritedTraits.filter(t => !allBaseClasses(t) || superCalls(t)) ++ additional + directlyInheritedTraits.filter(t => !allBaseClasses(t) || superCallsSet(t)) ++ additional } val interfaces = classSym.superInterfaces.map(classBTypeFromSymbol) diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 8016c2bfc209..cab17b31c3f3 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -25,7 +25,7 @@ import StdNames.nme import NameKinds.{LazyBitMapName, LazyLocalName} import Names.Name -class DottyBackendInterface(val superCallsMap: ReadOnlyMap[Symbol, Set[ClassSymbol]])(using val ctx: Context) { +class DottyBackendInterface(val superCallsMap: ReadOnlyMap[Symbol, List[ClassSymbol]])(using val ctx: Context) { private val desugared = new java.util.IdentityHashMap[Type, tpd.Select] diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index a616241d9a3e..f28c89b7817e 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -23,10 +23,10 @@ class GenBCode extends Phase { self => override def isRunnable(using Context) = super.isRunnable && !ctx.usedBestEffortTasty - private val superCallsMap = new MutableSymbolMap[Set[ClassSymbol]] + private val superCallsMap = new MutableSymbolMap[List[ClassSymbol]] def registerSuperCall(sym: Symbol, calls: ClassSymbol): Unit = { - val old = superCallsMap.getOrElse(sym, Set.empty) - superCallsMap.update(sym, old + calls) + val old = superCallsMap.getOrElse(sym, List.empty) + superCallsMap.update(sym, old :+ calls) } private val entryPoints = new mutable.HashSet[String]()