diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22c4d453..c276fcf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,17 @@ jobs: components: rustfmt - run: cargo fmt --check + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + - run: cargo clippy --locked --all-targets -- -D warnings + msrv: name: Minimum supported Rust version runs-on: ubuntu-latest diff --git a/src/agg/mod.rs b/src/agg/mod.rs index 2e5c80cc..953fdac7 100644 --- a/src/agg/mod.rs +++ b/src/agg/mod.rs @@ -93,7 +93,7 @@ mod tests { fn test_singleton_is_singleton() { for aggregator in aggregators(&fixtures::by_id()) { for taxon in fixtures::taxon_list() { - assert_matches!(aggregator.counting_aggregate(&vec![taxon.id]), Ok(tid) if tid == taxon.id); + assert_matches!(aggregator.counting_aggregate(&[taxon.id]), Ok(tid) if tid == taxon.id); } } } @@ -102,13 +102,11 @@ mod tests { fn test_invalid_taxa() { for aggregator in aggregators(&fixtures::by_id()) { assert_matches!( - aggregator.counting_aggregate(&vec![5]).unwrap_err(), + aggregator.counting_aggregate(&[5]).unwrap_err(), Error::Taxon(taxon::Error::UnknownTaxon(5)) ); assert_matches!( - aggregator - .counting_aggregate(&vec![1, 2, 5, 1]) - .unwrap_err(), + aggregator.counting_aggregate(&[1, 2, 5, 1]).unwrap_err(), Error::Taxon(taxon::Error::UnknownTaxon(5)) ); } diff --git a/src/agg/rank.rs b/src/agg/rank.rs index 0bcb315a..45a94c18 100644 --- a/src/agg/rank.rs +++ b/src/agg/rank.rs @@ -32,7 +32,7 @@ impl> RankAggregator { fn raise_to_rank(&self, taxon: TaxonId, target: Rank) -> Option { let mut ancestor = Some(taxon); - while ancestor.map_or(false, |a| self.ranks[a].map_or(true, |r| target < r)) { + while ancestor.is_some_and(|a| self.ranks[a].is_none_or(|r| target < r)) { ancestor = ancestor.and_then(|a| self.ancestors[a]); } ancestor @@ -58,7 +58,7 @@ impl> Iterator for RankAggregator { let (mut aggregate, mut aggregate_rank) = self.with_rank(initial_tid).expect("reeeeeeee"); - while self.records.peek().map_or(false, |(s, _)| *s == sequence) { + while self.records.peek().is_some_and(|(s, _)| *s == sequence) { let (_, next) = self.records.next().expect("we just peeked at it"); let (next_taxon, next_rank) = self.with_rank(next).expect("reeeeeee"); diff --git a/src/commands/prot2kmer2lca.rs b/src/commands/prot2kmer2lca.rs index 29f7e90e..f3e45d50 100644 --- a/src/commands/prot2kmer2lca.rs +++ b/src/commands/prot2kmer2lca.rs @@ -165,7 +165,7 @@ where let mut chunk_output = String::new(); for read in chunk { // Ignore empty reads and reads with a length smaller than k - if let Some(prot) = read.sequence.get(0).filter(|p| p.len() >= k) { + if let Some(prot) = read.sequence.first().filter(|p| p.len() >= k) { chunk_output.push_str(&format!(">{}\n", read.header)); let mut lcas = (0..(prot.len() - k + 1)) .map(|i| &prot[i..i + k]) diff --git a/src/commands/prot2tryp2lca.rs b/src/commands/prot2tryp2lca.rs index 69ee30f4..0f0cb796 100644 --- a/src/commands/prot2tryp2lca.rs +++ b/src/commands/prot2tryp2lca.rs @@ -121,7 +121,7 @@ pub fn prot2tryp2lca(args: ProtToTrypToLca) -> errors::Result<()> { } }) { - if let Some(lca) = fst.get(&peptide).map(Some).unwrap_or(default) { + if let Some(lca) = fst.get(peptide).map(Some).unwrap_or(default) { chunk_output.push_str(&format!("{}\n", lca)); } } diff --git a/src/commands/snaptaxon.rs b/src/commands/snaptaxon.rs index e33d7a61..42a95156 100644 --- a/src/commands/snaptaxon.rs +++ b/src/commands/snaptaxon.rs @@ -78,7 +78,9 @@ pub struct SnapTaxon { pub fn snaptaxon(args: SnapTaxon) -> errors::Result<()> { let taxons = taxon::read_taxa_file(&args.taxon_file)?; if args.rank.map(|r| r == rank::Rank::NoRank).unwrap_or(false) { - return Err(errors::Error::InvalidInvocation("Snap to an actual rank.".into()).into()); + return Err(errors::Error::InvalidInvocation( + "Snap to an actual rank.".into(), + )); } // Parsing the taxons diff --git a/src/commands/taxa2agg.rs b/src/commands/taxa2agg.rs index c73bd999..be1335d0 100644 --- a/src/commands/taxa2agg.rs +++ b/src/commands/taxa2agg.rs @@ -138,8 +138,7 @@ pub fn taxa2agg(args: TaxaToAgg) -> errors::Result<()> { (m, s) => Err(errors::Error::InvalidInvocation(format!( "{:?} and {:?} cannot be combined", m, s - )) - .into()), + ))), }; let aggregator = aggregator?; @@ -208,7 +207,7 @@ impl FromStr for Method { match s { "tree" => Ok(Method::Tree), "rmq" => Ok(Method::RangeMinimumQuery), - _ => Err(Error::ParseMethodError(s.to_string()).into()), + _ => Err(Error::ParseMethodError(s.to_string())), } } } @@ -237,7 +236,7 @@ impl FromStr for Strategy { "lca*" => Ok(Strategy::LowestCommonAncestor), "hybrid" => Ok(Strategy::Hybrid), "mrtl" => Ok(Strategy::MaximumRootToLeafPath), - _ => Err(Error::ParseStrategyError(s.to_string()).into()), + _ => Err(Error::ParseStrategyError(s.to_string())), } } } diff --git a/src/commands/taxa2freq.rs b/src/commands/taxa2freq.rs index b3887bf4..6a01b861 100644 --- a/src/commands/taxa2freq.rs +++ b/src/commands/taxa2freq.rs @@ -90,7 +90,9 @@ pub struct TaxaToFreq { pub fn taxa2freq(args: TaxaToFreq) -> errors::Result<()> { let taxons = taxon::read_taxa_file(&args.taxon_file)?; if args.rank == rank::Rank::NoRank { - return Err(errors::Error::InvalidInvocation("Snap to an actual rank.".into()).into()); + return Err(errors::Error::InvalidInvocation( + "Snap to an actual rank.".into(), + )); } let numfiles = args.input_files.len(); diff --git a/src/commands/translate.rs b/src/commands/translate.rs index 2e110c51..17e49810 100644 --- a/src/commands/translate.rs +++ b/src/commands/translate.rs @@ -169,7 +169,7 @@ impl FromStr for Frame { "1R" => Ok(Frame::Reverse1), "2R" => Ok(Frame::Reverse2), "3R" => Ok(Frame::Reverse3), - _ => Err(Error::ParseFrameError(s.to_string()).into()), + _ => Err(Error::ParseFrameError(s.to_string())), } } } diff --git a/src/commands/uniq.rs b/src/commands/uniq.rs index bcbd9b59..21c3c7a3 100644 --- a/src/commands/uniq.rs +++ b/src/commands/uniq.rs @@ -61,12 +61,9 @@ pub fn uniq(args: Uniq) -> errors::Result<()> { for record in fasta::Reader::new(io::stdin(), false).records() { let mut record = record?; if let Some(ref delimiter) = args.delimiter { - record.header.truncate( - record - .header - .find(delimiter) - .unwrap_or_else(|| record.header.len()), - ); + record + .header + .truncate(record.header.find(delimiter).unwrap_or(record.header.len())); } if let Some(ref mut rec) = last { if rec.header == record.header { diff --git a/src/dna/mod.rs b/src/dna/mod.rs index c68cc4f0..0a0840c0 100644 --- a/src/dna/mod.rs +++ b/src/dna/mod.rs @@ -55,7 +55,7 @@ impl From for u8 { } } -impl<'a> From<&'a u8> for Nucleotide { +impl From<&u8> for Nucleotide { fn from(ch: &u8) -> Self { Nucleotide::from(*ch) } @@ -69,13 +69,13 @@ pub struct Frame<'a>(&'a [Nucleotide]); #[derive(Debug, PartialEq)] pub struct Strand(Vec); -impl<'a> From<&'a [u8]> for Strand { +impl From<&[u8]> for Strand { fn from(read: &[u8]) -> Self { Strand(read.iter().map(Nucleotide::from).collect()) } } -impl<'a> From<&'a Vec> for Strand { +impl From<&Vec> for Strand { fn from(lines: &Vec) -> Self { Strand( lines diff --git a/src/dna/translation.rs b/src/dna/translation.rs index 8a3a5684..3260b8a1 100644 --- a/src/dna/translation.rs +++ b/src/dna/translation.rs @@ -11,7 +11,7 @@ use crate::dna::{Frame, Nucleotide}; #[derive(Debug, PartialEq, Eq, Hash)] pub struct Codon(Nucleotide, Nucleotide, Nucleotide); -impl<'a> From<&'a [Nucleotide]> for Codon { +impl From<&[Nucleotide]> for Codon { fn from(b: &[Nucleotide]) -> Self { Codon(b[0], b[1], b[2]) } diff --git a/src/io/fasta.rs b/src/io/fasta.rs index 5064c717..1a0149d5 100644 --- a/src/io/fasta.rs +++ b/src/io/fasta.rs @@ -42,8 +42,7 @@ impl Reader { }; if !header.starts_with('>') { - return Err(errors::Error::Io(io::Error::new( - io::ErrorKind::Other, + return Err(errors::Error::Io(io::Error::other( "Expected > at beginning of fasta header.", ))); } @@ -165,16 +164,16 @@ impl<'a, W: Write> Writer<'a, W> { write!(self.buffer, ">{}", record.header)?; let sequence = record.sequence.join(self.separator); if !self.wrap { - self.buffer.write_all(&[b'\n'])?; + self.buffer.write_all(b"\n")?; self.buffer.write_all(sequence.as_bytes())?; } else { for subseq in sequence.as_bytes().chunks(FASTA_WIDTH) { - self.buffer.write_all(&[b'\n'])?; + self.buffer.write_all(b"\n")?; self.buffer.write_all(subseq)?; } } if !sequence.is_empty() { - self.buffer.write_all(&[b'\n'])?; + self.buffer.write_all(b"\n")?; } Ok(()) } diff --git a/src/io/fastq.rs b/src/io/fastq.rs index 3b9fba90..6deba449 100644 --- a/src/io/fastq.rs +++ b/src/io/fastq.rs @@ -30,8 +30,7 @@ impl Reader { Some(header) => header?, }; if !header.starts_with('@') { - return Err(errors::Error::Io(io::Error::new( - io::ErrorKind::Other, + return Err(errors::Error::Io(io::Error::other( "Expected @ at beginning of fastq header.", ))); } @@ -59,8 +58,7 @@ impl Reader { .map(|line| !line.starts_with('+')) .unwrap_or(false) { - return Err(errors::Error::Io(io::Error::new( - io::ErrorKind::Other, + return Err(errors::Error::Io(io::Error::other( "Expected a + as separator.", ))); } @@ -71,8 +69,7 @@ impl Reader { if let Some(line) = self.lines.next() { quality.push_str(&line?) } else { - return Err(errors::Error::Io(io::Error::new( - io::ErrorKind::Other, + return Err(errors::Error::Io(io::Error::other( "Expected as many quality lines as \ sequence lines.", ))); diff --git a/src/rank.rs b/src/rank.rs index 473d8272..f4a8f151 100644 --- a/src/rank.rs +++ b/src/rank.rs @@ -108,6 +108,14 @@ impl Rank { } } +// Deliberately not `Some(self.cmp(other))`: NoRank is treated as incomparable, so that +// `score()` falls through every branch for it and `raise_to_rank` stops climbing. Making +// this canonical would give NoRank a score of 12 and change aggregation. +// +// Note this does contradict the Ord impl below, which reports NoRank as Less rather than +// incomparable, so `min()` and `<` disagree about it. Left as is because both behaviours +// are relied on; worth revisiting deliberately rather than as a lint fix. +#[allow(clippy::non_canonical_partial_ord_impl)] impl PartialOrd for Rank { fn partial_cmp(&self, other: &Rank) -> Option { if self == &Rank::NoRank || other == &Rank::NoRank { diff --git a/src/rmq/lca.rs b/src/rmq/lca.rs index 5ef13aa9..6413253b 100644 --- a/src/rmq/lca.rs +++ b/src/rmq/lca.rs @@ -49,8 +49,8 @@ impl LCACalculator { fn first_occurence(&self, taxon_id: TaxonId) -> taxon::Result { self.first_occurences .get(&taxon_id) - .ok_or_else(|| taxon::Error::UnknownTaxon(taxon_id).into()) - .map(|t| *t) + .ok_or(taxon::Error::UnknownTaxon(taxon_id)) + .copied() } } @@ -102,30 +102,30 @@ mod tests { #[test] fn test_two_on_same_path() { let aggregator = LCACalculator::new(fixtures::tree()); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185752]), Ok(185752)); - assert_matches!(aggregator.counting_aggregate(&vec![185752, 12884]), Ok(185752)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 2]), Ok(2)); - assert_matches!(aggregator.counting_aggregate(&vec![2, 1]), Ok(2)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185752]), Ok(185752)); + assert_matches!(aggregator.counting_aggregate(&[185752, 12884]), Ok(185752)); + assert_matches!(aggregator.counting_aggregate(&[1, 2]), Ok(2)); + assert_matches!(aggregator.counting_aggregate(&[2, 1]), Ok(2)); } #[test] fn test_two_on_fork() { let aggregator = LCACalculator::new(fixtures::tree()); - assert_matches!(aggregator.counting_aggregate(&vec![2, 10239]), Ok(1)); - assert_matches!(aggregator.counting_aggregate(&vec![10239, 2]), Ok(1)); - assert_matches!(aggregator.counting_aggregate(&vec![185751, 185752]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185752, 185751]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[2, 10239]), Ok(1)); + assert_matches!(aggregator.counting_aggregate(&[10239, 2]), Ok(1)); + assert_matches!(aggregator.counting_aggregate(&[185751, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185752, 185751]), Ok(12884)); } #[test] fn test_three_on_triangle() { let aggregator = LCACalculator::new(fixtures::tree()); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751, 185752]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185752, 185751]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185751, 12884, 185752]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185752, 12884, 185751]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185751, 185752, 12884]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185752, 185751, 12884]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185752, 185751]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185751, 12884, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185752, 12884, 185751]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185751, 185752, 12884]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185752, 185751, 12884]), Ok(12884)); } fn taxon(id: TaxonId, parent: TaxonId) -> Taxon { @@ -155,10 +155,10 @@ mod tests { #[test] fn test_with_deeper_interns() { let large_aggregator = LCACalculator::new(TaxonTree::new(&large_taxon_list())); - assert_matches!(large_aggregator.counting_aggregate(&vec![9, 7]), Ok(3)); - assert_matches!(large_aggregator.counting_aggregate(&vec![9, 10]), Ok(3)); - assert_matches!(large_aggregator.counting_aggregate(&vec![7, 9]), Ok(3)); - assert_matches!(large_aggregator.counting_aggregate(&vec![14, 8]), Ok(3)); - assert_matches!(large_aggregator.counting_aggregate(&vec![14, 8]), Ok(3)); + assert_matches!(large_aggregator.counting_aggregate(&[9, 7]), Ok(3)); + assert_matches!(large_aggregator.counting_aggregate(&[9, 10]), Ok(3)); + assert_matches!(large_aggregator.counting_aggregate(&[7, 9]), Ok(3)); + assert_matches!(large_aggregator.counting_aggregate(&[14, 8]), Ok(3)); + assert_matches!(large_aggregator.counting_aggregate(&[14, 8]), Ok(3)); } } diff --git a/src/rmq/mix.rs b/src/rmq/mix.rs index 9c7e686a..e93ed224 100644 --- a/src/rmq/mix.rs +++ b/src/rmq/mix.rs @@ -72,7 +72,7 @@ impl agg::Aggregator for MixCalculator { for (&right, &count) in taxons.iter() { let lca = self.lca_aggregator.lca(left, right)?; if lca == left || lca == right { - let mut weight = weights.entry(left).or_insert_with(Weights::new); + let weight = weights.entry(left).or_insert_with(Weights::new); if lca == left { weight.lca += count; } @@ -89,7 +89,7 @@ impl agg::Aggregator for MixCalculator { .iter() .max_by_key(|&(_, w)| NotNan::new(factorize(*w, self.factor)).unwrap()) .map(|tup| *tup.0) - .ok_or_else(|| agg::Error::EmptyInput) + .ok_or(agg::Error::EmptyInput) } } @@ -103,25 +103,25 @@ mod tests { #[test] fn test_full_rtl() { let aggregator = MixCalculator::new(fixtures::tree(), 0.0); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751]), Ok(185751)); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751, 185752, 185752]), Ok(185752)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 1, 10239, 10239, 10239, 12884, 185751, 185752]), Ok(10239)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751, 185752, 185752]), Ok(185752)); + assert_matches!(aggregator.counting_aggregate(&[1, 1, 10239, 10239, 10239, 12884, 185751, 185752]), Ok(10239)); } #[test] fn test_full_lca() { let aggregator = MixCalculator::new(fixtures::tree(), 1.0); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751, 185752, 185752]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 1, 10239, 10239, 10239, 12884, 185751, 185752]), Ok(1)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751, 185752, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[1, 1, 10239, 10239, 10239, 12884, 185751, 185752]), Ok(1)); } /* third example might fail because 12884 and 185751 have the same score. */ #[test] fn test_one_half() { let aggregator = MixCalculator::new(fixtures::tree(), 0.5); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 12884, 185751]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751, 185751]), Ok(185751)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 12884, 12884, 185751, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[12884, 12884, 185751]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751, 185751]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[1, 12884, 12884, 185751, 185752]), Ok(12884)); } } diff --git a/src/rmq/mod.rs b/src/rmq/mod.rs index c5c0c77a..b53d0d99 100644 --- a/src/rmq/mod.rs +++ b/src/rmq/mod.rs @@ -6,7 +6,6 @@ pub mod mix; pub mod rtl; use std::fmt::Display; -use std::mem::size_of; /// Represents a Range Minimum Query (RMQ), which can efficiently return the minimal value in a /// given range of an array. @@ -28,7 +27,7 @@ fn clearbits(n: usize, x: usize) -> usize { } fn size() -> usize { - size_of::() * 8 + usize::BITS as usize } fn intlog2(n: usize) -> usize { diff --git a/src/rmq/rtl.rs b/src/rmq/rtl.rs index d20707ad..307824a5 100644 --- a/src/rmq/rtl.rs +++ b/src/rmq/rtl.rs @@ -53,7 +53,7 @@ impl agg::Aggregator for RTLCalculator { .iter() .max_by_key(|&(_, &count)| NotNan::new(count).unwrap()) .map(|tup| *tup.0) - .ok_or_else(|| agg::Error::EmptyInput) + .ok_or(agg::Error::EmptyInput) } } @@ -68,26 +68,26 @@ mod tests { #[test] fn test_all_on_same_path() { let aggregator = RTLCalculator::new(fixtures::ROOT, &fixtures::by_id()); - assert_matches!(aggregator.counting_aggregate(&vec![1]), Ok(1)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 12884]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 12884, 185751]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[1]), Ok(1)); + assert_matches!(aggregator.counting_aggregate(&[1, 12884]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[1, 12884, 185751]), Ok(185751)); } #[test] fn favouring_root() { let aggregator = RTLCalculator::new(fixtures::ROOT, &fixtures::by_id()); - assert_matches!(aggregator.counting_aggregate(&vec![1, 1, 1, 185751, 1, 1]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[1, 1, 1, 185751, 1, 1]), Ok(185751)); } #[test] fn leaning_close() { let aggregator = RTLCalculator::new(fixtures::ROOT, &fixtures::by_id()); - assert_matches!(aggregator.counting_aggregate(&vec![1, 1, 185752, 185751, 185751, 1]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[1, 1, 185752, 185751, 185751, 1]), Ok(185751)); } #[test] fn non_deterministic() { let aggregator = RTLCalculator::new(fixtures::ROOT, &fixtures::by_id()); - assert!(vec![185751, 185752].contains(&aggregator.counting_aggregate(&vec![1, 1, 185752, 185751, 1]).unwrap())); + assert!([185751, 185752].contains(&aggregator.counting_aggregate(&[1, 1, 185752, 185751, 1]).unwrap())); } } diff --git a/src/taxon.rs b/src/taxon.rs index 79a029fc..6e3ac3ce 100644 --- a/src/taxon.rs +++ b/src/taxon.rs @@ -174,7 +174,7 @@ impl TaxonList { /// Retrieve a taxon from the taxon list by id, returns UnknownTaxon if /// the taxon is not present. pub fn get_or_unknown(&self, index: TaxonId) -> Result<&Taxon> { - Ok(self.get(index).ok_or(Error::UnknownTaxon(index))?) + self.get(index).ok_or(Error::UnknownTaxon(index)) } /// Retrieve the rank score of a taxon in the list. @@ -250,7 +250,7 @@ impl TaxonTree { // passes the filter. fn with_filtered( &self, - mut ancestors: &mut Vec>, + ancestors: &mut Vec>, current: TaxonId, ancestor: Option, filter: &F, @@ -265,7 +265,7 @@ impl TaxonTree { ancestors[current] = ancestor; if let Some(children) = self.children.get(¤t) { for child in children { - self.with_filtered(&mut ancestors, *child, ancestor, filter); + self.with_filtered(ancestors, *child, ancestor, filter); } } } diff --git a/src/tree/lca.rs b/src/tree/lca.rs index 927e3591..1cfa7be7 100644 --- a/src/tree/lca.rs +++ b/src/tree/lca.rs @@ -50,29 +50,29 @@ mod tests { #[test] fn test_two_on_same_path() { let aggregator = LCACalculator::new(fixtures::tree().root, &fixtures::by_id()); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185752]), Ok(185752)); - assert_matches!(aggregator.counting_aggregate(&vec![185752, 12884]), Ok(185752)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 2]), Ok(2)); - assert_matches!(aggregator.counting_aggregate(&vec![2, 1]), Ok(2)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185752]), Ok(185752)); + assert_matches!(aggregator.counting_aggregate(&[185752, 12884]), Ok(185752)); + assert_matches!(aggregator.counting_aggregate(&[1, 2]), Ok(2)); + assert_matches!(aggregator.counting_aggregate(&[2, 1]), Ok(2)); } #[test] fn test_two_on_fork() { let aggregator = LCACalculator::new(fixtures::tree().root, &fixtures::by_id()); - assert_matches!(aggregator.counting_aggregate(&vec![2, 10239]), Ok(1)); - assert_matches!(aggregator.counting_aggregate(&vec![10239, 2]), Ok(1)); - assert_matches!(aggregator.counting_aggregate(&vec![185751, 185752]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185752, 185751]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[2, 10239]), Ok(1)); + assert_matches!(aggregator.counting_aggregate(&[10239, 2]), Ok(1)); + assert_matches!(aggregator.counting_aggregate(&[185751, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185752, 185751]), Ok(12884)); } #[test] fn test_three_on_triangle() { let aggregator = LCACalculator::new(fixtures::tree().root, &fixtures::by_id()); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751, 185752]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185752, 185751]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185751, 12884, 185752]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185752, 12884, 185751]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185751, 185752, 12884]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![185752, 185751, 12884]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185752, 185751]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185751, 12884, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185752, 12884, 185751]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185751, 185752, 12884]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[185752, 185751, 12884]), Ok(12884)); } } diff --git a/src/tree/mix.rs b/src/tree/mix.rs index 41583f7f..883ad5d5 100644 --- a/src/tree/mix.rs +++ b/src/tree/mix.rs @@ -74,25 +74,25 @@ mod tests { #[test] fn test_full_rtl() { let aggregator = MixCalculator::new(fixtures::ROOT, &fixtures::by_id(), 0.0); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751]), Ok(185751)); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751, 185752, 185752]), Ok(185752)); - assert!(vec![185751, 185752].contains(&aggregator.counting_aggregate(&vec![1, 1, 10239, 10239, 12884, 185751, 185752]).unwrap())); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751, 185752, 185752]), Ok(185752)); + assert!([185751, 185752].contains(&aggregator.counting_aggregate(&[1, 1, 10239, 10239, 12884, 185751, 185752]).unwrap())); } #[test] fn test_full_lca() { let aggregator = MixCalculator::new(fixtures::ROOT, &fixtures::by_id(), 1.0); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751]), Ok(185751)); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751, 185752, 185752]), Ok(12884)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 1, 10239, 10239, 10239, 12884, 185751, 185752]), Ok(1)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751, 185752, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[1, 1, 10239, 10239, 10239, 12884, 185751, 185752]), Ok(1)); } #[test] fn test_two_thirds() { let aggregator = MixCalculator::new(fixtures::ROOT, &fixtures::by_id(), 0.66); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751]), Ok(185751)); - assert_matches!(aggregator.counting_aggregate(&vec![12884, 185751]), Ok(185751)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 12884, 12884, 185751]), Ok(185751)); - assert_matches!(aggregator.counting_aggregate(&vec![1, 12884, 10239, 185751, 185751, 185752]), Ok(12884)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[12884, 185751]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[1, 12884, 12884, 185751]), Ok(185751)); + assert_matches!(aggregator.counting_aggregate(&[1, 12884, 10239, 185751, 185751, 185752]), Ok(12884)); } } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 3c8531bd..6d6e1c52 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -41,7 +41,7 @@ impl Tree { if !tree.contains_key(&parent) { queue.push_back(parent); } - let siblings = tree.entry(parent).or_insert_with(HashSet::new); + let siblings = tree.entry(parent).or_default(); siblings.insert(id); } Ok(Tree::create(root, &tree, taxons)) @@ -62,7 +62,7 @@ impl Tree { .map(|&tid| Tree::create(tid, children, taxons)) .collect() }) - .unwrap_or_else(Vec::new), + .unwrap_or_default(), } }