Skip to content

Commit 2d4d9e7

Browse files
committed
Consider setter of effectively private var
Anonymous classes get a setter for a var member: as usual, don't warn about the setter but only about the var getter. Additionally, check whether the setter is referenced before claiming that the var is unset.
1 parent 13077f7 commit 2d4d9e7

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import dotty.tools.dotc.config.ScalaSettings
77
import dotty.tools.dotc.core.Contexts.*
88
import dotty.tools.dotc.core.Flags.*
99
import dotty.tools.dotc.core.Names.{Name, SimpleName, DerivedName, TermName, termName}
10-
import dotty.tools.dotc.core.NameOps.{isAnonymousFunctionName, isReplWrapperName}
10+
import dotty.tools.dotc.core.NameOps.{isAnonymousFunctionName, isReplWrapperName, setterName}
1111
import dotty.tools.dotc.core.NameKinds.{
1212
BodyRetainerName, ContextBoundParamName, ContextFunctionParamName, DefaultGetterName, WildcardParamName}
1313
import dotty.tools.dotc.core.StdNames.nme
@@ -505,7 +505,13 @@ object CheckUnused:
505505
if sym.isLocalToBlock then
506506
if ctx.settings.WunusedHas.locals && sym.is(Mutable) && !infos.asss(sym) then
507507
warnAt(pos)(UnusedSymbol.unsetLocals)
508-
else if ctx.settings.WunusedHas.privates && sym.isAllOf(Private | Mutable) && !infos.asss(sym) then
508+
else if ctx.settings.WunusedHas.privates
509+
&& sym.is(Mutable)
510+
&& sym.isEffectivelyPrivate
511+
&& !sym.isSetter // tracks sym.underlyingSymbol sibling getter, check setter below
512+
&& !infos.asss(sym)
513+
&& !infos.refs(sym.owner.info.member(sym.name.asTermName.setterName).symbol)
514+
then
509515
warnAt(pos)(UnusedSymbol.unsetPrivates)
510516

511517
def checkPrivate(sym: Symbol, pos: SrcPos) =
@@ -514,7 +520,10 @@ object CheckUnused:
514520
&& !sym.isOneOf(SelfName | Synthetic | CaseAccessor)
515521
&& !sym.name.is(BodyRetainerName)
516522
&& !sym.isSerializationSupport
517-
&& !(sym.is(Mutable) && sym.isSetter && sym.owner.is(Trait)) // tracks sym.underlyingSymbol sibling getter
523+
&& !( sym.is(Mutable)
524+
&& sym.isSetter // tracks sym.underlyingSymbol sibling getter
525+
&& (sym.owner.is(Trait) || sym.owner.isAnonymousClass)
526+
)
518527
&& !infos.nowarn(sym)
519528
then
520529
warnAt(pos)(UnusedSymbol.privateMembers)

tests/warn/i23200.check

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- [E198] Unused Symbol Warning: tests/warn/i23200.scala:8:8 -----------------------------------------------------------
2+
8 | var x: Int = 42 // warn
3+
| ^
4+
| unset private variable, consider using an immutable val instead
5+
-- [E198] Unused Symbol Warning: tests/warn/i23200.scala:40:6 ----------------------------------------------------------
6+
40 | var x: Int = 42 // warn local var
7+
| ^
8+
| unset local variable, consider using an immutable val instead

tests/warn/i23200.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//> using options -Wunused:all
2+
3+
trait Foo
4+
trait Bar
5+
6+
def `anon not updated` =
7+
new Foo {
8+
var x: Int = 42 // warn
9+
val _ = new Bar:
10+
println(x)
11+
//x = 27
12+
//x_=(27)
13+
}
14+
def `anon yes updated` =
15+
new Foo {
16+
var x: Int = 42 // nowarn
17+
val _ = new Bar:
18+
println(x)
19+
x = 27
20+
//x_=(27)
21+
}
22+
def `anon yes updated from nested context` =
23+
new Foo {
24+
var x: Int = 42 // nowarn
25+
val _ = new Bar:
26+
println(x)
27+
x = 27
28+
//x_=(27)
29+
}
30+
def `anon yes updated in daring use of setter` =
31+
new Foo {
32+
var x: Int = 42 // nowarn
33+
val _ = new Bar:
34+
println(x)
35+
//x = 27
36+
x_=(27)
37+
}
38+
39+
def f: Unit =
40+
var x: Int = 42 // warn local var
41+
println(x)

0 commit comments

Comments
 (0)