Skip to content

Forbid comparing iter.count() with zero #15716

@TomFryersMidsummer

Description

@TomFryersMidsummer

What it does

This suggests replacing iter.count() > 0 (or >= 1 or != 0) with iter.next().is_some() and iter.count() == 0 (or < 1) with iter.next().is_none().

This could go in perf.

Advantage

This avoids potentially having to run through the whole iterator, if the optimiser can't see through it. In at least one case, it can't.

Along with filter_next and search_is_some, this completes a path that can transform one of the obvious naïve ways to write Iterator::any into the genuine article.

xs.filter(|&x| x == 3).count() > 0

xs.filter(|&x| x == 3).next().is_some()

→ (filter_next)

xs.find(|&x| x == 3).is_some()

→ (search_is_some)

xs.any(|x| x == 3)

The overall benefit here looks significant.

Drawbacks

If running through the iterator has side effects, then the behaviour will change.

The resulting code is five characters longer, and requires the underlying variable to be mutable.

Example

fn empty<T>(xs: impl Iterator<Item = T>) -> bool {
    xs.count() == 0
}

Could be written as:

fn empty<T>(mut xs: impl Iterator<Item = T>) -> bool {
    xs.next().is_none()
}

Comparison with existing lints

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: New lints

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions