{"record":{"id":"5f522c9a2bba228a","repo":"oxc-project/oxc","slug":"both-sides-of-this-comparison-are-exactly-the-same","errorCode":null,"errorMessage":"Both sides of this comparison are exactly the same","messagePattern":"Both sides of this comparison are exactly the same","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/no_self_compare.rs","lineNumber":9,"sourceCode":"use oxc_ast::AstKind;\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{ContentEq, GetSpan, Span};\n\nuse crate::{AstNode, context::LintContext, rule::Rule};\n\nfn no_self_compare_diagnostic(left_span: Span, right_span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Both sides of this comparison are exactly the same\")\n        .with_help(\"If you are testing for NaN, you can use the `Number.isNaN()` function.\")\n        .with_labels([left_span, right_span])\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoSelfCompare;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallow comparisons where both sides are exactly the same.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// Comparing a variable against itself is usually an error, either a typo or refactoring error.\n    /// It is confusing to the reader and may potentially introduce a runtime error.\n    ///\n    /// ### Examples","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_self_compare.rs#L1-L27","documentation":"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.","triggerScenarios":"`if (x === x)`, `a !== a` (NaN test), `obj.value === obj.value`; both labels are attached, one per operand span.","commonSituations":"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.","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."],"exampleFix":"// before\nif (value === value) { /* skip NaN */ }\n\n// after\nif (!Number.isNaN(value)) { /* skip NaN */ }","handlingStrategy":"type-guard","validationCode":"// Reject self-comparisons before they ship (simple identifier form)\nfunction hasSelfCompare(src) {\n  return /([A-Za-z_$][\\w$.]*)\\s*(?:===|!==|==|!=)\\s*\\1(?![\\w$])/.test(src);\n}","typeGuard":"// Correct way to express the intent this rule guesses at:\nfunction isNotNaN(value) {\n  return typeof value === 'number' && !Number.isNaN(value);\n}\n// use: if (isNotNaN(x)) { ... } instead of if (x === x)","tryCatchPattern":null,"preventionTips":["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."],"tags":["lint","eslint","no-self-compare","comparisons","nan","possible-bug"],"backgroundTag":"self-comparison-nan-check","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}