Skip to content

Commit 23dfe91

Browse files
committed
Named arg may be deprecatedName
1 parent 83e9fe9 commit 23dfe91

File tree

3 files changed

+70
-11
lines changed

3 files changed

+70
-11
lines changed

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

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,21 @@ trait Applications extends Compatibility {
604604

605605
inline def tailOf[A](list: List[A]): List[A] = if list.isEmpty then list else list.tail // list.drop(1)
606606

607+
def hasDeprecatedName(pname: Name, other: Name, t: Trees.Tree[T]): Boolean = !ctx.isAfterTyper &&
608+
methRef.symbol.paramSymss.flatten.find(_.name == pname).flatMap(_.getAnnotation(defn.DeprecatedNameAnnot)).match
609+
case Some(annot) =>
610+
val name = annot.argumentConstantString(0)
611+
val version = annot.argumentConstantString(1).filter(!_.isEmpty)
612+
val since = version.map(v => s" (since $v)").getOrElse("")
613+
name.map(_.toTermName) match
614+
case Some(`other`) =>
615+
report.deprecationWarning(em"the parameter name $other is deprecated$since: use $pname instead", t.srcPos)
616+
case Some(`pname`) | None =>
617+
report.deprecationWarning(em"naming parameter $pname is deprecated$since", t.srcPos)
618+
case _ =>
619+
true
620+
case _ => false
621+
607622
/** Reorder the suffix of named args per a list of required names.
608623
*
609624
* @param pnames The list of parameter names that are missing arguments
@@ -619,25 +634,32 @@ trait Applications extends Compatibility {
619634
*/
620635
def handleNamed(pnames: List[Name], args: List[Trees.Tree[T]],
621636
nameToArg: Map[Name, Trees.NamedArg[T]], toDrop: Set[Name],
622-
missingArgs: Boolean): List[Trees.Tree[T]] = pnames match
623-
case pname :: pnames if nameToArg.contains(pname) =>
624-
// there is a named argument for this parameter; pick it
625-
nameToArg(pname) :: handleNamed(pnames, args, nameToArg - pname, toDrop + pname, missingArgs)
637+
missingArgs: Boolean): List[Trees.Tree[T]] =
638+
pnames match
639+
case pname :: pnames if nameToArg.contains(pname) => // use the named argument for this parameter
640+
val arg = nameToArg(pname)
641+
hasDeprecatedName(pname, nme.NO_NAME, arg)
642+
arg :: handleNamed(pnames, args, nameToArg - pname, toDrop + pname, missingArgs)
626643
case _ =>
627644
args match
628-
case (arg @ NamedArg(aname, _)) :: args1 =>
629-
if toDrop.contains(aname) // named argument is already passed
630-
then handleNamed(pnames, args1, nameToArg, toDrop - aname, missingArgs)
631-
else if nameToArg.contains(aname) && pnames.nonEmpty // argument is missing, pass an empty tree
632-
then genericEmptyTree :: handleNamed(pnames.tail, args, nameToArg, toDrop, missingArgs = true)
645+
case allArgs @ (arg @ NamedArg(aname, _)) :: args =>
646+
if toDrop.contains(aname) then // named argument was already picked
647+
handleNamed(pnames, args, nameToArg, toDrop - aname, missingArgs)
648+
else if pnames.nonEmpty && nameToArg.contains(aname) then
649+
val pname = pnames.head
650+
if hasDeprecatedName(pname, aname, arg) then // name was deprecated alt, so try again with canonical name
651+
val parg = cpy.NamedArg(arg)(pname, arg.arg).asInstanceOf[Trees.NamedArg[T]]
652+
handleNamed(pnames, parg :: args, nameToArg.removed(aname).updated(pname, parg), toDrop, missingArgs)
653+
else // argument for pname is missing, pass an empty tree
654+
genericEmptyTree :: handleNamed(pnames.tail, allArgs, nameToArg, toDrop, missingArgs = true)
633655
else // name not (or no longer) available for named arg
634656
def msg =
635657
if methodType.paramNames.contains(aname) then
636658
em"parameter $aname of $methString is already instantiated"
637659
else
638660
em"$methString does not have a parameter $aname"
639661
fail(msg, arg.asInstanceOf[Arg])
640-
arg :: handleNamed(tailOf(pnames), args1, nameToArg, toDrop, missingArgs)
662+
arg :: handleNamed(tailOf(pnames), args, nameToArg, toDrop, missingArgs)
641663
case arg :: args =>
642664
if toDrop.nonEmpty || missingArgs then
643665
report.error(i"positional after named argument", arg.srcPos)
@@ -649,8 +671,10 @@ trait Applications extends Compatibility {
649671
/** Skip prefix of positional args, then handleNamed */
650672
def handlePositional(pnames: List[Name], args: List[Trees.Tree[T]]): List[Trees.Tree[T]] =
651673
args match
674+
case (arg @ NamedArg(name, _)) :: args if !pnames.isEmpty && pnames.head == name =>
675+
hasDeprecatedName(name, nme.NO_NAME, arg)
676+
arg :: handlePositional(pnames.tail, args)
652677
case (_: NamedArg) :: _ =>
653-
//val nameAssocs = for case arg @ NamedArg(name, _) <- args yield (name, arg)
654678
val nameAssocs = args.collect { case arg @ NamedArg(name, _) => name -> arg }
655679
handleNamed(pnames, args, nameAssocs.toMap, toDrop = Set.empty, missingArgs = false)
656680
case arg :: args =>

tests/warn/i19077.check

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
-- Deprecation Warning: tests/warn/i19077.scala:8:6 --------------------------------------------------------------------
2+
8 | f(x = 1, 2, 3) // warn
3+
| ^^^^^
4+
| naming parameter x is deprecated
5+
-- Deprecation Warning: tests/warn/i19077.scala:9:9 --------------------------------------------------------------------
6+
9 | f(1, y = 2, 3) // warn
7+
| ^^^^^
8+
| naming parameter y is deprecated
9+
-- Deprecation Warning: tests/warn/i19077.scala:10:12 ------------------------------------------------------------------
10+
10 | f(1, 2, w = 3) // warn
11+
| ^^^^^
12+
| the parameter name w is deprecated: use z instead
13+
-- Deprecation Warning: tests/warn/i19077.scala:11:13 ------------------------------------------------------------------
14+
11 | f(w = 3, x = 1, y = 2) // warn // warn // warn
15+
| ^^^^^
16+
| naming parameter x is deprecated
17+
-- Deprecation Warning: tests/warn/i19077.scala:11:20 ------------------------------------------------------------------
18+
11 | f(w = 3, x = 1, y = 2) // warn // warn // warn
19+
| ^^^^^
20+
| naming parameter y is deprecated
21+
-- Deprecation Warning: tests/warn/i19077.scala:11:6 -------------------------------------------------------------------
22+
11 | f(w = 3, x = 1, y = 2) // warn // warn // warn
23+
| ^^^^^
24+
| the parameter name w is deprecated: use z instead

tests/warn/i19077.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//> using options -deprecation
2+
3+
def f(@deprecatedName("x") x: Int, @deprecatedName y: Int, @deprecatedName("w") z: Int) = x+y+z
4+
5+
@main def Test =
6+
f(1, 2, 3) // nowarn
7+
f(1, 2, z = 3) // nowarn
8+
f(x = 1, 2, 3) // warn
9+
f(1, y = 2, 3) // warn
10+
f(1, 2, w = 3) // warn
11+
f(w = 3, x = 1, y = 2) // warn // warn // warn

0 commit comments

Comments
 (0)