Repository: eslint/eslint
File: lib/rules/no-useless-assignment.js (JavaScript)

Code before:
             */
            function isIdentifierUsedInSegment(segment, identifier) {
                const segmentInfo = target.segments[segment.id];

                return (
                    segmentInfo.first &&
                    segmentInfo.last &&
                    segmentInfo.first.range[0] <= identifier.range[0] &&
                    identifier.range[1] <= segmentInfo.last.range[1]
                );
            }

            /**
             * Verifies whether the given assignment info is an used assignment.
             * Report if it is an unused assignment.
             * @param {AssignmentInfo} targetAssignment The assignment info to verify.
             * @param {AssignmentInfo[]} allAssignments The list of all assignment info for variables.
             * @returns {void}
             */
            function verifyAssignmentIsUsed(targetAssignment, allAssignments) {

                // Check if the variable is used in a catch clause
                const isUsedInCatchClause = targetAssignment.variable.references.some(reference => {
                    const id = reference.identifier;

                    if (id.parent.type !== "AssignmentExpression") {
                        return [...scopeStack.catchClauses].some(catchClause =>
                            catchClause.range[0] <= id.range[0] && id.range[1] <= catchClause.range[1]);
                    }

                    return false;
                });

                if (isUsedInCatchClause) {
                    return;
                }

                /**
                 * @typedef {Object} SubsequentSegmentData
                 * @property {CodePathSegment} segment The code path segment
                 * @property {AssignmentInfo} [assignment] The first occurrence of the assignment within the segment.
                 * There is no need to check if the variable is used after this assignment,
                 * as the value it was assigned will be used.
                 */

                /**
                 * Information used in `getSubsequentSegments()`.
                 * To avoid unnecessary iterations, cache information that has already been iterated over,
                 * and if additional iterations are needed, start iterating from the retained position.
                 */
                const subsequentSegmentData = {

Review comment (suggestion):
I think this case would remain a false ~negative~ positive:

```js
function foo(){
    let bar, baz;
    try {
        bar = 2;
        unsafeFn();
        return { error: undefined };
    } catch {
        baz = bar;
    }
    return baz;
}
function unsafeFn() {
    throw new Error();
}
```

If the check for `AssignmentExpression` is intended to skip write-only references, we can use `reference.isRead()` instead.

Code after:
             */
            function isIdentifierUsedInSegment(segment, identifier) {
                const segmentInfo = target.segments[segment.id];

                return (
                    segmentInfo.first &&
                    segmentInfo.last &&
                    segmentInfo.first.range[0] <= identifier.range[0] &&
                    identifier.range[1] <= segmentInfo.last.range[1]
                );
            }

            /**
             * Verifies whether the given assignment info is an used assignment.
             * Report if it is an unused assignment.
             * @param {AssignmentInfo} targetAssignment The assignment info to verify.
             * @param {AssignmentInfo[]} allAssignments The list of all assignment info for variables.
             * @returns {void}
             */
            function verifyAssignmentIsUsed(targetAssignment, allAssignments) {

                // Skip assignment if it is in a try block.
                const isAssignmentInTryBlock = target.tryStatementBlocks.some(tryBlock =>
                    tryBlock.range[0] <= targetAssignment.identifier.range[0] &&
                    targetAssignment.identifier.range[1] <= tryBlock.range[1]
                );

                if (isAssignmentInTryBlock) {
                    return;
                }

                /**
                 * @typedef {Object} SubsequentSegmentData
                 * @property {CodePathSegment} segment The code path segment
                 * @property {AssignmentInfo} [assignment] The first occurrence of the assignment within the segment.
                 * There is no need to check if the variable is used after this assignment,
                 * as the value it was assigned will be used.
                 */

                /**
                 * Information used in `getSubsequentSegments()`.
                 * To avoid unnecessary iterations, cache information that has already been iterated over,
                 * and if additional iterations are needed, start iterating from the retained position.
                 */
                const subsequentSegmentData = {

                    /**
                     * Cache of subsequent segment information list that have already been iterated.
                     * @type {SubsequentSegmentData[]}
                     */
                    results: [],