Skip to content

Commit

Permalink
pin rust, add justfile, update lints (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
rinde authored Oct 9, 2024
1 parent 5d41f9f commit 5825433
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 71 deletions.
27 changes: 21 additions & 6 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,39 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@v2
with:
tool: just
- run: echo "RUST_TOOLCHAIN=$(just rust-version)" >> $GITHUB_ENV
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
- uses: Swatinem/rust-cache@v2
with:
shared-key: debug-build
- name: Test
run: cargo test --workspace
run: just test

lint:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@v2
with:
tool: just
- run: |
echo "RUST_TOOLCHAIN=$(just rust-version)" >> $GITHUB_ENV
echo "RUST_TOOLCHAIN_NIGHTLY=$(just rust-nightly-version)" >> $GITHUB_ENV
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }}
components: rustfmt
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
with:
shared-key: debug-build
- name: Lint
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
- name: Check formatting
run: cargo fmt --all --check
run: just lint "strict"
74 changes: 35 additions & 39 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,44 @@ keywords = ["bitset", "stack", "small", "data-structure"]
num-traits = "0.2.17"

[lints.rust]
macro_use_extern_crate = "warn"
meta_variable_misuse = "warn"
missing_copy_implementations = "warn"
missing_debug_implementations = "warn"
missing_docs = "warn"
unused_crate_dependencies = "warn"
redundant_lifetimes = "deny"
single_use_lifetimes = "deny"
unreachable_pub = "deny"
unnameable_types = "deny"
unsafe_code = "deny"
unstable_features = "deny"
unused_crate_dependencies = "deny"
unused_extern_crates = "warn"
unused_import_braces = "warn"
unused_lifetimes = "warn"
unused_macro_rules = "warn"
unused_results = "warn"
unused_tuple_struct_fields = "warn"
unused_qualifications = "warn"
unused_results = "deny"
dead_code = "warn"
unused = { level = "warn", priority = -1 }
missing_docs = "deny"
refining_impl_trait = { level = "warn", priority = -1 }

[lints.rustdoc]
broken_intra_doc_links = "deny"
private_intra_doc_links = "allow"

[lints.clippy]
correctness = "deny"
suspicious = "deny"
complexity = "warn"
perf = "warn"
style = "warn"
cargo = "warn"
# selected lints from the `pedantic` group
cast_lossless = "warn"
cast_possible_truncation = "warn"
cast_possible_wrap = "warn"
checked_conversions = "warn"
cloned_instead_of_copied = "warn"
copy_iterator = "warn"
doc_link_with_quotes = "warn"
doc_markdown = "warn"
explicit_into_iter_loop = "warn"
explicit_iter_loop = "warn"
filter_map_next = "warn"
flat_map_option = "warn"
iter_not_returning_iterator = "warn"
manual_assert = "warn"
manual_instant_elapsed = "warn"
manual_let_else = "warn"
manual_ok_or = "warn"
map_unwrap_or = "warn"
match_bool = "warn"
match_same_arms = "warn"
missing_errors_doc = "warn"
missing_fields_in_debug = "warn"
missing_panics_doc = "warn"
module_name_repetitions = "warn"
range_minus_one = "warn"
range_plus_one = "warn"
redundant_else = "warn"
semicolon_if_nothing_returned = "warn"
complexity = { level = "warn", priority = -1 }
correctness = { level = "deny", priority = -1 }
perf = { level = "warn", priority = -1 }
style = { level = "warn", priority = -1 }
suspicious = { level = "deny", priority = -1 }
todo = "warn"

disallowed-types = "deny"
missing_const_for_fn = "warn"

allow_attributes = "deny"
allow_attributes_without_reason = "deny"

pedantic = { level = "warn", priority = -1 } # setting a lower priority for the group to allow individual overrides
41 changes: 41 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Fail on early and on unset variables in non-shebang recipes
set shell := ["bash", "-euo", "pipefail", "-c"]
# Allow usage of bash methods to handle multiple arguments and work around quoting issues
set positional-arguments
set quiet

