@@ -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  = 
@@ -291,7 +292,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
291292  //  if sym is not an enclosing element, record the reference
292293  def  refUsage (sym : Symbol )(using  Context ):  Unit  = 
293294    if  ! ctx.outersIterator.exists(cur =>  cur.owner eq sym) then 
294-       refInfos.refs.addOne (sym)
295+       refInfos.addRef (sym)
295296
296297  /**  Look up a reference in enclosing contexts to determine whether it was introduced by a definition or import. 
297298   *  The binding of highest precedence must then be correct. 
@@ -341,7 +342,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
341342      &&  ctxsym.thisType.member(sym.name).hasAltWith(d =>  d.containsSym(sym) &&  ! name.exists(_ !=  d.name))
342343
343344    //  Avoid spurious NoSymbol and also primary ctors which are never warned about.
344-     //  Selections C.this.toString should be already excluded, but backtopped  here for eq, etc.
345+     //  Selections C.this.toString should be already excluded, but backstopped  here for eq, etc.
345346    if  ! sym.exists ||  sym.isPrimaryConstructor ||  sym.isEffectiveRoot ||  defn.topClasses(sym.owner) then  return 
346347
347348    //  Find the innermost, highest precedence. Contexts have no nesting levels but assume correctness.
@@ -392,7 +393,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
392393    end while 
393394    //  record usage and possibly an import
394395    if  ! enclosed then 
395-       refInfos.refs.addOne (sym)
396+       refInfos.addRef (sym)
396397    if  candidate !=  NoContext  &&  candidate.isImportContext &&  importer !=  null  then 
397398      refInfos.sels.put(importer, ())
398399  end  resolveUsage 
@@ -417,6 +418,9 @@ object CheckUnused:
417418  /**  Ignore reference. */  
418419  val  Ignore  =  Property .StickyKey [Unit ]
419420
421+   /**  Tree is LHS of Assign. */  
422+   val  AssignmentTarget  =  Property .StickyKey [Unit ]
423+ 
420424  class  PostTyper  extends  CheckUnused (PhaseMode .Aggregate , " PostTyper" 
421425
422426  class  PostInlining  extends  CheckUnused (PhaseMode .Report , " PostInlining" 
@@ -461,6 +465,14 @@ object CheckUnused:
461465
462466    val  inlined  =  Stack .empty[SrcPos ] //  enclosing call.srcPos of inlined code (expansions)
463467    var  inliners  =  0  //  depth of inline def (not inlined yet)
468+ 
469+     //  instead of refs.addOne, use addRef to distinguish a read from a write to var
470+     var  isAssignment  =  false 
471+     def  addRef (sym : Symbol ):  Unit  = 
472+       if  isAssignment then 
473+         asss.addOne(sym)
474+       else 
475+         refs.addOne(sym)
464476  end  RefInfos 
465477
466478  //  Names are resolved by definitions and imports, which have four precedence levels:
0 commit comments