commit 4731e52ae651bf5404fe0f24597f763de7664ed5
parent 177519dba61a589d3970c1ccdb4dfd0d2a79ad3f
Author: Zack Newman <zack@philomathiclife.com>
Date: Fri, 6 Sep 2024 10:16:08 -0600
update deps. address lints
Diffstat:
M | Cargo.toml | | | 33 | +++++++++++++-------------------- |
M | README.md | | | 34 | +++++++++++++++++++++++----------- |
D | build.rs | | | 12 | ------------ |
M | src/lib.rs | | | 128 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
4 files changed, 114 insertions(+), 93 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
authors = ["Zack Newman <zack@philomathiclife.com>"]
categories = ["mathematics", "no-std"]
-description = "Trait that represents a set according to Zermelo–Fraenkel set theory with the axiom of choice (ZFC)"
+description = "Trait that represents a set according to Zermelo–Fraenkel set theory with the axiom of choice (ZFC)."
documentation = "https://docs.rs/zfc/latest/zfc/"
edition = "2021"
keywords = ["math", "set", "zfc"]
@@ -9,29 +9,22 @@ license = "MIT OR Apache-2.0"
name = "zfc"
readme = "README.md"
repository = "https://git.philomathiclife.com/repos/zfc/"
-version = "0.3.2"
+rust-version = "1.81.0"
+version = "0.4.0"
-[lib]
-name = "zfc"
-path = "src/lib.rs"
-
-[build-dependencies]
-rustc_version = "0.4.0"
-
-[features]
-std = []
-
-[dependencies]
-num-bigint = { version = "0.4.4", default-features = false }
+[badges]
+maintenance = { status = "actively-developed" }
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
-[badges]
-maintenance = { status = "actively-developed" }
+[dependencies]
+num-bigint = { version = "0.4.6", default-features = false }
-[profile.release]
-lto = true
-panic = 'abort'
-strip = true
+
+### FEATURES #################################################################
+
+[features]
+# Provide Set implementation for HashSet.
+std = []
diff --git a/README.md b/README.md
@@ -1,11 +1,23 @@
-# `zfc`
-
-`zfc` is a library for sets according to [Zermelo–Fraenkel set theory with the axiom of choice (ZFC)](https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory).
-
-## Status
-
-This package will be actively maintained until it is deemed “feature complete”.
-
-The crates are only tested on the `x86_64-unknown-linux-gnu` and `x86_64-unknown-openbsd` targets, but
-they should work on any [Tier 1 with Host Tools](https://doc.rust-lang.org/beta/rustc/platform-support.html)
-target.
+# `zfc`
+
+`zfc` is a library for sets according to
+[Zermelo–Fraenkel set theory with the axiom of choice (ZFC)](https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory).
+
+## License
+
+Licensed under either of
+
+* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0).
+* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT).
+
+at your option.
+
+## Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you,
+as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
+
+### Status
+
+The crate is only tested on `x86_64-unknown-linux-gnu` and `x86_64-unknown-openbsd` targets, but it should work
+on most platforms.
diff --git a/build.rs b/build.rs
@@ -1,12 +0,0 @@
-use rustc_version::{version_meta, Channel};
-
-fn main() {
- // Set cfg flags depending on release channel
- let channel = match version_meta().unwrap().channel {
- Channel::Stable => "CHANNEL_STABLE",
- Channel::Beta => "CHANNEL_BETA",
- Channel::Nightly => "CHANNEL_NIGHTLY",
- Channel::Dev => "CHANNEL_DEV",
- };
- println!("cargo:rustc-cfg={}", channel)
-}
diff --git a/src/lib.rs b/src/lib.rs
@@ -1,13 +1,16 @@
//! # `zfc`
//!
-//! `zfc` is a library for sets according to [Zermelo–Fraenkel set theory with the axiom of choice (ZFC)](https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory).
-#![cfg_attr(all(doc, CHANNEL_NIGHTLY), feature(doc_auto_cfg))]
+//! `zfc` is a library for sets according to
+//! [Zermelo–Fraenkel set theory with the axiom of choice (ZFC)](https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory).
+#![cfg_attr(docsrs, feature(doc_cfg))]
#![no_std]
#![deny(
+ unknown_lints,
future_incompatible,
let_underscore,
missing_docs,
nonstandard_style,
+ refining_impl_trait,
rust_2018_compatibility,
rust_2018_idioms,
rust_2021_compatibility,
@@ -26,25 +29,28 @@
clippy::style,
clippy::suspicious
)]
-#![allow(
- clippy::arithmetic_side_effects,
+#![expect(
clippy::blanket_clippy_restriction_lints,
+ clippy::exhaustive_enums,
clippy::exhaustive_structs,
clippy::implicit_return,
+ clippy::min_ident_chars,
clippy::missing_trait_methods,
clippy::ref_patterns,
- clippy::single_char_lifetime_names
+ clippy::single_char_lifetime_names,
+ reason = "noisy, opinionated, and likely doesn't prevent bugs or improve APIs"
)]
extern crate alloc;
-use alloc::collections::BTreeSet;
+use alloc::{collections::BTreeSet, vec::Vec};
use core::borrow::Borrow;
use core::cmp::Ordering;
+use core::error::Error;
use core::fmt::{self, Display, Formatter};
use core::ops::{Range, RangeInclusive, Sub};
+pub use num_bigint;
use num_bigint::BigUint;
/// Represents the quantity of elements in a [`Set`].
#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
-#[allow(clippy::exhaustive_enums)]
pub enum Cardinality {
/// The contained `BigUint` represents the quantity of elements in a finite `Set`.
Finite(BigUint),
@@ -145,7 +151,6 @@ impl Cardinality {
}
}
impl Display for Cardinality {
- #[allow(clippy::min_ident_chars)]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
@@ -155,7 +160,6 @@ impl Display for Cardinality {
}
}
impl fmt::Debug for Cardinality {
- #[allow(clippy::min_ident_chars)]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
<Self as Display>::fmt(self, f)
@@ -291,34 +295,29 @@ impl PartialOrd<BigUint> for Cardinality {
Some(self.cmp_biguint(other))
}
}
-/// Error returned when attempting to create a
-/// [`BoundedCardinality`] from a pair of [`BigUint`]s
-/// or [`Cardinality`]s such that the upper bound
-/// is strictly less than the lower bound.
+/// Error returned when attempting to create a [`BoundedCardinality`] from a pair of [`BigUint`]s
+/// or [`Cardinality`]s such that the upper bound is strictly less than the lower bound.
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BoundedErr;
impl Display for BoundedErr {
- #[allow(clippy::min_ident_chars)]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("upper bound is greater than lower bound")
}
}
-/// Error returned when attempting to create a
-/// [`Cardinality`] from a [`BoundedCardinality`] such that
+impl Error for BoundedErr {}
+/// Error returned when attempting to create a [`Cardinality`] from a [`BoundedCardinality`] such that
/// the lower bound is less than the upper bound.
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct CardinalityErr;
impl Display for CardinalityErr {
- #[allow(clippy::min_ident_chars)]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("lower bound of the BoundedCardinality is less than the upper bound")
}
}
-/// Contains a lower and upper bound
-/// [`Cardinality`] used to bound the cardinality
-/// of a [`Set`].
+impl Error for CardinalityErr {}
+/// Contains a lower and upper bound [`Cardinality`] used to bound the cardinality of a [`Set`].
#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BoundedCardinality {
/// Lower bound.
@@ -328,6 +327,7 @@ pub struct BoundedCardinality {
}
impl BoundedCardinality {
/// Creates an instance of `BoundedCardinality`.
+ ///
/// Returns `None` iff `lower > upper`.
#[inline]
#[must_use]
@@ -338,8 +338,7 @@ impl BoundedCardinality {
Some(Self { lower, upper })
}
}
- /// Creates an instance of `BoundedCardinality` with the lower and upper bounds
- /// both set to `exact`.
+ /// Creates an instance of `BoundedCardinality` with the lower and upper bounds both set to `exact`.
#[inline]
#[must_use]
pub fn new_exact(exact: Cardinality) -> Self {
@@ -348,9 +347,9 @@ impl BoundedCardinality {
upper: exact,
}
}
- /// Creates an instance of `BoundedCardinality`
- /// with the lower and upper bounds as `Cardinality::Finite`
+ /// Creates an instance of `BoundedCardinality` with the lower and upper bounds as `Cardinality::Finite`
/// of their respective values.
+ ///
/// Returns `None` iff `lower > upper`.
#[inline]
#[must_use]
@@ -364,8 +363,7 @@ impl BoundedCardinality {
})
}
}
- /// Creates an instance of `BoundedCardinality`
- /// with the lower and upper bounds as `Cardinality::Finite(exact)`.
+ /// Creates an instance of `BoundedCardinality` with the lower and upper bounds as `Cardinality::Finite(exact)`.
#[inline]
#[must_use]
pub fn from_biguint_exact(exact: BigUint) -> Self {
@@ -374,26 +372,30 @@ impl BoundedCardinality {
upper: Cardinality::Finite(exact),
}
}
- /// Creates an instance of `BoundedCardinality`
- /// without verifying `lower <= upper`.
+ /// Creates an instance of `BoundedCardinality` without verifying `lower <= upper`.
///
/// # Safety
///
/// `lower <= upper`.
- #[allow(unsafe_code)]
+ #[expect(
+ unsafe_code,
+ reason = "when literal values are used, code can reasonably bypass checks"
+ )]
#[inline]
#[must_use]
pub const unsafe fn new_unsafe(lower: Cardinality, upper: Cardinality) -> Self {
Self { lower, upper }
}
- /// Creates an instance of `BoundedCardinality`
- /// with the lower and upper bounds as `Cardinality::Finite`
+ /// Creates an instance of `BoundedCardinality` with the lower and upper bounds as `Cardinality::Finite`
/// of their respective values without verifying `lower <= upper`.
///
/// # Safety
///
/// `lower <= upper`.
- #[allow(unsafe_code)]
+ #[expect(
+ unsafe_code,
+ reason = "when literal values are used, code can reasonably bypass checks"
+ )]
#[inline]
#[must_use]
pub const unsafe fn from_biguint_unsafe(lower: BigUint, upper: BigUint) -> Self {
@@ -464,14 +466,12 @@ impl BoundedCardinality {
}
}
impl Display for BoundedCardinality {
- #[allow(clippy::min_ident_chars)]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.lower, self.upper)
}
}
impl fmt::Debug for BoundedCardinality {
- #[allow(clippy::min_ident_chars)]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
<Self as Display>::fmt(self, f)
@@ -518,11 +518,15 @@ impl From<BoundedCardinality> for (BigUint, BigUint) {
(value.lower.into(), value.upper.into())
}
}
-/// Represents a set according to [Zermelo–Fraenkel set theory with the axiom of choice (ZFC)](https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory).
-/// Note that elements in a `Set` must not be distinguishable by order or frequency, so care must be taken in its implementation if the implementing type
-/// exposes an API that distinguishes between the order or frequency of `Elem` (e.g., [`Vec<T>`](https://doc.rust-lang.org/alloc/vec/struct.Vec.html) where `Elem` = `T`).
+/// Represents a set according to
+/// [Zermelo–Fraenkel set theory with the axiom of choice (ZFC)](https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory).
+///
+/// Note that elements in a `Set` must not be distinguishable by order or frequency, so care must be taken in its
+/// implementation if the implementing type exposes an API that distinguishes between the order or frequency of
+/// `Elem` (e.g., [`Vec<T>`](https://doc.rust-lang.org/alloc/vec/struct.Vec.html) where `Elem` = `T`).
pub trait Set {
/// The elements that make up the set.
+ ///
/// Per ZFC, this must not be the same type as `Self` nor a recursive type based on `Self`.
type Elem: Eq + ?Sized;
/// Returns the cardinality of `self` if it is known exactly.
@@ -687,13 +691,29 @@ where
for<'a, 'b> <&'a T as Sub<&'b T>>::Output: Into<BigUint>,
{
type Elem = T;
+ #[expect(
+ clippy::arithmetic_side_effects,
+ reason = "we need to calculate the cardinality, and we avoid underflow"
+ )]
#[inline]
fn cardinality(&self) -> Option<Cardinality> {
- Some(Cardinality::Finite((&self.end - &self.start).into()))
+ Some(Cardinality::Finite(if self.end >= self.start {
+ (&self.end - &self.start).into()
+ } else {
+ BigUint::new(Vec::new())
+ }))
}
+ #[expect(
+ clippy::arithmetic_side_effects,
+ reason = "we need to calculate the cardinality, and we avoid underflow"
+ )]
#[inline]
fn bounded_cardinality(&self) -> BoundedCardinality {
- let card = Cardinality::Finite((&self.end - &self.start).into());
+ let card = Cardinality::Finite(if self.end >= self.start {
+ (&self.end - &self.start).into()
+ } else {
+ BigUint::new(Vec::new())
+ });
BoundedCardinality {
lower: card.clone(),
upper: card,
@@ -726,16 +746,29 @@ where
for<'a, 'b> <&'a T as Sub<&'b T>>::Output: Into<BigUint>,
{
type Elem = T;
+ #[expect(
+ clippy::arithmetic_side_effects,
+ reason = "we need to calculate the cardinality, and we avoid underflow. Overflow is no worry since we use BigUint."
+ )]
#[inline]
fn cardinality(&self) -> Option<Cardinality> {
- Some(Cardinality::Finite(
- (self.end() - self.start()).into() + BigUint::new(alloc::vec![1]),
- ))
+ Some(Cardinality::Finite(if self.end() >= self.start() {
+ (self.end() - self.start()).into() + BigUint::new(alloc::vec![1])
+ } else {
+ BigUint::new(Vec::new())
+ }))
}
+ #[expect(
+ clippy::arithmetic_side_effects,
+ reason = "we need to calculate the cardinality, and we avoid underflow. Overflow is no worry since we use BigUint."
+ )]
#[inline]
fn bounded_cardinality(&self) -> BoundedCardinality {
- let card =
- Cardinality::Finite((self.end() - self.start()).into() + BigUint::new(alloc::vec![1]));
+ let card = Cardinality::Finite(if self.end() >= self.start() {
+ (self.end() - self.start()).into() + BigUint::new(alloc::vec![1])
+ } else {
+ BigUint::new(Vec::new())
+ });
BoundedCardinality {
lower: card.clone(),
upper: card,
@@ -768,8 +801,7 @@ use core::hash::{BuildHasher, Hash};
#[cfg(feature = "std")]
use std::collections::HashSet;
#[cfg(feature = "std")]
-use std::error::Error;
-#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T, S> Set for HashSet<T, S>
where
T: Eq + Hash,
@@ -804,7 +836,3 @@ where
self.len() <= val.len() && self.intersection(val).count() == val.len()
}
}
-#[cfg(feature = "std")]
-impl Error for BoundedErr {}
-#[cfg(feature = "std")]
-impl Error for CardinalityErr {}