8000 chore(lint): make all-targets clippy pass and gate it in CI by adityamukho · Pull Request #895 · project-minigraf/minigraf · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: Lint

# rustfmt and clippy in one job: formatting takes a second once the toolchain
# is installed. Clippy lints the library and binary with every feature; tests,
# examples and benches are not linted (the panic-prevention lints in Cargo.toml
# would need thousands of changes there). wasm.yml lints the wasm targets.
# is installed. Clippy lints all targets with every feature. clippy.toml scopes
# panic and indexing exemptions to tests; Cargo.toml keeps production denies.
# wasm.yml lints the wasm targets.

on:
push:
Expand Down Expand Up @@ -33,4 +33,4 @@ jobs:
run: cargo fmt -- --check

- name: Run clippy
run: cargo clippy --all-features -- -D warnings
run: cargo clippy --all-targets --all-features -- -D warnings
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ web-sys = { version = "0.3", optional = true, features = [
] }

[dev-dependencies]
# Checked float-to-integer conversions in the soak harness (already transitive).
num-traits = "0.2"
serde_json = "1.0"
pest = "2"
pest_derive = "2"
Expand Down
6 changes: 3 additions & 3 deletions benches/helpers/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl Shape {

/// Rows the answer has.
pub fn rows(&self) -> usize {
self.oracle().rows as usize
usize::try_from(self.oracle().rows).expect("fixture value fits in usize")
}

/// The answer, computed without the database.
Expand Down Expand Up @@ -215,13 +215,13 @@ impl Shape {
self.records(|e, a, v| {
command.push_str(&format!("[#uuid \"{e}\" {a} {}]", edn(&v)));
count += 1;
if count % 1000 == 0 {
if count.is_multiple_of(1000) {
command.push_str("])");
db.execute(&command).unwrap();
command = String::from("(transact [");
}
});
if count % 1000 != 0 {
if !count.is_multiple_of(1000) {
command.push_str("])");
db.execute(&command).unwrap();
}
Expand Down
13 changes: 10 additions & 3 deletions benches/minigraf_bench.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#![allow(
clippy::expect_used,
clippy::indexing_slicing,
clippy::panic,
clippy::unwrap_used
)]
// TODO (Phase 7.4): Add profiling integration before optimizing the query path.
//
// Integrate `pprof` as a Criterion profiler (via the `pprof` crate's Criterion
Expand Down Expand Up @@ -61,8 +67,9 @@ mod chunked_transactions;
#[cfg(not(target_arch = "wasm32"))]
mod simd_helpers;

use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group};
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group};
use minigraf::OpenOptions;
use std::hint::black_box;

// ── Task 3: insert/ ───────────────────────────────────────────────────────────

