Skip to content

Commit cf55e6a

Browse files
committed
Simplify argumet reordering
1 parent e04786f commit cf55e6a

File tree

1 file changed

+25
-47
lines changed

1 file changed

+25
-47
lines changed

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 25 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotc
33
package typer
44

55
import core._
6-
import ast.{TreeInfo, Trees, tpd, untpd}
6+
import ast.{Trees, untpd, tpd, TreeInfo}
77
import util.Positions._
88
import util.Stats.track
99
import Trees.Untyped
@@ -26,7 +26,7 @@ import EtaExpansion._
2626
import Inferencing._
2727

2828
import collection.mutable
29-
import config.Printers.{overload, typr, unapp}
29+
import config.Printers.{typr, unapp, overload}
3030
import TypeApplications._
3131

3232
import language.implicitConversions
@@ -583,25 +583,6 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
583583
myNormalizedFun = liftApp(liftedDefs, myNormalizedFun)
584584
}
585585

586-
/** The index of the first difference between lists of trees `xs` and `ys`,
587-
* where initial `EmptyTree`s in the second list are skipped.
588-
* -1 if there are no differences.
589-
*/
590-
private def firstDiffSkipInitEmptyTrees[T <: Trees.Tree[_]](xs: List[T], ys: List[T], n: Int = 0): Int = xs match {
591-
case x :: xs1 =>
592-
ys match {
593-
case EmptyTree :: ys1 => firstDiffSkipInitEmptyTrees(xs, ys1, n)
594-
case y :: ys1 => if (x ne y) n else firstDiff(xs1, ys1, n + 1)
595-
case nil => n
596-
}
597-
case nil =>
598-
ys match {
599-
case EmptyTree :: ys1 => firstDiffSkipInitEmptyTrees(xs, ys1, n)
600-
case y :: ys1 => n
601-
case nil => -1
602-
}
603-
}
604-
605586
/** The index of the first difference between lists of trees `xs` and `ys`
606587
* -1 if there are no differences.
607588
*/
@@ -617,45 +598,42 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
617598
case nil => -1
618599
}
619600
}
601+
private def sameSeq[T <: Trees.Tree[_]](xs: List[T], ys: List[T]): Boolean = firstDiff(xs, ys) < 0
620602

621603
val result = {
622604
var typedArgs = typedArgBuf.toList
623605
def app0 = cpy.Apply(app)(normalizedFun, typedArgs) // needs to be a `def` because typedArgs can change later
624606
val app1 =
625607
if (!success) app0.withType(UnspecifiedErrorType)
626608
else {
627-
if (firstDiffSkipInitEmptyTrees(args, orderedArgs) >= 0 && !isJavaAnnotConstr(methRef.symbol)) {
609+
if (sameSeq(args, orderedArgs.dropWhile(_ eq EmptyTree)) && !isJavaAnnotConstr(methRef.symbol)) {
628610
// need to lift arguments to maintain evaluation order in the
629611
// presence of argument reorderings.
612+
630613
liftFun()
631-
val eqSuffixLength = firstDiffSkipInitEmptyTrees(app.args.reverse, orderedArgs.reverse)
632-
val (liftable, rest) = typedArgs splitAt (typedArgs.length - eqSuffixLength)
633-
634-
// Mapping of index of each `liftable` into original args ordering
635-
var indices = ListBuffer.empty[Int]
636-
var nextDefaultParamIndex = args.size
637-
var prefixShift = 0
638-
if (liftedDefs.nonEmpty) {
639-
indices += 0
640-
prefixShift = 1
641-
}
642-
liftable.foreach {
643-
case NamedArg(_, arg) if isPureExpr(arg) =>
644-
case arg if isPureExpr(arg) =>
645-
case arg =>
646-
if (args.contains(arg)) {
647-
indices += prefixShift + args.indexOf(arg)
648-
} else {
649-
indices += prefixShift + nextDefaultParamIndex
650-
nextDefaultParamIndex += 1
651-
}
652-
}
653614

654-
typedArgs = liftArgs(liftedDefs, methType, liftable) ++ rest
615+
// lift arguments in the definition order
616+
val argDefBuff = mutable.ListBuffer.empty[Tree]
617+
typedArgs = liftArgs(argDefBuff, methType, typedArgs)
618+
619+
def orderedArgDefs = {
620+
val impureArgs = typedArgBuf.filterNot { // pure are not lifted by liftArgs
621+
case NamedArg(_, arg) => isPureExpr(arg)
622+
case arg => isPureExpr(arg)
623+
}
624+
var defaultParamIndex = args.size
625+
// Mapping of index of each `liftable` into original args ordering
626+
val indices = impureArgs.map { arg =>
627+
val idx = args.indexOf(arg)
628+
if (idx >= 0) args.indexOf(arg)
629+
else defaultParamIndex // assuming stable sorting
630+
}
631+
scala.util.Sorting.stableSort[(Tree, Int), Int](argDefBuff zip indices, x => x._2).map(_._1)
632+
}
655633

656-
liftedDefs = (liftedDefs zip indices).sortBy(_._2).unzip._1.to
634+
liftedDefs ++= orderedArgDefs
657635
}
658-
if (firstDiff(typedArgs, args) < 0) // trick to cut down on tree copying
636+
if (sameSeq(typedArgs, args)) // trick to cut down on tree copying
659637
typedArgs = args.asInstanceOf[List[Tree]]
660638
assignType(app0, normalizedFun, typedArgs)
661639
}

0 commit comments

Comments
 (0)