Skip to content

Commit 0cbe43b

Browse files
committed
Check if param was used in default arg getter
1 parent ec9a060 commit 0cbe43b

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ object CheckUnused:
530530
// A class param is unused if its param accessor is unused.
531531
// (The class param is not assigned to a field until constructors.)
532532
// A local param accessor warns as a param; a private accessor as a private member.
533-
// Avoid warning for case class elements because they are aliased via unapply.
533+
// Avoid warning for case class elements because they are aliased via unapply (i.e. may be extracted).
534534
if m.isPrimaryConstructor then
535535
val alias = m.owner.info.member(sym.name)
536536
if alias.exists then
@@ -551,6 +551,7 @@ object CheckUnused:
551551
)
552552
&& !sym.name.isInstanceOf[DerivedName]
553553
&& !ctx.platform.isMainMethod(m)
554+
&& !usedByDefaultGetter(sym, m)
554555
then
555556
warnAt(pos)(UnusedSymbol.explicitParams(sym))
556557
end checkExplicit
@@ -562,6 +563,16 @@ object CheckUnused:
562563
checkExplicit()
563564
end checkParam
564565

566+
// does the param have an alias in a default arg method that is used?
567+
def usedByDefaultGetter(param: Symbol, meth: Symbol): Boolean =
568+
val cls = meth.enclosingClass
569+
val MethName = meth.name
570+
cls.info.decls.exists: d =>
571+
d.name match
572+
case DefaultGetterName(MethName, _) =>
573+
d.paramSymss.exists(_.exists(p => p.name == param.name && infos.refs(p)))
574+
case _ => false
575+
565576
def checkImplicit(sym: Symbol, pos: SrcPos) =
566577
val m = sym.owner
567578
def allowed =
@@ -593,7 +604,7 @@ object CheckUnused:
593604
|| aliasSym.isAllOf(Protected | ParamAccessor, butNot = CaseAccessor) && m.owner.is(Given)
594605
if checking && !infos.refs(alias.symbol) then
595606
warnAt(pos)(UnusedSymbol.implicitParams(aliasSym))
596-
else
607+
else if !usedByDefaultGetter(sym, m) then
597608
warnAt(pos)(UnusedSymbol.implicitParams(sym))
598609

599610
def checkLocal(sym: Symbol, pos: SrcPos) =

tests/warn/i15503e.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,4 @@ object UnwrapTyped:
9292
error("Compiler bug: `codeOf` was not evaluated by the compiler")
9393

9494
object `default usage`:
95-
def f(i: Int)(j: Int = i * 2) = j // warn I guess
95+
def f(i: Int)(j: Int = i * 2) = j // ~warn~ I guess (see tests/warn/i23349.scala)

tests/warn/i23349.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//> using options -Wunused:explicits
1+
//> using options -Wunused:explicits,implicits
22

33
// An external class that doesn't get its own `copy` method.
44
class Foo(val a: String, val b: Int)
@@ -12,4 +12,9 @@ extension (self: Foo)
1212
//
1313
// Example 2: implement `copyFoo` with parameter groups.
1414
//
15-
def copyFoo(foo: Foo)(a: String = foo.a, b: Int = foo.b): Foo = Foo(a, b) // warn
15+
def copyFoo(foo: Foo)(a: String = foo.a, b: Int = foo.b): Foo = Foo(a, b)
16+
17+
class C:
18+
def copyFoo(foo: Foo, bar: String)(a: String = foo.a, b: Int = foo.b)(c: String = bar): Foo = Foo(a, b) // warn c
19+
def copyUsing(using foo: Foo, bar: String)(a: String = foo.a, b: Int = foo.b)(c: String = bar): Foo = // warn c
20+
Foo(a, b)

0 commit comments

Comments
 (0)