Skip to content

Commit 225e274

Browse files
ci: infra cleanup (MSRV + julia-cache + rustdoc + fmt) (#48)
## Summary Three-commit cleanup of pre-existing CI infrastructure debt that surfaced while merging #47. None of these touch product logic. - `ci(rust)`: bump MSRV `1.75 → 1.85` (Cargo.lock v4 needs ≥1.78) and `julia-actions/cache v2 → v3.1.0` (v2 pulled in the deprecated `actions/cache@0c45773b` and GitHub auto-fails such runs). - `docs(rustdoc)`: fix 20 `unresolved-link` errors that `RUSTDOCFLAGS=-D warnings` turns hard. Two patterns — math notation `k[vars]` / `w[n]` / `set[T]` etc. escaped to `\[...\]`; bracketed code spans like `` [`prover_kind`] `` whose target was not in scope had the brackets dropped (kept the code span). Files in `coprocessor/`, `provers/`, `disciplines/mod.rs`, `gnn/{client,guided_search}.rs`. - `style`: `cargo fmt --all` (150 files). Pure formatting; reproduce locally with `cargo fmt --all`. ## Test plan - [ ] CI green on this branch (Rust CI Test Suite / Documentation / Julia Integration / MSRV) - [ ] No diff vs `cargo fmt --all` after merge - [ ] `cargo doc --no-deps --all-features` clean with `RUSTDOCFLAGS=-D warnings` - [ ] Clippy still red — `cargo clippy --all-targets --all-features -- -D warnings` reports 29 errors (unused imports, dead code, idiomatic suggestions). Left for a follow-up; surface area is wider than this PR's scope.
1 parent d9b145d commit 225e274

157 files changed

Lines changed: 3056 additions & 2188 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

crates/echidna-core-spark/src/axiom_tracker.rs

Lines changed: 140 additions & 108 deletions
Large diffs are not rendered by default.

crates/echidna-core-spark/src/lib.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ use creusot_contracts::*;
7878
/// 3. **Reject caps at Level1** — `DangerLevel::Reject` input to
7979
/// [`compute_trust_level`] always yields `Level1`.
8080
/// Discharged by the `#[ensures]` on [`compute_trust_level`].
81-
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
82-
#[derive(serde::Serialize, serde::Deserialize)]
81+
#[derive(
82+
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
83+
)]
8384
pub enum TrustLevel {
8485
/// Large-TCB system, unchecked result, or uses dangerous axioms.
8586
Level1 = 1,
@@ -134,7 +135,11 @@ impl TrustLevel {
134135
ensures(result == a || result == b)
135136
)]
136137
pub fn min_level(a: TrustLevel, b: TrustLevel) -> TrustLevel {
137-
if a <= b { a } else { b }
138+
if a <= b {
139+
a
140+
} else {
141+
b
142+
}
138143
}
139144

140145
/// Returns the maximum (higher-trust) of two `TrustLevel` values.
@@ -151,7 +156,11 @@ impl TrustLevel {
151156
ensures(result == a || result == b)
152157
)]
153158
pub fn max_level(a: TrustLevel, b: TrustLevel) -> TrustLevel {
154-
if a >= b { a } else { b }
159+
if a >= b {
160+
a
161+
} else {
162+
b
163+
}
155164
}
156165
}
157166

