@@ -52,6 +52,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
5252 tree
5353
5454 override def transformIdent (tree : Ident )(using Context ): tree.type =
55+ refInfos.isAssignment = tree.hasAttachment(AssignmentTarget )
5556 if tree.symbol.exists then
5657 // if in an inline expansion, resolve at summonInline (synthetic pos) or in an enclosing call site
5758 val resolving =
@@ -68,10 +69,12 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
6869 resolveUsage(tree.symbol, tree.name, tree.typeOpt.importPrefix.skipPackageObject)
6970 else if tree.hasType then
7071 resolveUsage(tree.tpe.classSymbol, tree.name, tree.tpe.importPrefix.skipPackageObject)
72+ refInfos.isAssignment = false
7173 tree
7274
7375 // import x.y; y may be rewritten x.y, also import x.z as y
7476 override def transformSelect (tree : Select )(using Context ): tree.type =
77+ refInfos.isAssignment = tree.hasAttachment(AssignmentTarget )
7578 val name = tree.removeAttachment(OriginalName ).getOrElse(nme.NO_NAME )
7679 inline def isImportable = tree.qualifier.srcPos.isSynthetic
7780 && tree.qualifier.tpe.match
@@ -92,6 +95,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
9295 resolveUsage(tree.symbol, name, tree.qualifier.tpe)
9396 else if ! ignoreTree(tree) then
9497 refUsage(tree.symbol)
98+ refInfos.isAssignment = false
9599 tree
96100
97101 override def transformLiteral (tree : Literal )(using Context ): tree.type =
@@ -113,13 +117,10 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
113117 ctx
114118
115119 override def prepareForAssign (tree : Assign )(using Context ): Context =
116- tree.lhs.putAttachment(Ignore , ()) // don't take LHS reference as a read
120+ tree.lhs.putAttachment(AssignmentTarget , ()) // don't take LHS reference as a read
117121 ctx
118122 override def transformAssign (tree : Assign )(using Context ): tree.type =
119- tree.lhs.removeAttachment(Ignore )
120- val sym = tree.lhs.symbol
121- if sym.exists then
122- refInfos.asss.addOne(sym)
123+ tree.lhs.removeAttachment(AssignmentTarget )
123124 tree
124125
125126 override def prepareForMatch (tree : Match )(using Context ): Context =
@@ -301,7 +302,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
301302 // if sym is not an enclosing element, record the reference
302303 def refUsage (sym : Symbol )(using Context ): Unit =
303304 if ! ctx.outersIterator.exists(cur => cur.owner eq sym) then
304- refInfos.refs.addOne (sym)
305+ refInfos.addRef (sym)
305306
306307 /** Look up a reference in enclosing contexts to determine whether it was introduced by a definition or import.
307308 * The binding of highest precedence must then be correct.
@@ -360,7 +361,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
360361 case none =>
361362
362363 // Avoid spurious NoSymbol and also primary ctors which are never warned about.
363- // Selections C.this.toString should be already excluded, but backtopped here for eq, etc.
364+ // Selections C.this.toString should be already excluded, but backstopped here for eq, etc.
364365 if ! sym.exists || sym.isPrimaryConstructor || sym.isEffectiveRoot || defn.topClasses(sym.owner) then return
365366
366367 // Find the innermost, highest precedence. Contexts have no nesting levels but assume correctness.
@@ -430,7 +431,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
430431 end while
431432 // record usage and possibly an import
432433 if ! enclosed then
433- refInfos.refs.addOne (sym)
434+ refInfos.addRef (sym)
434435 if candidate != NoContext && candidate.isImportContext && importer != null then
435436 refInfos.sels.put(importer, ())
436437 // possibly record that we have performed this look-up
@@ -469,6 +470,9 @@ object CheckUnused:
469470 /** Ignore reference. */
470471 val Ignore = Property .StickyKey [Unit ]
471472
473+ /** Tree is LHS of Assign. */
474+ val AssignmentTarget = Property .StickyKey [Unit ]
475+
472476 class PostTyper extends CheckUnused (PhaseMode .Aggregate , " PostTyper" )
473477
474478 class PostInlining extends CheckUnused (PhaseMode .Report , " PostInlining" )
@@ -513,6 +517,14 @@ object CheckUnused:
513517
514518 val inlined = Stack .empty[SrcPos ] // enclosing call.srcPos of inlined code (expansions)
515519 var inliners = 0 // depth of inline def (not inlined yet)
520+
521+ // instead of refs.addOne, use addRef to distinguish a read from a write to var
522+ var isAssignment = false
523+ def addRef (sym : Symbol ): Unit =
524+ if isAssignment then
525+ asss.addOne(sym)
526+ else
527+ refs.addOne(sym)
516528 end RefInfos
517529
518530 // Symbols already resolved in the given Context (with name and prefix of lookup).
0 commit comments