Skip to content

Commit 2dc97d9

Browse files
committed
Check if param was used in default arg getter
1 parent 9fc5c89 commit 2dc97d9

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ object CheckUnused:
534534
// A class param is unused if its param accessor is unused.
535535
// (The class param is not assigned to a field until constructors.)
536536
// A local param accessor warns as a param; a private accessor as a private member.
537-
// Avoid warning for case class elements because they are aliased via unapply.
537+
// Avoid warning for case class elements because they are aliased via unapply (i.e. may be extracted).
538538
if m.isPrimaryConstructor then
539539
val alias = m.owner.info.member(sym.name)
540540
if alias.exists then
@@ -555,6 +555,7 @@ object CheckUnused:
555555
)
556556
&& !sym.name.isInstanceOf[DerivedName]
557557
&& !ctx.platform.isMainMethod(m)
558+
&& !usedByDefaultGetter(sym, m)
558559
then
559560
warnAt(pos)(UnusedSymbol.explicitParams(sym))
560561
end checkExplicit
@@ -566,6 +567,16 @@ object CheckUnused:
566567
checkExplicit()
567568
end checkParam
568569

570+
// does the param have an alias in a default arg method that is used?
571+
def usedByDefaultGetter(param: Symbol, meth: Symbol): Boolean =
572+
val cls = meth.enclosingClass
573+
val MethName = meth.name
574+
cls.info.decls.exists: d =>
575+
d.name match
576+
case DefaultGetterName(MethName, _) =>
577+
d.paramSymss.exists(_.exists(p => p.name == param.name && infos.refs(p)))
578+
case _ => false
579+
569580
def checkImplicit(sym: Symbol, pos: SrcPos) =
570581
val m = sym.owner
571582
def allowed =
@@ -597,7 +608,7 @@ object CheckUnused:
597608
|| aliasSym.isAllOf(Protected | ParamAccessor, butNot = CaseAccessor) && m.owner.is(Given)
598609
if checking && !infos.refs(alias.symbol) then
599610
warnAt(pos)(UnusedSymbol.implicitParams(aliasSym))
600-
else
611+
else if !usedByDefaultGetter(sym, m) then
601612
warnAt(pos)(UnusedSymbol.implicitParams(sym))
602613

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

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)