rust-lang/rust-clippy

Lint assertions on collection emptiness checks

Open

#17.114 aberto em 30 de mai. de 2026

Ver no GitHub
 (2 comments) (0 reactions) (0 assignees)Rust (1.391 forks)batch import
A-lintgood first issue

Métricas do repositório

Stars
 (10.406 stars)
Métricas de merge de PR
 (Mesclagem média 16d 6h) (79 fundiu PRs em 30d)

Description

What it does

Detects assertions that only check whether a collection is empty or non-empty.

assert!(items.is_empty());
assert!(!items.is_empty());

Could be written as:

assert_eq!(items, []);
assert_ne!(items, []);

Advantage

assert!(collection.is_empty()) and assert!(!collection.is_empty()) produce low-information failures: they tell the user that the condition was false, but not what the collection actually contained.

The user usually has to reproduce locally, add temporary logging, or reshape the test so that it exposes the values in the collection. Each option is time-consuming and requires investigating the test away from where the failure may have been surfaced, such as CI. When the failure output already contains the unexpected collection, the path from CI failure to fix is often minutes faster because the developer can reason from the original failure instead of running another investigation cycle.

This is especially common before a deeper assertion about the collection contents:

assert!(!items.is_empty());
assert_eq!(items[0], "bar");

When this fails at the emptiness check, the following assertion never runs, so the failure can hide the nearby assertion that would have exposed more useful context. That chained pattern may be the most important case for the lint to catch, but bare emptiness assertions have the same diagnostic problem.

Using equality assertions against an empty collection gives the assertion machinery a value to print, making the failure easier to diagnose.

Drawbacks

This overlaps with Clippy’s existing preference for .is_empty() in non-assertion contexts. In particular, clippy::len_zero suggests .is_empty() instead of length comparisons, and clippy::comparison_to_empty suggests .is_empty() instead of comparing to an empty slice or string.

The distinction here is assertion diagnostics: inside assert!, the concise boolean check hides the actual value on failure.

The lint may need to be conservative about suggestions where the right empty value is not obvious or would require type annotations.

Example

assert!(items.is_empty());
assert!(!items.is_empty());

Could be written as:

assert_eq!(items, []);
assert_ne!(items, []);

Comparison with existing lints

clippy::len_zero and clippy::comparison_to_empty prefer .is_empty() for ordinary boolean checks. This lint would be limited to assertion contexts, where comparing against an empty value can produce better failure output.

clippy::manual_assert_eq has a similar diagnostic motivation for assertions written as equality checks, but it does not cover .is_empty().

clippy::bool_assert_comparison may currently rewrite boolean equality assertions toward assert!(items.is_empty()); this lint would address the assertion-diagnostic problem that remains after that rewrite.

Additional Context

This comes up in practice when debugging tests. I have spent many hours over the years, across Rust and other languages such as C# and Java, chasing failures from assertions like is_empty() or len() == 0. These failures often happen in CI or another remote service, where the immediate failure output does not include the values needed to understand the problem.

Longer term, it may be worth exploring an RFC for making emptiness traitable/assertable in the Rust standard library. If Rust had a standard trait for emptiness, an assert_empty! / assert_not_empty! macro could be a better target than assert_eq!(foo, []). That broader API question is separate from this lint; in current Rust, assert_eq! / assert_ne! against an empty value are the standard assertion forms that can show the actual value on failure.

This is probably not a restriction lint, since it is not trying to ban .is_empty() generally. The main question is whether the test-diagnostic benefit is strong enough for a default lint category, or whether this should start as pedantic or nursery.

Guia do colaborador