@@ -171,8 +180,7 @@ impl std::fmt::Display for TrustLevel {
171180
/// A deliberately minimal enum that covers the distinctions the trust
172181
/// algorithm cares about without pulling in the full 105-variant
173182
/// `ProverKind` from the main `echidna` crate.
174-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
175-
#[derive(serde::Serialize, serde::Deserialize)]
183+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
176184
pub enum ProverClass {
177185
/// Small-kernel proof assistant (Lean4, Coq, Isabelle, Agda, Metamath,
178186
/// HOLLight, HOL4, Idris2, F*, Twelf, Nuprl, Minlog).
@@ -187,8 +195,7 @@ pub enum ProverClass {
187195
///
188196
/// This mirrors `TrustFactors` in `confidence.rs` but uses [`ProverClass`]
189197
/// instead of the full `ProverKind` enum, keeping the crate self-contained.
190-
#[derive(Debug, Clone)]
191-
#[derive(serde::Serialize, serde::Deserialize)]
198+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
192199
pub struct TrustFactors {
193200
/// Class of prover that produced the result.
194201
pub prover_class: ProverClass,
@@ -362,12 +369,10 @@ pub mod impl_invariants {
362369
// only exercised at test time — hence the allow.
363370
#[allow(unused_imports)]
364371
use crate::{
365-
TrustLevel, TrustFactors, ProverClass,
366-
combine_trust, clamp_trust, compute_trust_level,
367-
axiom_tracker::DangerLevel,
372+
axiom_tracker::DangerLevel, clamp_trust, combine_trust, compute_trust_level, ProverClass,
373+
TrustFactors, TrustLevel,
368374
};
369375

370-
371376
// -----------------------------------------------------------------------
372377
// Property: TrustLevel is totally ordered (Level1 < Level2 < … < Level5)
373378
// -----------------------------------------------------------------------
@@ -454,7 +459,10 @@ pub mod impl_invariants {
454459
for &c in &levels {
455460
let lhs = combine_trust(combine_trust(a, b), c);
456461
let rhs = combine_trust(a, combine_trust(b, c));
457-
assert_eq!(lhs, rhs, "combine_trust not associative for {a:?}, {b:?}, {c:?}");
462+
assert_eq!(
463+
lhs, rhs,
464+
"combine_trust not associative for {a:?}, {b:?}, {c:?}"
465+
);
458466
}
459467
}
460468
}
@@ -475,7 +483,7 @@ pub mod impl_invariants {
475483
fn po5_reject_danger_always_level1() {
476484
let factors = TrustFactors {
477485
prover_class: ProverClass::SmallKernel,
478-
confirming_provers: 10, // maximum cross-checking
486+
confirming_provers: 10, // maximum cross-checking
479487
has_certificate: true,
480488
certificate_verified: true,
481489
worst_axiom_danger: DangerLevel::Reject,
@@ -502,7 +510,7 @@ pub mod impl_invariants {
502510
has_certificate: true,
503511
certificate_verified: true,
504512
worst_axiom_danger: DangerLevel::Safe,
505-
solver_integrity_ok: false, // <-- integrity failure
513+
solver_integrity_ok: false, // <-- integrity failure
506514
};
507515
assert_eq!(
508516
compute_trust_level(&factors),
@@ -570,7 +578,7 @@ pub mod impl_invariants {
570578
/// for documentation purposes).
571579
#[test]
572580
fn po9_compute_trust_level_range() {
573-
use crate::axiom_tracker::DangerLevel::{Safe, Noted, Warning, Reject};
581+
use crate::axiom_tracker::DangerLevel::{Noted, Reject, Safe, Warning};
574582
use crate::TrustLevel::{Level1, Level5};
575583
let danger_levels = [Safe, Noted, Warning, Reject];
576584
let prover_classes = [

crates/echidna-core-spark/src/pareto.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,9 @@ pub fn weighted_rank(
331331
let score = |idx: usize| -> f64 {
332332
let c = &candidates[idx];
333333
trust_w * (c.objectives.trust_level.value() as f64)
334-
- time_w * (c.objectives.proof_time_ms as f64)
335-
- mem_w * (c.objectives.memory_bytes as f64)
336-
- steps_w * (c.objectives.proof_steps as f64)
334+
- time_w * (c.objectives.proof_time_ms as f64)
335+
- mem_w * (c.objectives.memory_bytes as f64)
336+
- steps_w * (c.objectives.proof_steps as f64)
337337
};
338338
let mut indices: Vec<usize> = (0..candidates.len()).collect();
339339
// Descending score — higher is better.
@@ -388,10 +388,7 @@ pub mod impl_invariants {
388388
for &m in &[0u64, 1024, 1 << 20] {
389389
for &s in &[0u64, 1, 100] {
390390
let o = obj(t, lvl, m, s);
391-
assert!(
392-
!dominates(&o, &o),
393-
"dominates is not irreflexive at {o:?}"
394-
);
391+
assert!(!dominates(&o, &o), "dominates is not irreflexive at {o:?}");
395392
}
396393
}
397394
}
@@ -494,12 +491,9 @@ pub mod impl_invariants {
494491
}
495492
}
496493
assert_eq!(
497-
cs[i].is_pareto_optimal,
498-
!dominated,
494+
cs[i].is_pareto_optimal, !dominated,
499495
"completeness violation at {}: optimal_flag={} but actually-dominated={}",
500-
cs[i].id,
501-
cs[i].is_pareto_optimal,
502-
dominated
496+
cs[i].id, cs[i].is_pareto_optimal, dominated
503497
);
504498
}
505499
}
@@ -518,8 +512,8 @@ pub mod impl_invariants {
518512
let n = cs.len();
519513
for i in 0..n {
520514
if !cs[i].is_pareto_optimal {
521-
let has_dominator = (0..n)
522-
.any(|j| j != i && dominates(&cs[j].objectives, &cs[i].objectives));
515+
let has_dominator =
516+
(0..n).any(|j| j != i && dominates(&cs[j].objectives, &cs[i].objectives));
523517
assert!(
524518
has_dominator,
525519
"dichotomy violation at {}: not optimal but no dominator",
@@ -535,7 +529,7 @@ pub mod impl_invariants {
535529
fn po_p7a_best_time_on_frontier() {
536530
use TrustLevel::*;
537531
let mut cs = vec![
538-
cand("fast", 10, Level1, 1_000_000, 1000), // best time
532+
cand("fast", 10, Level1, 1_000_000, 1000), // best time
539533
cand("trusted", 5000, Level5, 100_000, 50),
540534
cand("balanced", 1000, Level3, 200_000, 100),
541535
];
@@ -553,7 +547,7 @@ pub mod impl_invariants {
553547
use TrustLevel::*;
554548
let mut cs = vec![
555549
cand("fast", 10, Level1, 1_000_000, 1000),
556-
cand("trusted", 5000, Level5, 100_000, 50), // best trust
550+
cand("trusted", 5000, Level5, 100_000, 50), // best trust
557551
cand("balanced", 1000, Level3, 200_000, 100),
558552
];
559553
let _frontier = compute(&mut cs);
@@ -569,7 +563,7 @@ pub mod impl_invariants {
569563
use TrustLevel::*;
570564
let mut cs = vec![
571565
cand("fast", 10, Level1, 1_000_000, 1000),
572-
cand("lean_mem", 5000, Level3, 1, 50), // best memory
566+
cand("lean_mem", 5000, Level3, 1, 50), // best memory
573567
cand("balanced", 1000, Level3, 200_000, 100),
574568
];
575569
let _frontier = compute(&mut cs);
@@ -585,7 +579,7 @@ pub mod impl_invariants {
585579
use TrustLevel::*;
586580
let mut cs = vec![
587581
cand("verbose", 10, Level1, 1_000_000, 1000),
588-
cand("terse", 5000, Level3, 500_000, 1), // best steps
582+
cand("terse", 5000, Level3, 500_000, 1), // best steps
589583
cand("balanced", 1000, Level3, 200_000, 100),
590584
];
591585
let _frontier = compute(&mut cs);
@@ -602,9 +596,9 @@ pub mod impl_invariants {
602596
use TrustLevel::*;
603597
let cs = vec![
604598
cand("a", 100, Level2, 100_000, 10),
605-
cand("b", 200, Level5, 50_000, 5),
599+
cand("b", 200, Level5, 50_000, 5),
606600
cand("c", 300, Level3, 200_000, 50),
607-
cand("d", 50, Level1, 10_000, 1),
601+
cand("d", 50, Level1, 10_000, 1),
608602
];
609603
let ranked = weighted_rank(&cs, 1.0, 0.001, 0.0, 0.0);
610604
assert_eq!(ranked.len(), cs.len(), "length must equal input length");

crates/echidna-core/src/types.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,32 @@ pub struct Universe {
176176
impl Universe {
177177
/// Predicative cumulative `Type level`.
178178
pub fn ty(level: usize) -> Self {
179-
Self { level, cumulative: true, impredicative: false, homotopy_level: None }
179+
Self {
180+
level,
181+
cumulative: true,
182+
impredicative: false,
183+
homotopy_level: None,
184+
}
180185
}
181186

182187
/// Impredicative proposition universe (`Prop`).
183188
pub fn prop() -> Self {
184-
Self { level: 0, cumulative: false, impredicative: true, homotopy_level: Some(1) }
189+
Self {
190+
level: 0,
191+
cumulative: false,
192+
impredicative: true,
193+
homotopy_level: Some(1),
194+
}
185195
}
186196

187197
/// HoTT n-type universe at the given homotopy level.
188198
pub fn hott(level: usize, n: u8) -> Self {
189-
Self { level, cumulative: true, impredicative: false, homotopy_level: Some(n) }
199+
Self {
200+
level,
201+
cumulative: true,
202+
impredicative: false,
203+
homotopy_level: Some(n),
204+
}
190205
}
191206
}
192207

@@ -456,7 +471,12 @@ mod tests {
456471
#[test]
457472
fn hypothesis_with_type_info_roundtrips() {
458473
use crate::core::Hypothesis;
459-
let h = Hypothesis { name: "h".into(), ty: Term::Const("Nat".to_string()), body: None, type_info: Some(TypeInfo::new().with_multiplicity(Multiplicity::Linear)) };
474+
let h = Hypothesis {
475+
name: "h".into(),
476+
ty: Term::Const("Nat".to_string()),
477+
body: None,
478+
type_info: Some(TypeInfo::new().with_multiplicity(Multiplicity::Linear)),
479+
};
460480
let json = serde_json::to_string(&h).expect("serialize");
461481
assert!(json.contains("Linear"));
462482
let back: Hypothesis = serde_json::from_str(&json).expect("deserialize");

crates/echidna-mcp/src/main.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,14 @@ impl EchidnaMcp {
136136
stderr: String::new(),
137137
};
138138
return serde_json::to_string_pretty(&result).unwrap_or_default();
139-
}
139+
},
140140
};
141141

142142
let stdout = String::from_utf8_lossy(&output.stdout).into_owned();
143143
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
144144

145-
let verified = stdout.contains("\"level\": \"success\"")
146-
|| stdout.contains("\"level\":\"success\"");
145+
let verified =
146+
stdout.contains("\"level\": \"success\"") || stdout.contains("\"level\":\"success\"");
147147
let message = extract_first_message(&stdout).unwrap_or_else(|| {
148148
if stderr.is_empty() {
149149
"(no output)".to_string()
@@ -196,7 +196,7 @@ impl EchidnaMcp {
196196
stdout.trim().to_string()
197197
};
198198
CheckProverResult { available, message }
199-
}
199+
},
200200
Err(e) => CheckProverResult {
201201
available: false,
202202
message: format!("Failed to invoke echidna: {e}"),
@@ -224,7 +224,8 @@ impl EchidnaMcp {
224224
stdout
225225
} else {
226226
// Wrap plain-text listing as a simple result object.
227-
let lines: Vec<&str> = stdout.lines().filter(|l| !l.trim().is_empty()).collect();
227+
let lines: Vec<&str> =
228+
stdout.lines().filter(|l| !l.trim().is_empty()).collect();
228229
let provers: HashMap<String, String> = lines
229230
.iter()
230231
.map(|l| (l.trim().to_string(), String::new()))
@@ -235,20 +236,20 @@ impl EchidnaMcp {
235236
};
236237
serde_json::to_string_pretty(&result).unwrap_or_default()
237238
}
238-
}
239+
},
239240
Ok(output) => {
240241
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
241242
let result = serde_json::json!({
242243
"error": format!("echidna list-provers failed: {}", stderr.trim())
243244
});
244245
serde_json::to_string_pretty(&result).unwrap_or_default()
245-
}
246+
},
246247
Err(e) => {
247248
let result = serde_json::json!({
248249
"error": format!("Failed to invoke echidna: {e}")
249250
});
250251
serde_json::to_string_pretty(&result).unwrap_or_default()
251-
}
252+
},
252253
}
253254
}
254255
}

crates/echidna-wire/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ pub mod gnn_capnp {
3737

3838
// Ergonomic re-exports under shorter names.
3939
pub use common_capnp as common;
40+
pub use gnn_capnp as gnn;
4041
pub use proof_capnp as proof;
4142
pub use prover_capnp as prover;
42-
pub use gnn_capnp as gnn;
4343

4444
#[cfg(test)]
4545
mod smoke {
@@ -64,7 +64,10 @@ mod smoke {
6464
)
6565
.unwrap();
6666
let root = reader.get_root::<proof::proof_goal::Reader>().unwrap();
67-
assert_eq!(root.get_request_id().unwrap().to_str().unwrap(), "test-req-0");
67+
assert_eq!(
68+
root.get_request_id().unwrap().to_str().unwrap(),
69+
"test-req-0"
70+
);
6871
assert_eq!(root.get_schema_version(), 1);
6972
assert_eq!(root.get_timeout_ms(), 300_000);
7073
}

crates/typed_wasm/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,8 +1009,11 @@ region.get Small[99] .val
10091009
);
10101010
let analysis = analyse(VALID_TWASM, &ti).unwrap();
10111011
// No BoundsProof, NullSafe, EffectSafe, LifetimeSafe obligations
1012-
let levels: HashSet<SafetyLevel> =
1013-
analysis.obligations.iter().map(|o| o.level.clone()).collect();
1012+
let levels: HashSet<SafetyLevel> = analysis
1013+
.obligations
1014+
.iter()
1015+
.map(|o| o.level.clone())
1016+
.collect();
10141017
assert!(!levels.contains(&SafetyLevel::BoundsProof));
10151018
assert!(!levels.contains(&SafetyLevel::EffectSafe));
10161019
assert!(levels.contains(&SafetyLevel::Linear));

0 commit comments

Comments
 (0)