Skip to content

Commit 12e5dc7

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 f87554b commit 12e5dc7

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
@@ -734,23 +734,27 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
734734
// lift arguments in the definition order
735735
val argDefBuf = mutable.ListBuffer.empty[Tree]
736736
typedArgs = lifter.liftArgs(argDefBuf, methType, typedArgs)
737-
738737
// Lifted arguments ordered based on the original order of typedArgBuf and
739738
// with all non-explicit default parameters at the end in declaration order.
740739
val orderedArgDefs = {
741-
// List of original arguments that are lifted by liftArgs
742-
val impureArgs = typedArgBuf.filterNot(lifter.noLift)
743-
// Assuming stable sorting all non-explicit default parameters will remain in the end with the same order
744-
val defaultParamIndex = args.size
745-
// Mapping of index of each `liftable` into original args ordering
746-
val indices = impureArgs.map { arg =>
747-
val idx = args.indexOf(arg)
748-
if (idx >= 0) idx // original index skipping pure arguments
749-
else defaultParamIndex
740+
// Indices of original typed arguments that are lifted by liftArgs
741+
val impureArgIndices = typedArgBuf.zipWithIndex.collect {
742+
case (arg, idx) if !lifter.noLift(arg) => idx
743+
}
744+
def position(arg: Trees.Tree[T]) = {
745+
val i = args.indexOf(arg)
746+
if (i >= 0) i else orderedArgs.length
750747
}
751-
scala.util.Sorting.stableSort[(Tree, Int), Int](argDefBuf zip indices, x => x._2).map(_._1)
748+
// The original indices of all ordered arguments, as an array
749+
val originalIndices = orderedArgs.map(position).toArray
750+
// Assuming stable sorting all non-explicit default parameters will remain in the end with the same order
751+
val defaultParamIndex = typedArgs.size
752+
// A map from lifted argument index to the corresponding position in the original argument list
753+
def originalIndex(n: Int) =
754+
if (n < originalIndices.length) originalIndices(n) else orderedArgs.length
755+
scala.util.Sorting.stableSort[(Tree, Int), Int](
756+
argDefBuf.zip(impureArgIndices), (arg, idx) => originalIndex(idx)).map(_._1)
752757
}
753-
754758
liftedDefs ++= orderedArgDefs
755759
}
756760
if (sameSeq(typedArgs, args)) // trick to cut down on tree copying

0 commit comments

Comments
 (0)