@default: fmt lint test

rust_version := `sed -nr 's/channel = "(.*)"/\1/p' rust-toolchain.toml`
rust_nightly_version := `sed -nr 's/channel = "(.*)"/\1/p' rust-toolchain-nightly.toml`

rust-version:
echo '{{rust_version}}'

rust-nightly-version:
echo '{{rust_nightly_version}}'

test:
cargo test --workspace --all-targets --all-features
cargo test --workspace --doc

lint strict="":
cargo '+{{rust_nightly_version}}' fmt -- --check
cargo clippy \
--workspace \
--tests \
--benches \
--all-targets \
--all-features \
--quiet \
-- {{ if strict != "" { "-D warnings" } else { "" } }}
cargo doc --all --no-deps --document-private-items --all-features --quiet

fmt:
cargo '+{{rust_nightly_version}}' fmt

udeps:
cargo '+{{rust_nightly_version}}' udeps

install-nightly:
rustup toolchain install '{{rust_nightly_version}}'
2 changes: 2 additions & 0 deletions rust-toolchain-nightly.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "nightly-2024-09-06"
2 changes: 2 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "1.81.0"
7 changes: 7 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
imports_granularity = "Item"
wrap_comments = true
format_code_in_doc_comments = true
normalize_comments = true
normalize_doc_attributes = true
group_imports = "StdExternalCrate"
use_field_init_shorthand = true
2 changes: 1 addition & 1 deletion src/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct IntoIter<T: BitBlock, const N: usize> {
}

