diff --git a/Cargo.toml b/Cargo.toml index ca4b3eb4..e4a84362 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,6 +86,7 @@ clippy.fallible_impl_from = "deny" clippy.wildcard_enum_match_arm = "deny" clippy.unneeded_field_pattern = "deny" clippy.fn_params_excessive_bools = "deny" +clippy.must_use_candidate = "deny" [profile.container] inherits = "release" diff --git a/crates/radicle-cli/src/git.rs b/crates/radicle-cli/src/git.rs index aa51aea0..b91f95f9 100644 --- a/crates/radicle-cli/src/git.rs +++ b/crates/radicle-cli/src/git.rs @@ -43,6 +43,7 @@ pub struct Rev(String); impl Rev { /// Return the revision as a string. + #[must_use] pub fn as_str(&self) -> &str { &self.0 } diff --git a/crates/radicle-cli/src/git/ddiff.rs b/crates/radicle-cli/src/git/ddiff.rs index f005ffe7..7157beee 100644 --- a/crates/radicle-cli/src/git/ddiff.rs +++ b/crates/radicle-cli/src/git/ddiff.rs @@ -382,6 +382,7 @@ impl DDiff { } /// Returns owned files in the diff. + #[must_use] pub fn into_files(self) -> Vec { self.files } diff --git a/crates/radicle-cli/src/git/unified_diff.rs b/crates/radicle-cli/src/git/unified_diff.rs index a167bec5..3843d0eb 100644 --- a/crates/radicle-cli/src/git/unified_diff.rs +++ b/crates/radicle-cli/src/git/unified_diff.rs @@ -33,6 +33,7 @@ impl Error { Self::Syntax(msg.to_string()) } + #[must_use] pub fn is_eof(&self) -> bool { match self { Self::UnexpectedEof => true, @@ -137,12 +138,14 @@ impl TryFrom<&Hunk> for HunkHeader { } impl HunkHeader { + #[must_use] pub fn old_line_range(&self) -> std::ops::Range { let start: u32 = self.old_line_no; let end: u32 = self.old_line_no + self.old_size; start..end + 1 } + #[must_use] pub fn new_line_range(&self) -> std::ops::Range { let start: u32 = self.new_line_no; let end: u32 = self.new_line_no + self.new_size; @@ -579,6 +582,7 @@ impl<'a> Writer<'a> { Ok(()) } + #[must_use] pub fn styled(mut self, value: bool) -> Self { self.styled = value; self diff --git a/crates/radicle-cli/src/node.rs b/crates/radicle-cli/src/node.rs index 518f4f98..4db7efc3 100644 --- a/crates/radicle-cli/src/node.rs +++ b/crates/radicle-cli/src/node.rs @@ -25,12 +25,14 @@ pub struct SyncSettings { impl SyncSettings { /// Set sync timeout. Defaults to [`DEFAULT_SYNC_TIMEOUT`]. + #[must_use] pub fn timeout(mut self, timeout: time::Duration) -> Self { self.timeout = timeout; self } /// Set replicas. + #[must_use] pub fn replicas(mut self, replicas: sync::ReplicationFactor) -> Self { self.replicas = replicas; self @@ -44,6 +46,7 @@ impl SyncSettings { /// Use profile to populate sync settings, by adding preferred seeds if no seeds are specified, /// and removing the local node from the set. + #[must_use] pub fn with_profile(mut self, profile: &Profile) -> Self { // If no seeds were specified, add the preferred seeds. if self.seeds.is_empty() { diff --git a/crates/radicle-cli/src/terminal/cob.rs b/crates/radicle-cli/src/terminal/cob.rs index 1f1b8be4..7086c4c3 100644 --- a/crates/radicle-cli/src/terminal/cob.rs +++ b/crates/radicle-cli/src/terminal/cob.rs @@ -51,6 +51,7 @@ pub mod migrate { use super::MigrateSpinner; /// Display migration progress via a spinner. + #[must_use] pub fn spinner() -> MigrateSpinner { MigrateSpinner::default() } diff --git a/crates/radicle-cli/src/terminal/format.rs b/crates/radicle-cli/src/terminal/format.rs index 05440a02..2e026cd7 100644 --- a/crates/radicle-cli/src/terminal/format.rs +++ b/crates/radicle-cli/src/terminal/format.rs @@ -17,6 +17,7 @@ use radicle_term::element::Line; use crate::terminal as term; /// Format a node id to be more compact. +#[must_use] pub fn node_id_human_compact(node: &NodeId) -> Paint { let node = node.to_human(); let start = node.chars().take(7).collect::(); @@ -26,10 +27,12 @@ pub fn node_id_human_compact(node: &NodeId) -> Paint { } /// Format a node id. +#[must_use] pub fn node_id_human(node: &NodeId) -> Paint { Paint::new(node.to_human()) } +#[must_use] pub fn addr_compact(address: &Address) -> Paint { let host = match address.host() { HostName::Ip(ip) => ip.to_string(), @@ -72,17 +75,20 @@ pub fn command(cmd: D) -> Paint { } /// Format a COB id. +#[must_use] pub fn cob(id: &ObjectId) -> Paint { Paint::new(format!("{:.7}", id.to_string())) } /// Format a DID. +#[must_use] pub fn did(did: &Did) -> Paint { let nid = did.as_key().to_human(); Paint::new(format!("{}…{}", &nid[..7], &nid[nid.len() - 7..])) } /// Format a Visibility. +#[must_use] pub fn visibility(v: &Visibility) -> Paint<&str> { match v { Visibility::Public => term::format::positive("public"), @@ -91,6 +97,7 @@ pub fn visibility(v: &Visibility) -> Paint<&str> { } /// Format a policy. +#[must_use] pub fn policy(p: &Policy) -> Paint { match p { Policy::Allow => term::format::positive(p.to_string()), @@ -108,6 +115,7 @@ pub fn timestamp(time: impl Into) -> Paint { Paint::new(fmt.convert(duration.into())) } +#[must_use] pub fn bytes(size: usize) -> Paint { const KB: usize = 1024; const MB: usize = 1024usize.pow(2); @@ -125,6 +133,7 @@ pub fn bytes(size: usize) -> Paint { } /// Format a ref update. +#[must_use] pub fn ref_update(update: &RefUpdate) -> Paint<&'static str> { match update { RefUpdate::Updated { .. } => term::format::tertiary("updated"), @@ -134,6 +143,7 @@ pub fn ref_update(update: &RefUpdate) -> Paint<&'static str> { } } +#[must_use] pub fn ref_update_verbose(update: &RefUpdate) -> Paint { match update { RefUpdate::Created { name, .. } => format!( @@ -175,6 +185,7 @@ pub struct Identity<'a> { } impl<'a> Identity<'a> { + #[must_use] pub fn new(profile: &'a Profile) -> Self { Self { profile, @@ -183,11 +194,13 @@ impl<'a> Identity<'a> { } } + #[must_use] pub fn short(mut self) -> Self { self.short = true; self } + #[must_use] pub fn styled(mut self) -> Self { self.styled = true; self @@ -227,6 +240,7 @@ pub struct Author<'a> { } impl<'a> Author<'a> { + #[must_use] pub fn new(nid: &'a NodeId, profile: &Profile, verbose: bool) -> Author<'a> { let alias = profile.alias(nid); @@ -238,10 +252,12 @@ impl<'a> Author<'a> { } } + #[must_use] pub fn alias(&self) -> Option { self.alias.as_ref().map(|a| a.to_string().into()) } + #[must_use] pub fn you(&self) -> Option { if self.you { Some(term::format::primary("(you)").dim().italic().into()) @@ -256,6 +272,7 @@ impl<'a> Author<'a> { /// * `(, (you))` -- the `Author` is the local peer and has no alias /// * `(, )` -- the `Author` is another peer and has an alias /// * `(, )` -- the `Author` is another peer and has no alias + #[must_use] pub fn labels(self) -> (term::Label, term::Label) { let node_id = if self.verbose { term::format::node_id_human(self.nid) @@ -274,6 +291,7 @@ impl<'a> Author<'a> { (alias, author) } + #[must_use] pub fn line(self) -> Line { let (alias, author) = self.labels(); Line::spaced([alias, author]) @@ -283,6 +301,7 @@ impl<'a> Author<'a> { /// HTML-related formatting. pub mod html { /// Comment a string with HTML comments. + #[must_use] pub fn commented(s: &str) -> String { format!("") } @@ -290,6 +309,7 @@ pub mod html { /// Remove html style comments from a string. /// /// The HTML comments must start at the beginning of a line and stop at the end. + #[must_use] pub fn strip_comments(s: &str) -> String { let ends_with_newline = s.ends_with('\n'); let mut is_comment = false; @@ -323,6 +343,7 @@ pub mod issue { use radicle::issue::{CloseReason, State}; /// Format issue state. + #[must_use] pub fn state(s: &State) -> term::Paint { match s { State::Open => term::format::positive(s.to_string()), @@ -341,6 +362,7 @@ pub mod patch { use super::*; use radicle::patch::{State, Verdict}; + #[must_use] pub fn verdict(v: Option) -> term::Paint { match v { Some(Verdict::Accept) => term::PREFIX_SUCCESS.into(), @@ -350,6 +372,7 @@ pub mod patch { } /// Format patch state. + #[must_use] pub fn state(s: &State) -> term::Paint { match s { State::Draft => term::format::dim(s.to_string()), @@ -366,6 +389,7 @@ pub mod identity { use radicle::cob::identity::State; /// Format identity revision state. + #[must_use] pub fn state(s: &State) -> term::Paint { match s { State::Active => term::format::tertiary(s.to_string()), diff --git a/crates/radicle-cli/src/terminal/highlight.rs b/crates/radicle-cli/src/terminal/highlight.rs index b62f9420..e5f04ef4 100644 --- a/crates/radicle-cli/src/terminal/highlight.rs +++ b/crates/radicle-cli/src/terminal/highlight.rs @@ -59,6 +59,7 @@ impl Default for Theme { impl Theme { /// Get the named color. + #[must_use] pub fn color(&self, color: &'static str) -> term::Color { if let Some(c) = (self.color)(color) { c @@ -68,6 +69,7 @@ impl Theme { } /// Return the color of a syntax group. + #[must_use] pub fn highlight(&self, group: &'static str) -> Option { let color = match group { "keyword" => self.color("red"), diff --git a/crates/radicle-cli/src/terminal/io.rs b/crates/radicle-cli/src/terminal/io.rs index 77c6cf2a..e37d8b3d 100644 --- a/crates/radicle-cli/src/terminal/io.rs +++ b/crates/radicle-cli/src/terminal/io.rs @@ -21,6 +21,7 @@ pub struct PassphraseValidator { impl PassphraseValidator { /// Create a new validator. + #[must_use] pub fn new(keystore: Keystore) -> Self { Self { keystore } } diff --git a/crates/radicle-cli/src/terminal/patch.rs b/crates/radicle-cli/src/terminal/patch.rs index daf823a8..5d5599ad 100644 --- a/crates/radicle-cli/src/terminal/patch.rs +++ b/crates/radicle-cli/src/terminal/patch.rs @@ -140,6 +140,7 @@ blank is also okay. /// Combine the title and description fields to display to the user. #[inline] +#[must_use] pub fn message(title: &str, description: &str) -> String { format!("{title}\n\n{description}").trim().to_string() } diff --git a/crates/radicle-cli/src/terminal/upload_pack.rs b/crates/radicle-cli/src/terminal/upload_pack.rs index 6e3db7bf..ab4cf0eb 100644 --- a/crates/radicle-cli/src/terminal/upload_pack.rs +++ b/crates/radicle-cli/src/terminal/upload_pack.rs @@ -22,6 +22,7 @@ impl Default for UploadPack { impl UploadPack { /// Construct an empty set of spinners. + #[must_use] pub fn new() -> Self { Self { remotes: BTreeSet::new(), diff --git a/crates/radicle-core/src/repo.rs b/crates/radicle-core/src/repo.rs index 0ef25438..347ba18d 100644 --- a/crates/radicle-core/src/repo.rs +++ b/crates/radicle-core/src/repo.rs @@ -47,6 +47,7 @@ impl RepoId { /// /// Eg. `rad:z3XncAdkZjeK9mQS5Sdc4qhw98BUX`. /// + #[must_use] pub fn urn(&self) -> String { RAD_PREFIX.to_string() + &self.canonical() } @@ -65,6 +66,7 @@ impl RepoId { /// /// Eg. `z3XncAdkZjeK9mQS5Sdc4qhw98BUX`. /// + #[must_use] pub fn canonical(&self) -> String { multibase::encode(multibase::Base::Base58Btc, AsRef::<[u8]>::as_ref(&self.0)) } diff --git a/crates/radicle-localtime/src/lib.rs b/crates/radicle-localtime/src/lib.rs index 0c1d3d05..6eaa0cec 100644 --- a/crates/radicle-localtime/src/lib.rs +++ b/crates/radicle-localtime/src/lib.rs @@ -50,6 +50,7 @@ impl LocalTime { } /// Construct a local time from whole seconds since Epoch. + #[must_use] pub const fn from_secs(secs: u64) -> Self { Self { millis: secs as u128 * 1000, @@ -57,16 +58,19 @@ impl LocalTime { } /// Construct a local time from milliseconds since Epoch. + #[must_use] pub const fn from_millis(millis: u128) -> Self { Self { millis } } /// Return whole seconds since Epoch. + #[must_use] pub fn as_secs(&self) -> u64 { (self.millis / 1000).try_into().unwrap() } /// Return milliseconds since Epoch. + #[must_use] pub fn as_millis(&self) -> u64 { self.millis.try_into().unwrap() } @@ -76,6 +80,7 @@ impl LocalTime { /// # Panics /// /// This function will panic if `earlier` is later than `self`. + #[must_use] pub fn duration_since(&self, earlier: LocalTime) -> LocalDuration { LocalDuration::from_millis( self.millis @@ -85,6 +90,7 @@ impl LocalTime { } /// Get the difference between two times. + #[must_use] pub fn diff(&self, other: LocalTime) -> LocalDuration { if self > &other { self.duration_since(other) @@ -149,31 +155,37 @@ impl LocalDuration { pub const MAX: LocalDuration = LocalDuration(u128::MAX); /// Create a new duration from whole seconds. + #[must_use] pub const fn from_secs(secs: u64) -> Self { Self(secs as u128 * 1000) } /// Create a new duration from whole minutes. + #[must_use] pub const fn from_mins(mins: u64) -> Self { Self::from_secs(mins * 60) } /// Construct a new duration from milliseconds. + #[must_use] pub const fn from_millis(millis: u128) -> Self { Self(millis) } /// Return the number of minutes in this duration. + #[must_use] pub const fn as_mins(&self) -> u64 { self.as_secs() / 60 } /// Return the number of seconds in this duration. + #[must_use] pub const fn as_secs(&self) -> u64 { (self.0 / 1000) as u64 } /// Return the number of milliseconds in this duration. + #[must_use] pub const fn as_millis(&self) -> u128 { self.0 }