Skip to content

Commit 96dccb9

Browse files
Fix #3018: use List instead of Map in InlineLocalObjects
Using Map#values resulted in losing the original order or arguments, a List fixes that. The lookup cost will be slightly higher this way, but that should be negligible.
1 parent 4366453 commit 96dccb9

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed

compiler/src/dotty/tools/dotc/transform/localopt/InlineLocalObjects.scala

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ class InlineLocalObjects(val simplifyPhase: Simplify) extends Optimisation {
3434
val gettersCalled = mutable.HashSet[Symbol]()
3535

3636
// Map from class to new fields, initialised between visitor and transformer.
37-
var newFieldsMapping: Map[Symbol, Map[Symbol, Symbol]] = null
38-
// | | |
39-
// | | New fields, replacements these getters
40-
// | Usages of getters of these classes
41-
// ValDefs of the classes that are being torn apart; = candidates.intersect(gettersCalled)
37+
var newFieldsMapping: Map[Symbol, List[(Symbol, Symbol)]] = null
38+
// | | |
39+
// | | New fields, replacements these getters
40+
// | Usages of getters of these classes
41+
// ValDefs of the classes that are being torn apart; = candidates.intersect(gettersCalled)
4242

4343
def clear(): Unit = {
4444
candidates.clear()
@@ -57,7 +57,7 @@ class InlineLocalObjects(val simplifyPhase: Simplify) extends Optimisation {
5757
val info: Type = x.asSeenFrom(refVal.info).info.finalResultType.widenDealias
5858
ctx.newSymbol(owner, name, flags, info)
5959
}
60-
(refVal, accessors.zip(newLocals).toMap)
60+
(refVal, accessors.zip(newLocals))
6161
}.toMap
6262
}
6363

@@ -89,7 +89,7 @@ class InlineLocalObjects(val simplifyPhase: Simplify) extends Optimisation {
8989
initNewFieldsMapping();
9090
{
9191
case t @ NewCaseClassValDef(fun, args) if newFieldsMapping.contains(t.symbol) =>
92-
val newFields = newFieldsMapping(t.symbol).values.toList
92+
val newFields = newFieldsMapping(t.symbol).map(_._2)
9393
val newFieldsDefs = newFields.zip(args).map { case (nf, arg) =>
9494
val rhs = arg.changeOwnerAfter(t.symbol, nf.symbol, simplifyPhase)
9595
ValDef(nf.asTerm, rhs)
@@ -99,10 +99,9 @@ class InlineLocalObjects(val simplifyPhase: Simplify) extends Optimisation {
9999
Thicket(newFieldsDefs :+ recreate)
100100

101101
case t @ Select(rec, _) if isImmutableAccessor(t) =>
102-
newFieldsMapping.getOrElse(rec.symbol, Map.empty).get(t.symbol) match {
103-
case None => t
104-
case Some(newSym) => ref(newSym)
105-
}
102+
newFieldsMapping.getOrElse(rec.symbol, Nil).collect {
103+
case ((oldSym, newSym)) if oldSym == t.symbol => ref(newSym)
104+
}.headOption.getOrElse(t)
106105

107106
case t => t
108107
}

tests/pos/i3018.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class Type
2+
class Symbol
3+
4+
sealed trait Space
5+
case object Empty extends Space
6+
case class Typ(tp: Type, decomposed: Boolean) extends Space
7+
case class Prod(tp: Type, unappTp: Type, unappSym: Symbol, params: List[Space], full: Boolean) extends Space
8+
case class Or(spaces: List[Space]) extends Space
9+
10+
object Test {
11+
def simplify(space: Space, aggressive: Boolean = false): Space = space match {
12+
case Prod(tp, fun, sym, spaces, full) =>
13+
val sp = Prod(tp, fun, sym, spaces.map(simplify(_)), full)
14+
if (sp.params.contains(Empty)) Empty
15+
else sp
16+
case Or(spaces) => space
17+
case Typ(tp, _) => space
18+
case _ => space
19+
}
20+
21+
def main(args: Array[String]): Unit = {
22+
simplify(Prod(new Type, new Type, new Symbol, Nil, false))
23+
}
24+
}

0 commit comments

Comments
 (0)