rust-lang / rust-lang/rust-clippy
`assert_is_empty` could catch every other collection in `std::collections`
@saberoueslati is already working on this.
Since Sep 17, 2026.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
Summary
Of all the collections in std::collections, assert_is_empty only fires on Vec. Here is how it can fire on every other collection in std::collections.
To make it more obvious which traits are the bare minimum required on a given type, I introduce this trait to allow me to fill collections generically:
trait ElementExists {
const ELEMENT: Self;
}
...and also leave comments explaining which traits are required.
All cases provided will intentionally fail the assertion, since that's the whole point of the lint. The first case in each set will be the case that the lint should fire on, to show the difference in trait bounds (as some collections have innate bounds).
Lint Name
assert_is_empty
Reproducer
In each of these, Clippy should suggest replacing the assert shown in *_normal with the assert shown in *_eq or *_matches if the type(s) in the collection meet the new trait bounds.
BTreeMap
// T: Ord is implied by the requirements of BTreeMap
fn btreemap_normal<T: ElementExists + Ord, U: ElementExists>() {
let mut btreemap = BTreeMap::new();
drop(btreemap.insert(T::ELEMENT, U::ELEMENT));
assert!(btreemap.is_empty());
}
fn btreemap_eq<
T: ElementExists + Ord + Debug, // T now needs Debug
U: ElementExists + PartialEq + Debug, // U now needs PartialEq and Debug
>() {
let mut btreemap = BTreeMap::new();
drop(btreemap.insert(T::ELEMENT, U::ELEMENT));
assert_eq!(btreemap, BTreeMap::new());
}
BTreeSet
// T: Ord is implied by the requirements of BTreeSet
fn btreeset_normal<T: ElementExists + Ord>() {
let mut btreeset = BTreeSet::new();
let _: bool = btreeset.insert(T::ELEMENT);
assert!(btreeset.is_empty());
}
// T now needs Debug
fn btreeset_eq<T: ElementExists + Ord + Debug>() {
let mut btreeset = BTreeSet::new();
let _: bool = btreeset.insert(T::ELEMENT);
assert_eq!(btreeset, BTreeSet::new());
}
BinaryHeap
// T: Ord is implied by the requirements of BinaryHeap
fn binaryheap_normal<T: ElementExists + Ord>() {
let mut binaryheap = BinaryHeap::new();
binaryheap.push(T::ELEMENT);
assert!(binaryheap.is_empty());
}
// T now needs Debug
fn binaryheap_eq<T: ElementExists + Ord + Debug>() {
let mut binaryheap = BinaryHeap::new();
binaryheap.push(T::ELEMENT);
assert_eq!(binaryheap.as_slice(), []);
}
HashMap
// T: Eq + Hash is implied by the requirements of HashMap
fn hashmap_normal<T: ElementExists + Eq + Hash, U: ElementExists>() {
let mut hashmap = HashMap::new();
drop(hashmap.insert(T::ELEMENT, U::ELEMENT));
assert!(hashmap.is_empty());
}
fn hashmap_eq<
T: ElementExists + Eq + Hash + Debug, // T now needs Debug
U: ElementExists + Debug + PartialEq, // U now needs PartialEq and Debug
>() {
let mut hashmap = HashMap::new();
drop(hashmap.insert(T::ELEMENT, U::ELEMENT));
assert_eq!(hashmap, HashMap::new());
}
HashSet
// T: Eq + Hash is implied by the requirements of HashSet
fn hashset_normal<T: ElementExists + Eq + Hash>() {
let mut hashset = HashSet::new();
let _: bool = hashset.insert(T::ELEMENT);
assert!(hashset.is_empty());
}
// T now needs Debug
fn hashset_eq<T: ElementExists + Eq + Hash + Debug>() {
let mut hashset = HashSet::new();
let _: bool = hashset.insert(T::ELEMENT);
assert_eq!(hashset, HashSet::new());
}
LinkedList
fn linkedlist_normal<T: ElementExists>() {
let mut linkedlist = LinkedList::new();
linkedlist.push_front(T::ELEMENT);
assert!(linkedlist.is_empty());
}
// T now needs PartialEq and Debug
fn linkedlist_eq<T: ElementExists + PartialEq + Debug>() {
let mut linkedlist = LinkedList::new();
linkedlist.push_front(T::ELEMENT);
assert_eq!(linkedlist, LinkedList::new());
}
VecDeque
This is the only collection where we can get a more general fix by using assert_matches!, but in case that's undesirable for some reason, the stricter assert_eq! solution is also included.
fn vecdeque_normal<T: ElementExists>() {
let mut vecdeque = VecDeque::new();
vecdeque.push_front(T::ELEMENT);
assert!(vecdeque.is_empty());
}
// T now needs PartialEq and Debug
fn vecdeque_eq<T: ElementExists + Debug + PartialEq>() {
let mut vecdeque = VecDeque::new();
vecdeque.push_front(T::ELEMENT);
assert_eq!(vecdeque, VecDeque::new());
}
// T now needs Debug
fn vecdeque_matches<T: ElementExists + Debug>() {
let mut vecdeque = VecDeque::new();
vecdeque.push_front(T::ELEMENT);
assert_matches!(vecdeque.as_slices(), ([], []));
}
Version
rustc 1.100.0-nightly (fb6531d55 2026-08-23)
binary: rustc
commit-hash: fb6531d550e0075b9eb9a51464f404805eec87d9
commit-date: 2026-08-23
host: x86_64-unknown-linux-gnu
release: 1.100.0-nightly
LLVM version: 23.1.0
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.