Meaningless Size Comparison

ID

swift.meaningless_size_comparison

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Swift

Tags

collection, reliability, suspicious-comparison

Description

Reports a collection count compared against a bound the count can never cross, so the comparison is a constant. count on any Collection — an array, a dictionary, a set, a string — is never negative, which makes >= 0 and > -1 always true, and < 0 and ⇐ -1 always false.

Both operand orders are recognised, so 0 ⇐ items.count is reported too. Only the bounds 0 and -1 are considered; every other bound states a real condition and is left alone.

Rationale

if items.count >= 0 {          // always taken — the guard protects nothing
    process(items)
}

if items.count < 0 {           // never taken — the branch is dead
    reportCorruption()
}

A comparison that cannot change its answer either guards nothing at all or, far more often, was meant to be an emptiness check and now lets every input through. Both readings are defects: the first leaves a guard that reads as meaningful and is not, the second silently disables a branch that a reader — and a reviewer — will assume runs.

The count’s declaring type is not resolved: a member named count is trusted to be a collection size. A bare identifier named count is deliberately not matched, because a plain Int counter really can go negative and count >= 0 on one is a legitimate test. Only a member access (items.count, page.rows.count) qualifies. An arithmetic operand such as offset + items.count >= 0 is likewise not reported — the sum can be negative.

Remediation

Decide what the test was meant to say. An emptiness check is spelled isEmpty; a real threshold uses a bound the count can actually cross; a guard that turns out to protect nothing should be deleted along with the branch it wrapped.

if !items.isEmpty {            // the emptiness check the constant was standing in for
    process(items)
}

if items.count >= maxBatch {   // a bound the count can cross
    flush()
}

The emptiness shapes against zero — count == 0, count != 0, count > 0, count ⇐ 0 — are reported separately by swift.avoid_comparing_count_zero, which advises isEmpty; that rule leaves the four constant combinations to this one, because isEmpty is not the remediation for a comparison whose answer is already fixed.

© 2026 Xygeni. All rights reserved