diff --git a/crates/eureka-pipeline/src/lib.rs b/crates/eureka-pipeline/src/lib.rs index 3186941..07c6857 100644 --- a/crates/eureka-pipeline/src/lib.rs +++ b/crates/eureka-pipeline/src/lib.rs @@ -805,7 +805,7 @@ macro_rules! pipeline_kinds { /// shape, not a document's. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[serde(tag = "kind", content = "value", rename_all = "snake_case")] - #[allow(clippy::large_enum_variant, reason = "a document is a transient wrapper around one value; boxing a variant would change every construction site")] + #[allow(clippy::large_enum_variant, reason = "one value per request or per batch of at most 64; boxing a variant would buy no memory and change every construction site")] pub enum PipelineDocument { $($variant($value)),* } impl PipelineKind { @@ -1908,7 +1908,7 @@ mod tests { // refuses this one: the digits rule is satisfied either way. refused(&format!("{CAMPAIGN}:cut_spec:cut-3a.1")); refused(&format!("{CAMPAIGN}:CUT_SPEC:cut-3a.r1")); - refused(&format!("EUREKA-STATE:cut_spec:cut-3a.r1")); + refused("EUREKA-STATE:cut_spec:cut-3a.r1"); refused(&format!("{CAMPAIGN}:cut_spec:cut-3a.r1:")); refused(&format!("{CAMPAIGN}::cut-3a.r1")); refused("cut-3a.r1"); diff --git a/crates/huginn-daemon/src/daemon.rs b/crates/huginn-daemon/src/daemon.rs index 614129e..c5453ff 100644 --- a/crates/huginn-daemon/src/daemon.rs +++ b/crates/huginn-daemon/src/daemon.rs @@ -150,7 +150,7 @@ impl> Daemon { HuginnMindResponse::Admit(outcome) } HuginnMindRequest::View { id, .. } => match self.mind.view(&id) { - Ok(view) => HuginnMindResponse::View(view), + Ok(view) => HuginnMindResponse::View(view.map(Box::new)), Err(refusal) => HuginnMindResponse::Refused(refusal), }, HuginnMindRequest::Query { selection, semantic: None, .. } => match self.mind.query(&selection) { @@ -495,9 +495,11 @@ pub(crate) mod tests { Ok(Daemon::new(Mind::open(state_root, instance)?, NoIndex)) } + type Seen = Vec<(Vec, Vec)>; + #[derive(Clone, Default)] struct RecordingIndex { - seen: Arc, Vec)>>>, + seen: Arc>, } impl IndexSink for RecordingIndex { @@ -607,7 +609,7 @@ pub(crate) mod tests { let PipelinePageItems::Documents(views) = &page.items else { panic!("the document projection is the view") }; assert_eq!(views[0].status, PipelineStatus::InForce); let view = daemon.handle(HuginnMindRequest::View { instance: slug(INSTANCE), id: id.clone() }, now()).answered(); - assert_eq!(view, HuginnMindResponse::View(Some(views[0].clone()))); + assert_eq!(view, HuginnMindResponse::View(Some(Box::new(views[0].clone())))); } /// Ruling 14 across the transport, on both sides: the mind refuses a read diff --git a/crates/huginn-daemon/src/index/mod.rs b/crates/huginn-daemon/src/index/mod.rs index fef9ebb..d52f5b6 100644 --- a/crates/huginn-daemon/src/index/mod.rs +++ b/crates/huginn-daemon/src/index/mod.rs @@ -596,7 +596,7 @@ impl Projector { let found = self.index.search(&self.collection, &vector, limit, budget.left()?)?; let mut hits = Vec::with_capacity(found.len()); for hit in found { - match PipelineKind::ALL.into_iter().find(|kind| kind.name() == hit.kind) { + match PipelineKind::ALL.iter().find(|kind| kind.name() == hit.kind) { Some(kind) => hits.push((PipelineRef { kind: *kind, id: Short(hit.doc_id) }, hit.score)), None => eprintln!("huginn: the index returned {} under the unknown kind {:?}; it is left out", hit.doc_id, hit.kind), } diff --git a/crates/huginn-daemon/src/index/tests.rs b/crates/huginn-daemon/src/index/tests.rs index d18f25b..2e53a16 100644 --- a/crates/huginn-daemon/src/index/tests.rs +++ b/crates/huginn-daemon/src/index/tests.rs @@ -19,10 +19,13 @@ use super::*; use crate::daemon::Daemon; use crate::daemon::tests::{INSTANCE, OTHER, batch, campaign_seed, now, question_and_ruling, slug}; +type AfterAbsorb = Box; +type Edit = (&'static str, Box); + thread_local! { /// Runs once, in the worker's own turn, between the inbox being absorbed /// and a search being taken, holding the guard `serve_search` holds. - static AFTER_ABSORB: std::cell::RefCell>> = const { std::cell::RefCell::new(None) }; + static AFTER_ABSORB: std::cell::RefCell> = const { std::cell::RefCell::new(None) }; } /// The hook `serve_search` calls at the point where a second lock once left a @@ -167,7 +170,7 @@ fn reconcile_indexes_exactly_the_indexable_documents_the_collection_lacks() { fn a_model_digest_change_rebuilds_the_collection() { let (_root, mind) = mind_with_documents(); let entries = mind.index_entries(None).unwrap(); - let changes: [(&str, Box); 3] = [ + let changes: [Edit; 3] = [ ("digest", Box::new(|identity| identity.digest = "d2".into())), ("name", Box::new(|identity| identity.name = "other-model".into())), ("dimensions", Box::new(|identity| identity.dimensions = 8)), @@ -1352,7 +1355,7 @@ fn a_model_changed_refusal_names_the_state_and_the_pending_count() { fn a_search_re_reads_the_collections_label() { let (_root, mind) = mind_with_documents(); let entries = mind.index_entries(None).unwrap(); - let cases: [(&str, Box); 3] = [ + let cases: [Edit; 3] = [ ( "another mind's label", Box::new(|stored| { diff --git a/crates/huginn-daemon/src/serve.rs b/crates/huginn-daemon/src/serve.rs index 561ad1b..60755d5 100644 --- a/crates/huginn-daemon/src/serve.rs +++ b/crates/huginn-daemon/src/serve.rs @@ -1024,7 +1024,7 @@ mod tests { let message_id = format!("{stem}{}", "0".repeat(zeros)); let at_probe = encoded_len(&reply_with_payload(&message_id, operation, runtime_id, "A".repeat(probe))); let payload_len = (probe as i64 + (target as i64 - at_probe as i64)) as usize; - if payload_len % 4 == 0 { + if payload_len.is_multiple_of(4) { let message = reply_with_payload(&message_id, operation, runtime_id, "A".repeat(payload_len)); assert_eq!(encoded_len(&message), target); return (message_id, message); diff --git a/crates/huginn-mind/src/admission.rs b/crates/huginn-mind/src/admission.rs index 5149f77..c05aaff 100644 --- a/crates/huginn-mind/src/admission.rs +++ b/crates/huginn-mind/src/admission.rs @@ -1669,7 +1669,7 @@ mod tests { let hand_off_ref = r(K::HandOff, &format!("{INSTANCE}:hand_off:{OTHER_INSTANCE}.gamecult_-huginn.2026-09-16")); // Accepted, one per resolvable kind. - committed(admit(&mut world(), vec![target(2, &[INVARIANT]), resolution(target_ref.clone(), superseded(&[target_r2.clone()]))])); + committed(admit(&mut world(), vec![target(2, &[INVARIANT]), resolution(target_ref.clone(), superseded(std::slice::from_ref(&target_r2)))])); committed(admit(&mut world(), vec![resolution(question_ref.clone(), withdrawn())])); committed(admit(&mut world(), vec![D::Ruling(ruling("R2")), resolution(ruling_ref.clone(), superseded(&[r(K::Ruling, &id("ruling", "R2"))]))])); committed(admit(&mut world(), vec![resolution(spec_ref.clone(), withdrawn())])); @@ -1712,7 +1712,7 @@ mod tests { incompatible(K::CutSpec, "Superseded") ); assert_eq!( - refusal(admit(&mut world(), vec![resolution(finding_ref.clone(), superseded(&[finding_ref.clone()]))])), + refusal(admit(&mut world(), vec![resolution(finding_ref.clone(), superseded(std::slice::from_ref(&finding_ref)))])), incompatible(K::Finding, "Superseded") ); assert_eq!( @@ -2212,7 +2212,7 @@ mod tests { committed(admit(&mut open(), vec![resolution(subject(), withdrawn())])); let other_run = r(K::Run, &run_key("z")); let refused = [ - (superseded(&[other_run.clone()]), "Superseded"), + (superseded(std::slice::from_ref(&other_run)), "Superseded"), (ResolutionOutcome::Answered { by: r(K::Ruling, &id("ruling", "R1")) }, "Answered"), (ResolutionOutcome::Fixed { commit: sha(), by: None }, "Fixed"), (ResolutionOutcome::Deferred { to: other_run }, "Deferred"), diff --git a/crates/huginn-mind/src/wire.rs b/crates/huginn-mind/src/wire.rs index 5265c0d..6a4cd09 100644 --- a/crates/huginn-mind/src/wire.rs +++ b/crates/huginn-mind/src/wire.rs @@ -102,11 +102,10 @@ impl HuginnMindRequest { /// transport failure: the read side carries `Refused`, the write side carries /// the outcome's own `Refused`. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -#[allow(clippy::large_enum_variant, reason = "one answer per request; a document view is the answer a reader asked for")] pub enum HuginnMindResponse { Whoami(MindStatus), Admit(PipelineAdmissionOutcome), - View(Option), + View(Option>), Query(PipelineSelectionPage), Refused(MindRefusal), /// The answer did not fit one send and is being held for the client to diff --git a/crates/mind-body/tests/control.rs b/crates/mind-body/tests/control.rs index 8ab013e..a11068f 100644 --- a/crates/mind-body/tests/control.rs +++ b/crates/mind-body/tests/control.rs @@ -485,13 +485,15 @@ mod unsafe_installs { error.downcast::().expect("the refusal is the typed UnsafeStore error") } + type Case = (&'static str, u32, Option, Option, &'static str); + #[test] fn a_group_or_world_writable_directory_lock_or_store_is_refused_and_nothing_is_written() { if !running_as_root() { eprintln!("SKIPPED: needs root to own the fixtures"); return; } - let cases: [(&str, u32, Option, Option, &str); 5] = [ + let cases: [Case; 5] = [ ("world-writable directory", 0o777, None, None, ""), ("group-writable directory", 0o775, None, None, ""), ("world-writable lock", 0o755, Some(0o666), None, "control.cc.lock"), diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..8934eb4 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.95.0" +components = ["clippy", "rustfmt"] +profile = "minimal"