Given fixed inputs, all items (should) fall into one of three categories:
- Output is non-deterministic, thus never reproducible
- Output is deterministic, but not considered portable
- Output is deterministic and portable
In general, functionality is considered deterministic and portable unless
it is clearly non-deterministic (e.g.
ThreadRng) or it is
documented as being unportable (e.g.
We try to follow semver rules regarding
API-breaking changes and
- New patch versions should not include API-breaking changes or major new features
- Before 1.0, minor versions may include API breaking changes. After 1.0 they should not.
Additionally, we must also consider value-breaking changes and portability. When given fixed inputs,
- For non-deterministic items, implementations may change in any release
- For deterministic unportable items, output should be preserved in patch releases, but may change in any minor release (including after 1.0)
- For portable items, any change of output across versions is considered equivalent to an API breaking change.
Portability of usize
There is unfortunately one non-portable item baked into the heart of the Rust
isize). For example, the size of an empty
Vec will differ on 32-bit and 64-bit targets. For most purposes this is not an
issue, but when it comes to generating random numbers in a portable manner
it does matter.
A simple rule follows: if portability is required, never sample a
isize value directly.
Within Rand we adhere to this rule whenever possible. All sequence-releated
code requiring a bounded
usize value will sample a
u32 value unless the
upper bound exceeds
(Note that this actually improves benchmark performance in many cases.)