rust-lang / rust-lang/rust-clippy

`iter_on_empty_collections` emitted when `iter::empty()` cannot work

Open
#11,680 1 comment 0 reactions 1 assignee View on GitHub

@J-ZhengLi is already working on this.

Since Apr 25, 2024.

C-bug I-false-positive I-suggestion-causes-error L-nursery
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

Summary

The suggestion for iter_on_empty_collections causes an incompatible match arm error in some cases.

Lint Name

iter_on_empty_collections

Reproducer

I am having a hard time finding a minimal reproduction, this seems to work OK in most other cases I try. Probably clippy just having trouble seeing through the mess of iterators. This is a snip from the full example:

use itertools::Either;

impl Source {
    /// Iterate through all morph info available
    pub fn morphs(&self) -> impl Iterator<Item = &MorphInfo> {
        match self {
            Source::Affix(rule) => {
                let iter = rule
                    .patterns()
                    .iter()
                    .flat_map(|pat| pat.morph_info().iter());
                Either::Left(iter)
            }
            // v is `&Box<[Arc<MorphInfo>]>`
            Source::Dict(v) => Either::Right(v.as_ref().iter()),
            Source::Personal(v) => Either::Right(v.morph.iter()),
            // problem arm
            Source::Raw => Either::Right([].iter()),
        }
        .map(AsRef::as_ref)
    }
}

I saw this happen:

warning: `iter` call on an empty collection
  --> zspell/src/dict/types.rs:77:42
   |
77 |             Source::Raw => Either::Right([].iter()),
   |                                          ^^^^^^^^^ help: try: `std::iter::empty()`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_empty_collections
note: the lint level is defined here
  --> zspell/src/lib.rs:87:9
   |
87 | #![warn(clippy::nursery)]
   |         ^^^^^^^^^^^^^^^
   = note: `#[warn(clippy::iter_on_empty_collections)]` implied by `#[warn(clippy::nursery)]`

Following the lint gives

error[E0308]: `match` arms have incompatible types
  --> zspell/src/dict/types.rs:77:28
   |
67 | /         match self {
68 | |             Source::Affix(rule) => {
69 | |                 let iter = rule
70 | |                     .patterns()
71 | |                     .iter()
72 | |                     .flat_map(|pat| pat.morph_info().iter());
   | |                               ----- the expected closure
73 | |                 Either::Left(iter)
   | |                 ------------------ this is found to be of type `itertools::Either<std::iter::FlatMap<std::slice::Iter<'_, dict::rule::AfxRulePattern>, std::slice::Iter<'_, std::sync::Arc<morph::MorphInfo>>, [closure@zspell/src/dict/types.rs:72:31: 72:36]>, std::slice::Iter<'_, std::sync::Arc<morph::MorphInfo>>>`
74 | |             }
75 | |             Source::Dict(v) => Either::Right(v.as_ref().iter()),
   | |                                -------------------------------- this is found to be of type `itertools::Either<std::iter::FlatMap<std::slice::Iter<'_, dict::rule::AfxRulePattern>, std::slice::Iter<'_, std::sync::Arc<morph::MorphInfo>>, [closure@zspell/src/dict/types.rs:72:31: 72:36]>, std::slice::Iter<'_, std::sync::Arc<morph::MorphInfo>>>`
76 | |             Source::Personal(v) => Either::Right(v.morph.iter()),
   | |                                    ----------------------------- this is found to be of type `itertools::Either<std::iter::FlatMap<std::slice::Iter<'_, dict::rule::AfxRulePattern>, std::slice::Iter<'_, std::sync::Arc<morph::MorphInfo>>, [closure@zspell/src/dict/types.rs:72:31: 72:36]>, std::slice::Iter<'_, std::sync::Arc<morph::MorphInfo>>>`
77 | |             Source::Raw => Either::Right(std::iter::empty()),
   | |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Either<FlatMap<Iter<'_, ...>, ..., ...>, ...>`, found `Either<_, Empty<_>>`
78 | |         }
   | |_________- `match` arms have incompatible types
   |
   = note: expected enum `itertools::Either<std::iter::FlatMap<std::slice::Iter<'_, dict::rule::AfxRulePattern>, std::slice::Iter<'_, std::sync::Arc<morph::MorphInfo>>, [closure@zspell/src/dict/types.rs:72:31: 72:36]>, std::slice::Iter<'_, std::sync::Arc<morph::MorphInfo>>>`
              found enum `itertools::Either<_, std::iter::Empty<_>>`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `zspell` (lib) due to previous error

I expected to see this happen: no error

Version
rustc 1.74.0-nightly (b4e54c6e3 2023-09-11)
binary: rustc
commit-hash: b4e54c6e39984840a04dcd02d14ec8c3574d30e5
commit-date: 2023-09-11
host: x86_64-unknown-linux-gnu
release: 1.74.0-nightly
LLVM version: 17.0.0
Additional Labels

@rustbot label +I-suggestion-causes-error

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.