Skip to content

Commit 212ab3f

Browse files
authored
Unused var message mentions unread or unset (#23719)
Fixes #23704 Further distinguish whether a variable was "mutated but not read".
1 parent fa03916 commit 212ab3f

File tree

4 files changed

+75
-6
lines changed

4 files changed

+75
-6
lines changed

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3381,11 +3381,13 @@ extends Message(UnusedSymbolID):
33813381
object UnusedSymbol:
33823382
def imports(actions: List[CodeAction])(using Context): UnusedSymbol = UnusedSymbol(i"unused import", actions)
33833383
def localDefs(using Context): UnusedSymbol = UnusedSymbol(i"unused local definition")
3384+
def localVars(using Context): UnusedSymbol = UnusedSymbol(i"local variable was mutated but not read")
33843385
def explicitParams(sym: Symbol)(using Context): UnusedSymbol =
33853386
UnusedSymbol(i"unused explicit parameter${paramAddendum(sym)}")
33863387
def implicitParams(sym: Symbol)(using Context): UnusedSymbol =
33873388
UnusedSymbol(i"unused implicit parameter${paramAddendum(sym)}")
33883389
def privateMembers(using Context): UnusedSymbol = UnusedSymbol(i"unused private member")
3390+
def privateVars(using Context): UnusedSymbol = UnusedSymbol(i"private variable was mutated but not read")
33893391
def patVars(using Context): UnusedSymbol = UnusedSymbol(i"unused pattern variable")
33903392
def unsetLocals(using Context): UnusedSymbol =
33913393
UnusedSymbol(i"unset local variable, consider using an immutable val instead")

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,11 @@ object CheckUnused:
498498
val warnings = ArrayBuilder.make[MessageInfo]
499499
def warnAt(pos: SrcPos)(msg: UnusedSymbol, origin: String = ""): Unit = warnings.addOne((msg, pos, origin))
500500
val infos = refInfos
501-
//println(infos.defs.mkString("DEFS\n", "\n", "\n---"))
502-
//println(infos.refs.mkString("REFS\n", "\n", "\n---"))
501+
502+
// non-local sym was target of assignment or has a sibling setter that was referenced
503+
def isMutated(sym: Symbol): Boolean =
504+
infos.asss(sym)
505+
|| infos.refs(sym.owner.info.member(sym.name.asTermName.setterName).symbol)
503506

504507
def checkUnassigned(sym: Symbol, pos: SrcPos) =
505508
if sym.isLocalToBlock then
@@ -509,8 +512,7 @@ object CheckUnused:
509512
&& sym.is(Mutable)
510513
&& (sym.is(Private) || sym.isEffectivelyPrivate)
511514
&& !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)
515+
&& !isMutated(sym)
514516
then
515517
warnAt(pos)(UnusedSymbol.unsetPrivates)
516518

@@ -526,7 +528,10 @@ object CheckUnused:
526528
)
527529
&& !infos.nowarn(sym)
528530
then
529-
warnAt(pos)(UnusedSymbol.privateMembers)
531+
if sym.is(Mutable) && isMutated(sym) then
532+
warnAt(pos)(UnusedSymbol.privateVars)
533+
else
534+
warnAt(pos)(UnusedSymbol.privateMembers)
530535

531536
def checkParam(sym: Symbol, pos: SrcPos) =
532537
val m = sym.owner
@@ -629,7 +634,10 @@ object CheckUnused:
629634
&& !sym.is(InlineProxy)
630635
&& !sym.isCanEqual
631636
then
632-
warnAt(pos)(UnusedSymbol.localDefs)
637+
if sym.is(Mutable) && infos.asss(sym) then
638+
warnAt(pos)(UnusedSymbol.localVars)
639+
else
640+
warnAt(pos)(UnusedSymbol.localDefs)
633641

634642
def checkPatvars() =
635643
// convert the one non-synthetic span so all are comparable; filter NoSpan below

tests/warn/i23704.check

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- [E198] Unused Symbol Warning: tests/warn/i23704.scala:9:8 -----------------------------------------------------------
2+
9 | var position: Int = 0 // warn position is assigned but not read
3+
| ^^^^^^^^
4+
| private variable was mutated but not read
5+
-- [E198] Unused Symbol Warning: tests/warn/i23704.scala:16:14 ---------------------------------------------------------
6+
16 | private var myvar: Int = 0 // warn for the same case with simpler syntax
7+
| ^^^^^
8+
| private variable was mutated but not read
9+
-- [E198] Unused Symbol Warning: tests/warn/i23704.scala:26:8 ----------------------------------------------------------
10+
26 | var localvar = 0 // warn local variable was mutated but not read
11+
| ^^^^^^^^
12+
| local variable was mutated but not read
13+
-- [E198] Unused Symbol Warning: tests/warn/i23704.scala:33:8 ----------------------------------------------------------
14+
33 | var settable: Int = 0 // warn private variable was mutated but not read
15+
| ^^^^^^^^
16+
| private variable was mutated but not read
17+
-- [E198] Unused Symbol Warning: tests/warn/i23704.scala:39:14 ---------------------------------------------------------
18+
39 | private var myvar: Int = 0 // warn plain unused
19+
| ^^^^^
20+
| unused private member

tests/warn/i23704.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//> using options -Wunused:all
2+
3+
trait Test {
4+
def incr(): Unit
5+
}
6+
7+
object Test {
8+
val test = new Test {
9+
var position: Int = 0 // warn position is assigned but not read
10+
11+
def incr(): Unit = { position += 1 }
12+
}
13+
}
14+
15+
class C:
16+
private var myvar: Int = 0 // warn for the same case with simpler syntax
17+
def mine: Int =
18+
myvar = 42
19+
27
20+
21+
class D:
22+
private var myvar: Int = 0 // nowarn (although read is RHS of assignment)
23+
def incr(): Unit = myvar = myvar + 1
24+
25+
def local(): Unit =
26+
var localvar = 0 // warn local variable was mutated but not read
27+
localvar += 1
28+
29+
class E:
30+
trait Setting:
31+
def setting(): Unit
32+
val test = new Test:
33+
var settable: Int = 0 // warn private variable was mutated but not read
34+
def setting(): Unit =
35+
settable_=(42)
36+
def incr() = setting()
37+
38+
class F:
39+
private var myvar: Int = 0 // warn plain unused

0 commit comments

Comments
 (0)