Expand Down Expand Up @@ -1853,7 +1860,7 @@ fn bench_prepared(c: &mut Criterion) {
let pq = db
.prepare("(query [:find ?e :where [?e :val ?v] [(< ?v $threshold)]])")
.unwrap();
let threshold = (n / 2) as i64;
let threshold = i64::try_from(n / 2).expect("fixture value fits in i64");
b.iter(|| {
pq.execute(&[(
"threshold",
Expand Down Expand Up @@ -1980,7 +1987,7 @@ fn bench_predicate_pushdown(c: &mut Criterion) {

for &(label, n) in SCALES {
let db = helpers::populate_with_names(n);
let threshold = (n as i64) * 9 / 10;
let threshold = i64::try_from(n).expect("fixture value fits in i64") * 9 / 10;
let query = format!(
"(query [:find ?e ?n :where [?e :val ?v] [?e :name ?n] [(> ?v {})]])",
threshold
Expand Down
6 changes: 4 additions & 2 deletions benches/minigraf_bench/chunked_transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ pub fn bench_chunked_transactions(c: &mut Criterion) {
let mut tx = db.begin_write().unwrap();
black_box(tx.execute(black_box(first)).unwrap());
black_box(tx.execute(black_box(second)).unwrap());
black_box(tx.commit().unwrap());
tx.commit().unwrap();
black_box(());
};
validated.get_or_init(|| {
let check = fixture(None);
Expand Down Expand Up @@ -184,7 +185,8 @@ pub fn bench_chunked_transactions(c: &mut Criterion) {
assert_eq!(error.code(), "API-011");
black_box(error);
black_box(tx.execute(black_box(AFTER)).unwrap());
black_box(tx.commit().unwrap());
tx.commit().unwrap();
black_box(());
};
validated.get_or_init(|| {
let check = fixture(None);
Expand Down
2 changes: 1 addition & 1 deletion benches/minigraf_bench/fact_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn records(n: usize) -> Vec<FactRecord> {
};
FactRecord {
entity: Uuid::from_u128(u128::try_from(entity).unwrap() + 1),
attribute: if entity % 2 == 0 {
attribute: if entity.is_multiple_of(2) {
":history/a"
} else {
":history/b"
Expand Down
3 changes: 2 additions & 1 deletion benches/minigraf_bench/history.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use criterion::{BenchmarkId, Criterion, black_box};
use criterion::{BenchmarkId, Criterion};
use std::hint::black_box;

// ── point_query_chain_depth (Issue #323) ─────────────────────────────────────
//
Expand Down
2 changes: 1 addition & 1 deletion benches/minigraf_bench/memory_meter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub fn bench_memory_meter(c: &mut Criterion) {
.path(&path)
.open()
.unwrap();
let err = constrained.execute(query).err().expect("limit enforced");
let err = constrained.execute(query).expect_err("limit enforced");
assert_eq!(err.code(), "QRY-012");
assert!(
err.to_string().contains("Aggregate"),
Expand Down
4 changes: 2 additions & 2 deletions benches/minigraf_bench/pagination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub fn bench_pagination(c: &mut Criterion) {
if descending { ":desc" } else { ":asc" }
);
let expected: Vec<_> = (offset..offset + limit)
.map(|i| vec![Value::Integer(if descending { n - 1 - i } else { i } as i64)])
.map(|i| vec![Value::Integer(i64::try_from(if descending { n - 1 - i } else { i }).expect("fixture value fits in i64"))])
.collect();
// Validate the entire page (including offset/order), not just
// its size. Keep fixture and oracle work out of the measurement.
Expand All @@ -94,7 +94,7 @@ pub fn bench_pagination(c: &mut Criterion) {
oracle.sort_unstable_by(|a, b| b.0.cmp(&a.0).then(a.1.cmp(&b.1)).then(a.2.cmp(&b.2)));
let expected: Vec<_> = oracle[137..147]
.iter()
.map(|&(g, s, v)| vec![Value::Integer(g as i64), Value::Integer(s as i64), Value::Integer(v as i64)])
.map(|&(g, s, v)| vec![Value::Integer(i64::try_from(g).expect("fixture value fits in i64")), Value::Integer(i64::try_from(s).expect("fixture value fits in i64")), Value::Integer(i64::try_from(v).expect("fixture value fits in i64"))])
.collect();
assert!(rows(&db, query) == expected, "complete tie order matches oracle");
b.iter(|| black_box(rows(&db, black_box(query))));
Expand Down
4 changes: 3 additions & 1 deletion benches/minigraf_bench/storage_v3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ fn check_golden(db: &Minigraf) {
/// the golden/integrity tests; no checksum is recomputed on the damaged page.
fn newest_meta(bytes: &[u8]) -> &[u8] {
bytes
.chunks_exact(4096)
.as_chunks::<4096>()
.0
.iter()
.take(2)
.filter(|page| &page[..4] == b"MGRF" && &page[8..12] == b"META")
.max_by_key(|page| u64::from_le_bytes(page[16..24].try_into().unwrap()))
Expand Down
52 changes: 28 additions & 24 deletions benches/simd_helpers.rs
10BC8
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#![allow(clippy::cast_possible_truncation)] // synthetic bench data: N ≤ 1M fits in i64
#![allow(clippy::cast_sign_loss)] // tx_count cast: monotonic counter, always positive

use wide::{CmpGt, i64x4, u64x4};
use wide::{i64x4, u64x4};

/// Count facts where `valid_from[i] <= ts && ts < valid_to[i]`.
///
Expand All @@ -26,13 +26,14 @@ pub fn valid_time_filter_simd(valid_from: &[i64], valid_to: &[i64], ts: i64) ->
let ts_v = i64x4::splat(ts);
let mut count = 0usize;

for (vf_chunk, vt_chunk) in valid_from.chunks_exact(4).zip(valid_to.chunks_exact(4)) {
let [vf0, vf1, vf2, vf3] = *vf_chunk else {
unreachable!()
};
let [vt0, vt1, vt2, vt3] = *vt_chunk else {
unreachable!()
};
for (vf_chunk, vt_chunk) in valid_from
.as_chunks::<4>()
.0
.iter()
.zip(valid_to.as_chunks::<4>().0)
{
let [vf0, vf1, vf2, vf3] = *vf_chunk;
let [vt0, vt1, vt2, vt3] = *vt_chunk;

let vf = i64x4::new([vf0, vf1, vf2, vf3]);
let vt = i64x4::new([vt0, vt1, vt2, vt3]);
Expand Down Expand Up @@ -70,8 +71,7 @@ pub fn as_of_filter_simd(tx_counts: &[u64], threshold: u64) -> usize {
let thr_v = u64x4::splat(threshold);
let mut count = 0usize;

for chunk in tx_counts.chunks_exact(4) {
let [a, b, c, d] = *chunk else { unreachable!() };
for &[a, b, c, d] in tx_counts.as_chunks::<4>().0 {
let v = u64x4::new([a, b, c, d]);

// tc <= threshold ≡ NOT (tc > threshold)
Expand Down Expand Up @@ -99,9 +99,8 @@ pub fn as_of_filter_simd(tx_counts: &[u64], threshold: u64) -> usize {
pub fn sum_simd_i64(values: &[i64]) -> i64 {
let mut acc = i64x4::splat(0_i64);

for chunk in values.chunks_exact(4) {
let [a, b, c, d] = *chunk else { unreachable!() };
acc = acc + i64x4::new([a, b, c, d]);
for &[a, b, c, d] in values.as_chunks::<4>().0 {
acc += i64x4::new([a, b, c, d]);
}

let lanes: [i64; 4] = acc.to_array();
Expand All @@ -117,7 +116,6 @@ pub fn sum_simd_i64(values: &[i64]) -> i64 {

#[cfg(test)]
mod tests {
use super::*;

// ── valid_time_filter_simd ────────────────────────────────────────────────

Expand All @@ -135,7 +133,10 @@ mod tests {
.filter(|&(&vf, &vt)| vf <= ts && ts < vt)
.count();

assert_eq!(valid_time_filter_simd(&valid_from, &valid_to, ts), scalar);
assert_eq!(
super::valid_time_filter_simd(&valid_from, &valid_to, ts),
scalar
);
}

#[test]
Expand All @@ -151,12 +152,15 @@ mod tests {
.filter(|&(&vf, &vt)| vf <= ts && ts < vt)
.count();

10BC8 assert_eq!(valid_time_filter_simd(&valid_from, &valid_to, ts), scalar);
assert_eq!(
super::valid_time_filter_simd(&valid_from, &valid_to, ts),
scalar
);
}

#[test]
fn test_valid_time_filter_empty() {
assert_eq!(valid_time_filter_simd(&[], &[], 0), 0);
assert_eq!(super::valid_time_filter_simd(&[], &[], 0), 0);
}

// ── as_of_filter_simd ─────────────────────────────────────────────────────
Expand All @@ -169,7 +173,7 @@ mod tests {

let scalar = tx_counts.iter().filter(|&&tc| tc <= threshold).count();

assert_eq!(as_of_filter_simd(&tx_counts, threshold), scalar);
assert_eq!(super::as_of_filter_simd(&tx_counts, threshold), scalar);
}

#[test]
Expand All @@ -180,12 +184,12 @@ mod tests {

let scalar = tx_counts.iter().filter(|&&tc| tc <= threshold).count();

assert_eq!(as_of_filter_simd(&tx_counts, threshold), scalar);
assert_eq!(super::as_of_filter_simd(&tx_counts, threshold), scalar);
}

#[test]
fn test_as_of_filter_empty() {
assert_eq!(as_of_filter_simd(&[], 100), 0);
assert_eq!(super::as_of_filter_simd(&[], 100), 0);
}

// ── sum_simd_i64 ──────────────────────────────────────────────────────────
Expand All @@ -196,7 +200,7 @@ mod tests {
let values: Vec<i64> = (1_i64..=9).collect();
let scalar: i64 = values.iter().sum();

assert_eq!(sum_simd_i64(&values), scalar);
assert_eq!(super::sum_simd_i64(&values), scalar);
}

#[test]
Expand All @@ -205,19 +209,19 @@ mod tests {
let values: Vec<i64> = (1_i64..=8).collect();
let scalar: i64 = values.iter().sum();

assert_eq!(sum_simd_i64(&values), scalar);
assert_eq!(super::sum_simd_i64(&values), scalar);
}

#[test]
fn test_sum_simd_empty() {
assert_eq!(sum_simd_i64(&[]), 0);
assert_eq!(super::sum_simd_i64(&[]), 0);
}

#[test]
fn test_sum_simd_negatives() {
let values = vec![-3_i64, -2, -1, 0, 1, 2, 3];
let scalar: i64 = values.iter().sum();

assert_eq!(sum_simd_i64(&values), scalar);
assert_eq!(super::sum_simd_i64(&values), scalar);
}
}
5 changes: 5 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Assertions and fixture helpers may panic; production code keeps Cargo.toml's denies.
allow-unwrap-in-tests = true
allow-expect-in-tests = true
allow-panic-in-tests = true
allow-indexing-slicing-in-tests = true
1 change: 1 addition & 0 deletions examples/memory_profile.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(clippy::unwrap_used)]
//! Memory profiling target for heaptrack.
//!
//! Usage: cargo run --example memory_profile --release -- <fact_count>
Expand Down
1 change: 1 addition & 0 deletions examples/pid_ns_helper.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(clippy::indexing_slicing)]
//! Helper for `tests/pid_namespace_test.rs`. Opens a database and either dies
//! holding the lock, or reports whether the open succeeded.
//!
Expand Down
3 changes: 2 additions & 1 deletion examples/tutorial_udfs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(clippy::indexing_slicing)]
//! Tutorial Section 10 — User-Defined Functions
//!
//! Demonstrates `register_predicate` and `register_aggregate` in the context
Expand Down Expand Up @@ -195,7 +196,7 @@ fn main() -> anyhow::Result<()> {
for row in &window_rows {
let order = match &row[0] {
Value::Keyword(k) => format!(":{}", k),
Value::Ref(u) => format!("{}", &u.to_string()[..8]),
Value::Ref(u) => u.to_string()[..8].to_string(),
other => format!("{:?}", other),
};
let score = match &row[1] {
Expand Down
6 changes: 3 additions & 3 deletions src/graph/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1426,7 +1426,7 @@ impl FactStorage {
) -> Result<Option<Value>> {
let relevant_facts = self.get_facts_by_entity_attribute(entity_id, attribute)?;
let mut net = net_asserted_facts(relevant_facts);
net.sort_by(|a, b| b.tx_count.cmp(&a.tx_count));
net.sort_by_key(|f| std::cmp::Reverse(f.tx_count));
Ok(net.first().map(|f| f.value.clone()))
}

Expand Down Expand Up @@ -2502,7 +2502,7 @@ mod tests {
entity,
attribute: attr.to_string(),
value,
tx_id: tx_count as u64,
tx_id: tx_count,
tx_count,
valid_from,
valid_to,
Expand All @@ -2516,7 +2516,7 @@ mod tests {
entity,
attribute: attr.to_string(),
value,
tx_id: tx_count as u64,
tx_id: tx_count,
tx_count,
valid_from: 0,
valid_to: VALID_TIME_FOREVER,
Expand Down
9 changes: 5 additions & 4 deletions src/query/datalog/parser.rs
69B6
Original file line number Diff line number Diff line change
Expand Up @@ -3246,7 +3246,9 @@ mod tests {
}
}

fn parse_order(input: &str) -> Result<(Vec<(FindSpec, Order)>, Option<Count>)> {
type ParsedOrder = (Vec<(FindSpec, Order)>, Option<Count>);

fn parse_order(input: &str) -> Result<ParsedOrder> {
match parse_datalog_command(input)? {
DatalogCommand::Query(q) => Ok((q.order_by, q.offset)),
_ => panic!("expected Query"),
Expand Down Expand Up @@ -4529,8 +4531,7 @@ mod window_parse_tests {
parse_datalog_command(&query("(sum ?v :over (:order-by ?v :rows 1 preceding))"))
.expect("matching frame");
let error = parse_datalog_command(&query("(sum ?v :over (:order-by ?v))"))
.err()
.expect("different frame");
.expect_err("different frame");
assert_eq!(crate::MinigrafError::from(error).code(), "PRS-117");
}

Expand Down Expand Up @@ -4679,7 +4680,7 @@ mod window_parse_tests {
r#"(query [:find ?d (count ?e) (sum ?d :over (:partition-by ?v :order-by ?d)) :where [?e :x ?v] [?e :d ?d]])"#,
r#"(query [:find ?d (count ?e) (sum ?v :over (:order-by ?d)) :with ?v :where [?e :x ?v] [?e :d ?d]])"#,
] {
let err = parse_datalog_command(q).err().expect("rejected");
let err = parse_datalog_command(q).expect_err("rejected");
assert_eq!(crate::MinigrafError::from(err).code(), "PRS-082");
}
parse_datalog_command(
Expand Down
Loading
Loading
0