Skip to content

Commit 0cc52d0

Browse files
som-snytttgodzik
authored andcommitted
Unused var message mentions unread or unset (scala#23719)
Fixes scala#23704 Further distinguish whether a variable was "mutated but not read". [Cherry-picked 212ab3f]
1 parent 641a408 commit 0cc52d0

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
@@ -3224,11 +3224,13 @@ extends Message(UnusedSymbolID):
32243224
object UnusedSymbol:
32253225
def imports(actions: List[CodeAction])(using Context): UnusedSymbol = UnusedSymbol(i"unused import", actions)
32263226
def localDefs(using Context): UnusedSymbol = UnusedSymbol(i"unused local definition")
3227+
def localVars(using Context): UnusedSymbol = UnusedSymbol(i"local variable was mutated but not read")
32273228
def explicitParams(sym: Symbol)(using Context): UnusedSymbol =
32283229
UnusedSymbol(i"unused explicit parameter${paramAddendum(sym)}")
32293230
def implicitParams(sym: Symbol)(using Context): UnusedSymbol =
32303231
UnusedSymbol(i"unused implicit parameter${paramAddendum(sym)}")
32313232
def privateMembers(using Context): UnusedSymbol = UnusedSymbol(i"unused private member")
3233+
def privateVars(using Context): UnusedSymbol = UnusedSymbol(i"private variable was mutated but not read")
32323234
def patVars(using Context): UnusedSymbol = UnusedSymbol(i"unused pattern variable")
32333235
def unsetLocals(using Context): UnusedSymbol =
32343236
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
@@ -536,8 +536,11 @@ object CheckUnused:
536536
val warnings = ArrayBuilder.make[MessageInfo]
537537
def warnAt(pos: SrcPos)(msg: UnusedSymbol, origin: String = ""): Unit = warnings.addOne((msg, pos, origin))
538538
val infos = refInfos
539-
//println(infos.defs.mkString("DEFS\n", "\n", "\n---"))
540-
//println(infos.refs.mkString("REFS\n", "\n", "\n---"))
539+
540+
// non-local sym was target of assignment or has a sibling setter that was referenced
541+
def isMutated(sym: Symbol): Boolean =
542+
infos.asss(sym)
543+
|| infos.refs(sym.owner.info.member(sym.name.asTermName.setterName).symbol)
541544

542545
def checkUnassigned(sym: Symbol, pos: SrcPos) =
543546
if sym.isLocalToBlock then
@@ -547,8 +550,7 @@ object CheckUnused:
547550
&& sym.is(Mutable)
548551
&& (sym.is(Private) || sym.isEffectivelyPrivate)
549552
&& !sym.isSetter // tracks sym.underlyingSymbol sibling getter, check setter below
550-
&& !infos.asss(sym)
551-
&& !infos.refs(sym.owner.info.member(sym.name.asTermName.setterName).symbol)
553+
&& !isMutated(sym)
552554
then
553555
warnAt(pos)(UnusedSymbol.unsetPrivates)
554556

@@ -564,7 +566,10 @@ object CheckUnused:
564566
)
565567
&& !infos.nowarn(sym)
566568
then
567-
warnAt(pos)(UnusedSymbol.privateMembers)
569+
if sym.is(Mutable) && isMutated(sym) then
570+
warnAt(pos)(UnusedSymbol.privateVars)
571+
else
572+
warnAt(pos)(UnusedSymbol.privateMembers)
568573

569574
def checkParam(sym: Symbol, pos: SrcPos) =
570575
val m = sym.owner
@@ -667,7 +672,10 @@ object CheckUnused:
667672
&& !sym.is(InlineProxy)
668673
&& !sym.isCanEqual
669674
then
670-
warnAt(pos)(UnusedSymbol.localDefs)
675+
if sym.is(Mutable) && infos.asss(sym) then
676+
warnAt(pos)(UnusedSymbol.localVars)
677+
else
678+
warnAt(pos)(UnusedSymbol.localDefs)
671679

672680
def checkPatvars() =
673681
// 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)