impl<T: BitBlock, const N: usize> IntoIter<T, N> {
pub(crate) fn new(blocks: [T; N]) -> Self {
pub(crate) const fn new(blocks: [T; N]) -> Self {
Self {
blocks,
index_front: 0,
Expand Down
53 changes: 28 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
//! known beforehand. The [`TinyBitSet`] is copyable and the implementation
//! assumes in many places that the data is small enough to cheaply be copied.
//! Thus it is mostly suitable for sizes of up to 256 bits. For larger sizes, a
//! heap-allocated crate like [`fixedbitset`][fixedbitset] is likely a better fit.
//! heap-allocated crate like [`fixedbitset`][fixedbitset] is likely a better
//! fit.
//!
//! One unique feature of this crate is that it uses const generics to have a
//! single generic bitset type whose size and underlying storage type can be
Expand Down Expand Up @@ -41,9 +42,8 @@ use std::ops::BitXorAssign;
use std::ops::Index;
use std::ops::Not;

use num_traits::PrimInt;

pub use iterators::IntoIter;
use num_traits::PrimInt;

/// Integer that can be used as a block of bits in a bitset.
pub trait BitBlock:
Expand Down Expand Up @@ -122,6 +122,7 @@ impl<T: BitBlock, const N: usize> TinyBitSet<T, N> {
/// Creates an empty bitset.
///
/// Equivalent to [`Self::EMPTY`].
#[must_use]
pub const fn new() -> Self {
Self::EMPTY
}
Expand All @@ -131,6 +132,7 @@ impl<T: BitBlock, const N: usize> TinyBitSet<T, N> {
/// # Panics
///
/// Panics if `bit >= Self::CAPACITY`.
#[must_use]
pub fn singleton(bit: usize) -> Self {
Self::new().inserted(bit)
}
Expand All @@ -156,7 +158,7 @@ impl<T: BitBlock, const N: usize> TinyBitSet<T, N> {
}

/// Iterates over the indices of set bits from lowest to highest.
pub fn iter(self) -> IntoIter<T, N> {
pub const fn iter(self) -> IntoIter<T, N> {
IntoIter::new(self.blocks)
}

Expand Down Expand Up @@ -371,7 +373,8 @@ impl<T: BitBlock, const N: usize> BitOrAssign for TinyBitSet<T, N> {
impl<T: BitBlock, const N: usize> BitXor for TinyBitSet<T, N> {
type Output = Self;

/// Returns a bitset with all bits that are set in exactly one of `self` and `rhs`.
/// Returns a bitset with all bits that are set in exactly one of `self` and
/// `rhs`.
fn bitxor(self, rhs: Self) -> Self::Output {
array::from_fn(|i| self.blocks[i] ^ rhs.blocks[i]).into()
}
Expand Down Expand Up @@ -504,7 +507,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn singleton_out_of_range() {
let _ = TestBitSet::singleton(16);
}
Expand Down Expand Up @@ -548,7 +551,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn insert_out_of_range() {
TestBitSet::new().insert(16);
}
Expand All @@ -562,7 +565,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn inserted_out_of_range() {
let _ = TestBitSet::new().inserted(16);
}
Expand All @@ -579,7 +582,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn remove_out_of_range() {
TestBitSet::new().remove(16);
}
Expand All @@ -594,7 +597,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn removed_out_of_range() {
let _ = TestBitSet::new().removed(16);
}
Expand All @@ -611,7 +614,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn toggle_out_of_range() {
TestBitSet::new().toggle(16);
}
Expand All @@ -625,7 +628,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn toggled_out_of_range() {
let _ = TestBitSet::new().toggled(16);
}
Expand All @@ -644,7 +647,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn assign_out_of_range() {
TestBitSet::new().assign(16, true);
}
Expand All @@ -659,7 +662,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn assigned_out_of_range() {
let _ = TestBitSet::new().assigned(16, true);
}
Expand Down Expand Up @@ -733,8 +736,8 @@ mod tests {
assert_eq!(TestBitSet::ALL, !TestBitSet::EMPTY);
assert_eq!(TestBitSet::EMPTY, !TestBitSet::ALL);
assert_eq!(
TestBitSet::from([0b00111100, 0b10101010]),
!TestBitSet::from([0b11000011, 0b01010101])
TestBitSet::from([0b0011_1100, 0b1010_1010]),
!TestBitSet::from([0b1100_0011, 0b0101_0101])
);
}

Expand All @@ -752,9 +755,9 @@ mod tests {
test(TestBitSet::ALL, TestBitSet::ALL, TestBitSet::ALL);

test(
TestBitSet::from([0b11100111, 0b01010101]),
TestBitSet::from([0b00111100, 0b10101010]),
TestBitSet::from([0b00100100, 0b00000000]),
TestBitSet::from([0b1110_0111, 0b0101_0101]),
TestBitSet::from([0b0011_1100, 0b1010_1010]),
TestBitSet::from([0b0010_0100, 0b0000_0000]),
);
}

Expand All @@ -772,9 +775,9 @@ mod tests {
test(TestBitSet::ALL, TestBitSet::ALL, TestBitSet::ALL);

test(
TestBitSet::from([0b01100110, 0b01010101]),
TestBitSet::from([0b00111100, 0b10101010]),
TestBitSet::from([0b01111110, 0b11111111]),
TestBitSet::from([0b0110_0110, 0b0101_0101]),
TestBitSet::from([0b0011_1100, 0b1010_1010]),
TestBitSet::from([0b0111_1110, 0b1111_1111]),
);
}

Expand All @@ -792,9 +795,9 @@ mod tests {
test(TestBitSet::ALL, TestBitSet::ALL, TestBitSet::EMPTY);

test(
TestBitSet::from([0b01100110, 0b01010101]),
TestBitSet::from([0b00111100, 0b10101010]),
TestBitSet::from([0b01011010, 0b11111111]),
TestBitSet::from([0b0110_0110, 0b0101_0101]),
TestBitSet::from([0b0011_1100, 0b1010_1010]),
TestBitSet::from([0b0101_1010, 0b1111_1111]),
);
}

Expand Down

0 comments on commit 5825433

Please sign in to comment.