Skip to content

Commit 17dfdc9

Browse files
committed
Fix ordering problem for applications
In an application with named and default arguments, where arguments have side effects and are given out of order, and some arguments are missing, the previous algorithm worked only if typed and untyped argument trees were the same. Test i2916 started failing once literals were represented as Number trees, since then untyped and typed versions of the argument were different.
1 parent 96b0854 commit 17dfdc9

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

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

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -758,23 +758,27 @@ trait Applications extends Compatibility {
758758
// lift arguments in the definition order
759759
val argDefBuf = mutable.ListBuffer.empty[Tree]
760760
typedArgs = lifter.liftArgs(argDefBuf, methType, typedArgs)
761-
762761
// Lifted arguments ordered based on the original order of typedArgBuf and
763762
// with all non-explicit default parameters at the end in declaration order.
764763
val orderedArgDefs = {
765-
// List of original arguments that are lifted by liftArgs
766-
val impureArgs = typedArgBuf.filterNot(lifter.noLift)
767-
// Assuming stable sorting all non-explicit default parameters will remain in the end with the same order
768-
val defaultParamIndex = args.size
769-
// Mapping of index of each `liftable` into original args ordering
770-
val indices = impureArgs.map { arg =>
771-
val idx = args.indexOf(arg)
772-
if (idx >= 0) idx // original index skipping pure arguments
773-
else defaultParamIndex
764+
// Indices of original typed arguments that are lifted by liftArgs
765+
val impureArgIndices = typedArgBuf.zipWithIndex.collect {
766+
case (arg, idx) if !lifter.noLift(arg) => idx
767+
}
768+
def position(arg: Trees.Tree[T]) = {
769+
val i = args.indexOf(arg)
770+
if (i >= 0) i else orderedArgs.length
774771
}
775-
scala.util.Sorting.stableSort[(Tree, Int), Int](argDefBuf zip indices, x => x._2).map(_._1)
772+
// The original indices of all ordered arguments, as an array
773+
val originalIndices = orderedArgs.map(position).toArray
774+
// Assuming stable sorting all non-explicit default parameters will remain in the end with the same order
775+
val defaultParamIndex = typedArgs.size
776+
// A map from lifted argument index to the corresponding position in the original argument list
777+
def originalIndex(n: Int) =
778+
if (n < originalIndices.length) originalIndices(n) else orderedArgs.length
779+
scala.util.Sorting.stableSort[(Tree, Int), Int](
780+
argDefBuf.zip(impureArgIndices), (arg, idx) => originalIndex(idx)).map(_._1)
776781
}
777-
778782
liftedDefs ++= orderedArgDefs
779783
}
780784
if (sameSeq(typedArgs, args)) // trick to cut down on tree copying

0 commit comments

Comments
 (0)