Skip to content

Prevent bugs caused by elements with zero counts in the set. - #1

Open
Arnavion wants to merge 1 commit into
ISibboI:masterfrom
Arnavion:modern-nonzero
Open

Prevent bugs caused by elements with zero counts in the set.#1
Arnavion wants to merge 1 commit into
ISibboI:masterfrom
Arnavion:modern-nonzero

Conversation

@Arnavion

@Arnavion Arnavion commented Nov 17, 2025

Copy link
Copy Markdown

Since the map should never store elements with a count of 0, it is better to store the count as NonZero<usize> instead of usize. This also allows the Iter impl to become smaller and simpler.

More importantly, before this change, it was possible to insert an element into the set with a count of zero using insert_times(val, 0), which would've produced misbehavior such as contains(&val) returning true. The use of NonZero makes this bug pop out and less likely to be reintroduced in the future. Now insert_times(val, 0) is correctly treated as a no-op.

Another source of an element with a count of zero was doing insert_times(val, usize::MAX); insert_times(val, 1); with overflow checks disabled, as they are by default in release mode. Now insert_times() checks for overflow of the inserted element count as well as the size of the whole set.

There is a user-visible change in the signature of distinct_elements in that it now surfaces NonZero<usize> instead of usize. Other API are unchanged.

This change also fixes a couple of clippy lints about elided '_ lifetimes, and missing edition key in the crate manifest.


Also sent to multiset

Since the map should never store elements with a count of 0, it is better to
store the count as `NonZero<usize>` instead of `usize`. This also allows
the `Iter` impl to become smaller and simpler.

More importantly, before this change, it was possible to insert an element
into the set with a count of zero using `insert_times(val, 0)`,
which would've produced misbehavior such as `contains(&val)` returning `true`.
The use of `NonZero` makes this bug pop out and less likely to be reintroduced
in the future. Now `insert_times(val, 0)` is correctly treated as a no-op.

Another source of an element with a count of zero was doing
`insert_times(val, usize::MAX); insert_times(val, 1);` with overflow checks
disabled, as they are by default in release mode. Now `insert_times()` checks
for overflow of the inserted element count as well as the size of
the whole set.

There is a user-visible change in the signature of `distinct_elements`
in that it now surfaces `NonZero<usize>` instead of `usize`. Other API are
unchanged.

This change also fixes a couple of clippy lints about elided `'_` lifetimes,
and missing `edition` key in the crate manifest.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant