oxc-project/oxc · warning · OxcDiagnostic
Both sides of this comparison are exactly the same
Error message
Both sides of this comparison are exactly the same
What it means
oxlint's port of ESLint `no-self-compare`. It flags comparisons whose left and right operands are structurally identical (`x === x`), checked with AST content equality (ContentEq). The only result of `x === x` is `true` — or `false` when x is NaN — so the help text points at `Number.isNaN()` as the intended check.
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_self_compare.rs:9
use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{ContentEq, GetSpan, Span};
use crate::{AstNode, context::LintContext, rule::Rule};
fn no_self_compare_diagnostic(left_span: Span, right_span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Both sides of this comparison are exactly the same")
.with_help("If you are testing for NaN, you can use the `Number.isNaN()` function.")
.with_labels([left_span, right_span])
}
#[derive(Debug, Default, Clone)]
pub struct NoSelfCompare;
declare_oxc_lint!(
/// ### What it does
///
/// Disallow comparisons where both sides are exactly the same.
///
/// ### Why is this bad?
///
/// Comparing a variable against itself is usually an error, either a typo or refactoring error.
/// It is confusing to the reader and may potentially introduce a runtime error.
///
/// ### ExamplesView on GitHub (pinned to e1e7af627c)
Solutions
- For NaN detection use `Number.isNaN(x)`.
- Otherwise correct the operand that should differ (`x === y`).
- Remove the comparison if it is dead logic that always evaluates to true.
Example fix
// before
if (value === value) { /* skip NaN */ }
// after
if (!Number.isNaN(value)) { /* skip NaN */ } Defensive patterns
Strategy: type-guard
Validate before calling
// Reject self-comparisons before they ship (simple identifier form)
function hasSelfCompare(src) {
return /([A-Za-z_$][\w$.]*)\s*(?:===|!==|==|!=)\s*\1(?![\w$])/.test(src);
} Type guard
// Correct way to express the intent this rule guesses at:
function isNotNaN(value) {
return typeof value === 'number' && !Number.isNaN(value);
}
// use: if (isNotNaN(x)) { ... } instead of if (x === x) Prevention
- Use `Number.isNaN(x)` for NaN checks — never `x !== x`.
- Enable the rule plus `eqeqeq` so comparison typos surface as two distinct signals.
- During copy-paste of comparison lines, change one operand consciously.
When it happens
Trigger: `if (x === x)`, `a !== a` (NaN test), `obj.value === obj.value`; both labels are attached, one per operand span.
Common situations: Hand-rolled NaN checks predating `Number.isNaN`; template/copy-paste comparisons where both sides were meant to differ; refactors that replaced one identifier with the wrong twin.
Related errors
- this expression is assigned to itself
- Setter cannot return a value
- Checking inequality with NaN will always return true
- Checking equality with NaN will always return false
- Comparison with NaN will always return false
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/5f522c9a2bba228a.
Report an issue: GitHub.