@@ -503,7 +503,21 @@ trait Applications extends Compatibility {
503
503
def infoStr = if methType.isErroneous then " " else i " : $methType"
504
504
i " ${err.refStr(methRef)}$infoStr"
505
505
506
- /** Re-order arguments to correctly align named arguments */
506
+ /** Re-order arguments to correctly align named arguments
507
+ * Issue errors in the following situations:
508
+ *
509
+ * - "positional after named argument" if a positional argument follows a named
510
+ * argument and one of the following is true:
511
+ *
512
+ * - There is a formal argument before the argument position
513
+ * that has not yet been instantiated with a previous actual argument,
514
+ * (either named or positional), or
515
+ * - The formal parameter at the argument position is also mentioned
516
+ * in a subsequent named parameter.
517
+ * - "parameter already instantiated" if a two named arguments have the same name.
518
+ * - "does not have parameter" if a named parameter does not mention a formal
519
+ * parameter name.
520
+ */
507
521
def reorder [T <: Untyped ](args : List [Trees .Tree [T ]]): List [Trees .Tree [T ]] = {
508
522
509
523
/** @param pnames The list of parameter names that are missing arguments
@@ -517,40 +531,43 @@ trait Applications extends Compatibility {
517
531
* 2. For every `(name -> arg)` in `nameToArg`, `arg` is an element of `args`
518
532
*/
519
533
def handleNamed (pnames : List [Name ], args : List [Trees .Tree [T ]],
520
- nameToArg : Map [Name , Trees .NamedArg [T ]], toDrop : Set [Name ]): List [Trees .Tree [T ]] = pnames match {
534
+ nameToArg : Map [Name , Trees .NamedArg [T ]], toDrop : Set [Name ],
535
+ missingArgs : Boolean ): List [Trees .Tree [T ]] = pnames match {
521
536
case pname :: pnames1 if nameToArg contains pname =>
522
537
// there is a named argument for this parameter; pick it
523
- nameToArg(pname) :: handleNamed(pnames1, args, nameToArg - pname, toDrop + pname)
538
+ nameToArg(pname) :: handleNamed(pnames1, args, nameToArg - pname, toDrop + pname, missingArgs )
524
539
case _ =>
525
540
def pnamesRest = if (pnames.isEmpty) pnames else pnames.tail
526
541
args match {
527
542
case (arg @ NamedArg (aname, _)) :: args1 =>
528
543
if (toDrop contains aname) // argument is already passed
529
- handleNamed(pnames, args1, nameToArg, toDrop - aname)
544
+ handleNamed(pnames, args1, nameToArg, toDrop - aname, missingArgs )
530
545
else if ((nameToArg contains aname) && pnames.nonEmpty) // argument is missing, pass an empty tree
531
- genericEmptyTree :: handleNamed(pnames.tail, args, nameToArg, toDrop)
546
+ genericEmptyTree :: handleNamed(pnames.tail, args, nameToArg, toDrop, missingArgs = true )
532
547
else { // name not (or no longer) available for named arg
533
548
def msg =
534
549
if (methodType.paramNames contains aname)
535
550
em " parameter $aname of $methString is already instantiated "
536
551
else
537
552
em " $methString does not have a parameter $aname"
538
553
fail(msg, arg.asInstanceOf [Arg ])
539
- arg :: handleNamed(pnamesRest, args1, nameToArg, toDrop)
554
+ arg :: handleNamed(pnamesRest, args1, nameToArg, toDrop, missingArgs )
540
555
}
541
556
case arg :: args1 =>
542
- arg :: handleNamed(pnamesRest, args1, nameToArg, toDrop) // unnamed argument; pick it
557
+ if toDrop.nonEmpty || missingArgs then
558
+ report.error(i " positional after named argument " , arg.srcPos)
559
+ arg :: handleNamed(pnamesRest, args1, nameToArg, toDrop, missingArgs) // unnamed argument; pick it
543
560
case Nil => // no more args, continue to pick up any preceding named args
544
561
if (pnames.isEmpty) Nil
545
- else handleNamed(pnamesRest, args, nameToArg, toDrop)
562
+ else handleNamed(pnamesRest, args, nameToArg, toDrop, missingArgs )
546
563
}
547
564
}
548
565
549
566
def handlePositional (pnames : List [Name ], args : List [Trees .Tree [T ]]): List [Trees .Tree [T ]] =
550
567
args match {
551
568
case (arg : NamedArg @ unchecked) :: _ =>
552
569
val nameAssocs = for (case arg @ NamedArg (name, _) <- args) yield (name, arg)
553
- handleNamed(pnames, args, nameAssocs.toMap, Set ())
570
+ handleNamed(pnames, args, nameAssocs.toMap, toDrop = Set (), missingArgs = false )
554
571
case arg :: args1 =>
555
572
arg :: handlePositional(if (pnames.isEmpty) Nil else pnames.tail, args1)
556
573
case Nil => Nil
0 commit comments