oxc-project/oxc · error · OxcDiagnostic
Misrefactored assign op. Variable appears on both sides of a
Error message
Misrefactored assign op. Variable appears on both sides of an assignment operation
What it means
Oxlint rule `oxc/misrefactored-assign-op` (ported from clippy's misrefactored_assign_op) flags compound assignments whose right-hand side repeats the assigned target under the same operator: `a op= a op b`, and for commutative operators (+, *, |, ^, &) also `a op= b op a`. These are almost always a half-finished refactor between `a = a op b` and `a op= b`; e.g. `a += a + 1` actually computes `a = a + (a + 1)`. Member targets (`obj.x += obj.x + 1`) are matched too, and the rule provides an autofix to `a op= b`.
Source
Thrown at crates/oxc_linter/src/rules/oxc/misrefactored_assign_op.rs:19
// Based on https://github.com/rust-lang/rust-clippy//blob/c9a43b18f11219fa70fe632b29518581fcd589c8/clippy_lints/src/operators/misrefactored_assign_op.rs
use oxc_ast::{
AstKind,
ast::{AssignmentTarget, Expression, SimpleAssignmentTarget, match_member_expression},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator};
use crate::{
AstNode,
context::LintContext,
rule::Rule,
utils::{is_same_expression, is_same_member_expression},
};
fn misrefactored_assign_op_diagnostic(span: Span, suggestion: &str) -> OxcDiagnostic {
OxcDiagnostic::warn(
"Misrefactored assign op. Variable appears on both sides of an assignment operation",
)
.with_help(format!("Did you mean `{suggestion}`?"))
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct MisrefactoredAssignOp;
declare_oxc_lint!(
/// ### What it does
///
/// https://rust-lang.github.io/rust-clippy/master/#/misrefactored_assign_op
///
/// Checks for `a op= a op b` or `a op= b op a` patterns.
///
/// ### Why is this bad?
///View on GitHub (pinned to e1e7af627c)
Solutions
- Apply the suggested form (autofix available): drop the duplicated target from the right-hand side
- If both operations were truly intended (`a = a + (a + 1)`), rewrite it as a plain assignment with parentheses so the grouping is explicit
- Re-run tests on arithmetic-heavy code after any assignment refactor
Example fix
// before a += a + 1; // computes a = a + (a + 1) // after a += 1;
Defensive patterns
Strategy: validation
Validate before calling
// .oxlintrc.json — suspicious rule with autofix
{
"rules": { "oxc/misrefactored-assign-op": "error" }
}
// CLI (applies the fix): npx oxlint --fix src/ Prevention
- When converting `a = a op b` to `a op= b`, delete the duplicated target on the right
- After codemods touching assignments, run oxlint and arithmetic tests
- Prefer writing the compound form directly instead of editing the long form in place
When it happens
Trigger: `a += a + 1` (fix: `a += 1`); `a -= a - 1` (fix: `a -= 1`); `a *= 42 * a` (fix: `a *= 42`); `a /= a / 2`; `obj.x += obj.x + n`.
Common situations: Mechanical refactors from `a = a + b` to `a += b` that leave the old right-hand side; codemod or sed rewrites; merging statements by hand.
Related errors
- Invalid character comparison
- Bad comparison sequence
- Math.min and Math.max combination leads to constant result
- Unexpected object literal comparison.
- Unexpected array literal comparison.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/d5c95c340f8bdeee.
Report an issue: GitHub.