calc_rational

CLI calculator for rational numbers.
git clone https://git.philomathiclife.com/repos/calc_rational
Log | Files | Refs | README

commit 084504bed2163a48fb2f08aaa841fa52e451d1e0
parent 14ad9d5c377bd55fe5dbe2f05e1e7832dd29ec64
Author: Zack Newman <zack@philomathiclife.com>
Date:   Mon, 19 May 2025 12:52:14 -0600

handle lints

Diffstat:
MCargo.toml | 51+++++++++++++++++++++++++++++++++++++++++++++------
Msrc/cache.rs | 1+
Msrc/lib.rs | 62+++++++++++---------------------------------------------------
Msrc/main.rs | 35-----------------------------------
4 files changed, 57 insertions(+), 92 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -9,8 +9,8 @@ license = "MIT OR Apache-2.0" name = "calc_rational" readme = "README.md" repository = "https://git.philomathiclife.com/repos/calc_rational/" -rust-version = "1.86.0" -version = "2.2.0" +rust-version = "1.87.0" +version = "2.3.0" [lib] name = "calc_lib" @@ -20,6 +20,47 @@ path = "src/lib.rs" name = "calc" path = "src/main.rs" +[lints.rust] +unknown_lints = { level = "deny", priority = -1 } +future_incompatible = { level = "deny", priority = -1 } +let_underscore = { level = "deny", priority = -1 } +missing_docs = { level = "deny", priority = -1 } +nonstandard_style = { level = "deny", priority = -1 } +refining_impl_trait = { level = "deny", priority = -1 } +rust_2018_compatibility = { level = "deny", priority = -1 } +rust_2018_idioms = { level = "deny", priority = -1 } +rust_2021_compatibility = { level = "deny", priority = -1 } +rust_2024_compatibility = { level = "deny", priority = -1 } +unsafe_code = { level = "deny", priority = -1 } +unused = { level = "deny", priority = -1 } +warnings = { level = "deny", priority = -1 } + +[lints.clippy] +all = { level = "deny", priority = -1 } +cargo = { level = "deny", priority = -1 } +complexity = { level = "deny", priority = -1 } +correctness = { level = "deny", priority = -1 } +nursery = { level = "deny", priority = -1 } +pedantic = { level = "deny", priority = -1 } +perf = { level = "deny", priority = -1 } +restriction = { level = "deny", priority = -1 } +style = { level = "deny", priority = -1 } +suspicious = { level = "deny", priority = -1 } +# Noisy, opinionated, and likely don't prevent bugs or improve APIs. +arbitrary_source_item_ordering = "allow" +blanket_clippy_restriction_lints = "allow" +exhaustive_enums = "allow" +implicit_return = "allow" +min_ident_chars = "allow" +missing_trait_methods = "allow" +pub_use = "allow" +question_mark_used = "allow" +ref_patterns = "allow" +return_and_then = "allow" +single_call_fn = "allow" +single_char_lifetime_names = "allow" +unseparated_literal_suffix = "allow" + [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] @@ -29,10 +70,8 @@ num-bigint = { version = "0.4.6", default-features = false } num-integer = { version = "0.1.46", default-features = false } num-rational = { version = "0.4.2", default-features = false, features = ["num-bigint"] } num-traits = { version = "0.2.19", default-features = false } -rand = { version = "0.9.0", default-features = false, features = ["thread_rng"], optional = true } - -[target.'cfg(target_os = "openbsd")'.dependencies] -priv_sep = { version = "2.2.0", default-features = false, features = ["openbsd"], optional = true } +priv_sep = { version = "3.0.0-alpha.1", default-features = false, optional = true } +rand = { version = "0.9.1", default-features = false, features = ["thread_rng"], optional = true } ### FEATURES ################################################################# diff --git a/src/cache.rs b/src/cache.rs @@ -57,6 +57,7 @@ impl<T> Cache<T, $x> { /// Adds `val` to the cache. In the event `N` values have already been cached, /// the oldest entry is overwritten. #[expect(clippy::arithmetic_side_effects, reason = "must, and overflow is not possible")] + #[expect(clippy::indexing_slicing, reason = "wont panic since next_head is always correct")] #[inline] pub fn push(&mut self, val: T) { if self.len < $x { diff --git a/src/lib.rs b/src/lib.rs @@ -110,53 +110,12 @@ //! //! For a more precise specification of the “calc language”, one can read the //! [calc language specification](https://git.philomathiclife.com/calc_rational/lang.pdf). -#![no_std] -#![cfg_attr(docsrs, feature(doc_cfg))] -#![deny( - unknown_lints, - future_incompatible, - let_underscore, - missing_docs, - nonstandard_style, - refining_impl_trait, - rust_2018_compatibility, - rust_2018_idioms, - rust_2021_compatibility, - rust_2024_compatibility, - unsafe_code, - unused, - warnings, - clippy::all, - clippy::cargo, - clippy::complexity, - clippy::correctness, - clippy::nursery, - clippy::pedantic, - clippy::perf, - clippy::restriction, - clippy::style, - clippy::suspicious -)] #![expect( clippy::arithmetic_side_effects, - reason = "this is a calculator, so this is unavoidable" -)] -#![expect( - clippy::arbitrary_source_item_ordering, - clippy::blanket_clippy_restriction_lints, - clippy::indexing_slicing, - clippy::exhaustive_enums, - clippy::implicit_return, - clippy::min_ident_chars, - clippy::missing_trait_methods, - clippy::pub_use, - clippy::question_mark_used, - clippy::ref_patterns, - clippy::return_and_then, - clippy::single_char_lifetime_names, - clippy::unseparated_literal_suffix, - reason = "noisy, opinionated, and likely doesn't prevent bugs or improve APIs" + reason = "calculator can't realistically avoid this" )] +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] extern crate alloc; use LangErr::{ DivByZero, ExpDivByZero, ExpIsNotIntOrOneHalf, InvalidAbs, InvalidDec, InvalidPar, InvalidQuit, @@ -321,6 +280,7 @@ impl Display for O<'_> { unsafe_code, reason = "manually construct guaranteed UTF-8; thus avoid the needless check" )] + #[expect(clippy::indexing_slicing, reason = "comment justifies correctness")] #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { @@ -383,6 +343,7 @@ impl Display for O<'_> { }; let int_str = int.to_string().into_bytes(); let (mut v, frac_str) = if val.numer().sign() == Sign::Minus { + // Guaranteed to be non-empty. if int_str[0] == b'-' { ( Vec::with_capacity(int_str.len() + 1 + digits), @@ -441,13 +402,10 @@ pub struct Evaluator<'input, 'cache, 'prev, 'scratch, 'rand> { #[cfg(not(feature = "rand"))] _rng: PhantomData<fn() -> &'rand ()>, } -#[expect( - clippy::allow_attributes, - reason = "can't use expect since it isn't triggered when rand is enabled" -)] #[allow( - clippy::needless_lifetimes, - reason = "when rand is not enable, 'rand is not needed." + clippy::allow_attributes, + clippy::elidable_lifetime_names, + reason = "unify rand and not rand" )] impl<'input, 'cache, 'prev, 'scratch, 'rand> Evaluator<'input, 'cache, 'prev, 'scratch, 'rand> { /// Creates an `Evaluator<'input, 'cache, 'prev, 'scratch, 'rand>` based on the supplied arguments. @@ -495,6 +453,7 @@ impl<'input, 'cache, 'prev, 'scratch, 'rand> Evaluator<'input, 'cache, 'prev, 's /// # Errors /// /// Returns a [`LangErr`] iff the input violates the calc language. + #[expect(clippy::indexing_slicing, reason = "correct")] #[inline] pub fn evaluate(mut self) -> Result<O<'prev>, LangErr> { self.utf8 = if self.utf8.last().is_none_or(|b| *b != b'\n') { @@ -541,6 +500,7 @@ impl<'input, 'cache, 'prev, 'scratch, 'rand> Evaluator<'input, 'cache, 'prev, 's } } /// Reads from the input until the next non-{space/tab} byte value. + #[expect(clippy::indexing_slicing, reason = "correct")] fn consume_ws(&mut self) { // ControlFlow makes more sense to use in try_fold; however due to a lack // of a map_or_else function, it is easier to simply return a Result with @@ -882,7 +842,6 @@ impl<'input, 'cache, 'prev, 'scratch, 'rand> Evaluator<'input, 'cache, 'prev, 's i64::from_ne_bytes(bytes) } /// Generates a random 64-bit integer inclusively between the passed arguments. - #[expect(clippy::single_call_fn, reason = "easier to reason about")] #[expect( clippy::integer_division_remainder_used, reason = "need for uniform randomness" @@ -1117,6 +1076,7 @@ impl<'input, 'cache, 'prev, 'scratch, 'rand> Evaluator<'input, 'cache, 'prev, 's } } /// Evaluates number literal expressions as defined in the calc language. + #[expect(clippy::indexing_slicing, reason = "correct")] fn get_rational(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> { // ControlFlow makes more sense to use in try_fold; however due to a lack // of a map_or_else function, it is easier to simply return a Result with diff --git a/src/main.rs b/src/main.rs @@ -1,41 +1,6 @@ //! # `calc` //! //! Consult [`README.md`](https://crates.io/crates/calc_rational). -#![deny( - unknown_lints, - future_incompatible, - let_underscore, - missing_docs, - nonstandard_style, - refining_impl_trait, - rust_2018_compatibility, - rust_2018_idioms, - rust_2021_compatibility, - rust_2024_compatibility, - unsafe_code, - unused, - warnings, - clippy::all, - clippy::cargo, - clippy::complexity, - clippy::correctness, - clippy::nursery, - clippy::pedantic, - clippy::perf, - clippy::restriction, - clippy::style, - clippy::suspicious -)] -#![allow( - clippy::blanket_clippy_restriction_lints, - clippy::implicit_return, - clippy::min_ident_chars, - clippy::missing_trait_methods, - clippy::ref_patterns, - clippy::return_and_then, - clippy::single_call_fn, - reason = "noisy, opinionated, and likely doesn't prevent bugs or improve APIs" -)] #[cfg(feature = "std")] use calc_lib::{EvalIter, lending_iterator::LendingIterator as _}; #[cfg(feature = "std")]