@@ -424,9 +424,12 @@ impl<'a> Symbol<'_, 'a> {
424424 // When symbol is being assigned a new value, we flag the reference
425425 // as only affecting itself until proven otherwise.
426426 AstKind :: UpdateExpression ( UpdateExpression { argument, .. } ) => {
427- // `a.b++` or `a[b] + 1` are not reassignment of `a`
428- if !argument. is_member_expression ( ) {
429- is_used_by_others = false ;
427+ // `for (let x = 0; x++; ) {}` is valid usage, as the loop body running is a side-effect
428+ if !self . is_in_for_loop_test_or_update ( node. id ( ) , ref_span) {
429+ // `a.b++` or `a[b] + 1` are not reassignment of `a`
430+ if !argument. is_member_expression ( ) {
431+ is_used_by_others = false ;
432+ }
430433 }
431434 }
432435 // RHS usage when LHS != reference's symbol is definitely used by
@@ -543,6 +546,27 @@ impl<'a> Symbol<'_, 'a> {
543546 !is_used_by_others
544547 }
545548
549+ /// Check if a [`AstNode`] is within the test or update section of a for loop.
550+ fn is_in_for_loop_test_or_update ( & self , node_id : NodeId , node_span : Span ) -> bool {
551+ for parent in self . iter_relevant_parents_of ( node_id) . map ( AstNode :: kind) {
552+ match parent {
553+ AstKind :: ForStatement ( for_stmt) => {
554+ return for_stmt
555+ . test
556+ . as_ref ( )
557+ . is_some_and ( |test| test. span ( ) . contains_inclusive ( node_span) )
558+ || for_stmt
559+ . update
560+ . as_ref ( )
561+ . is_some_and ( |update| update. span ( ) . contains_inclusive ( node_span) ) ;
562+ }
563+ x if x. is_statement ( ) => return false ,
564+ _ => { }
565+ }
566+ }
567+ false
568+ }
569+
546570 /// Check if a [`AstNode`] is within a return statement or implicit return.
547571 fn is_in_return_statement ( & self , node_id : NodeId ) -> bool {
548572 for parent in self . iter_relevant_parents_of ( node_id) . map ( AstNode :: kind) {
0 commit comments