From 7171282b572ab15dd3ff807a583102390e685e9d Mon Sep 17 00:00:00 2001 From: Levi Neuwirth Date: Mon, 18 May 2026 11:38:57 -0400 Subject: [PATCH] Pin toolchain to 1.95.0 + mechanical clippy/rustc fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI was red on every recent main commit (pre-existing, not from the V0.2/audit work): the workflow installs rolling `stable`, which on the runners is ~1 year newer than the local toolchain that validated the code. Under `RUSTFLAGS: -D warnings` + `clippy -- -D warnings`, new rustc/clippy lints across pre-existing code became hard failures. Confirmed identical on the 4 commits before v1.0-rc (e.g. the `rope.rs:1076` unused_parens compile error is byte-identical there). Resolution: - `rust-toolchain.toml` pins channel 1.95.0 (the validated version). The repo directory override makes every cargo invocation use it regardless of what the CI action installs, eliminating the local/CI toolchain-drift class permanently. Bump deliberately. - Mechanical lint fixes (~17 sites, all the trivial/auto-fixable class — no logic change): `cargo clippy --fix` + `cargo fix` applied the machine-applicable set; hand-fixed the residuals: daemon.rs (duplicated #[allow]), completion_framework.rs (sort_by -> sort_by_key/Reverse), attach.rs (map().unwrap_or -> map_or, crdt), buffer.rs (is_some+expect -> match, crdt), m10_11_acceptance.rs (if -> match guard x2, crdt). - `cargo fmt --all` (clippy --fix left overlay_paint.rs unformatted). Verified clean under 1.95.0, all lanes: fmt 0 diffs; clippy --all-targets -D warnings clean for luajit, lua54, AND crdt; -D warnings build clean luajit+lua54; doc tests pass; lib 1223/0; autofix-modified tests (m7_5, m8_1 incl. the Finding-2 fs_watch fix) pass. Scope: this clears CI red class #1 (toolchain-gap lints) only. Independent and still triage-pending: #2 macOS F9 nix PeerCredentials portability (Test (macos-*)), #3 M1/M4/M6 perf/fuzz gates. Per plan, those are triaged after CI confirms #1 green. Co-Authored-By: Claude Opus 4.7 --- rust-toolchain.toml | 10 ++++++++++ src/attach.rs | 6 ++---- src/attach_reconnect.rs | 12 ++++++------ src/buffer.rs | 7 +++---- src/completion_framework.rs | 2 +- src/daemon.rs | 1 - src/daemon_attach.rs | 4 ++-- src/editor_core.rs | 2 +- src/file_io.rs | 3 +-- src/overlay_paint.rs | 28 +++++++++++++--------------- src/rope.rs | 2 +- tests/m10_11_acceptance.rs | 20 +++++++++----------- tests/m7_5_acceptance.rs | 2 +- tests/m8_1_acceptance.rs | 2 +- 14 files changed, 51 insertions(+), 50 deletions(-) create mode 100644 rust-toolchain.toml diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..78ba1ce --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,10 @@ +[toolchain] +# Pinned so local == CI permanently. The CI workflow installs the +# `stable` channel via dtolnay/rust-toolchain; this directory override +# makes every cargo invocation in the repo use the validated version +# regardless, eliminating the local/CI toolchain-drift class that +# silently red-lined CI under newer rolling-stable lints. Bump +# deliberately (its own validated cycle), never implicitly. +channel = "1.95.0" +components = ["clippy", "rustfmt"] +profile = "minimal" diff --git a/src/attach.rs b/src/attach.rs index 5dd522a..0b4fc59 100644 --- a/src/attach.rs +++ b/src/attach.rs @@ -803,8 +803,7 @@ pub(crate) fn run_attach_pair( if matches!(k.kind, KeyEventKind::Press | KeyEventKind::Repeat) { let timestamp_ns = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) - .map(|d| u64::try_from(d.as_nanos()).unwrap_or(0)) - .unwrap_or(0); + .map_or(0, |d| u64::try_from(d.as_nanos()).unwrap_or(0)); let pmacs_key = key_from_crossterm(k, assigned_id, timestamp_ns); // T M10.10 Day 3 step 5 Path β — determine @@ -985,8 +984,7 @@ fn forward_event( let _ = KeyModifiers::empty(); // import touch: keeps lint happy if unused let timestamp_ns = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) - .map(|d| u64::try_from(d.as_nanos()).unwrap_or(0)) - .unwrap_or(0); + .map_or(0, |d| u64::try_from(d.as_nanos()).unwrap_or(0)); let pmacs_key = key_from_crossterm(k, assigned_id, timestamp_ns); write_message(writer, &FrontendEvent::Key(pmacs_key))?; } diff --git a/src/attach_reconnect.rs b/src/attach_reconnect.rs index 702b5a0..0a0bbc4 100644 --- a/src/attach_reconnect.rs +++ b/src/attach_reconnect.rs @@ -322,11 +322,11 @@ mod tests { let mut s = BackoffSchedule::new(); let expected = [ Duration::from_millis(500), - Duration::from_millis(1000), - Duration::from_millis(2000), - Duration::from_millis(4000), - Duration::from_millis(8000), - Duration::from_millis(16000), + Duration::from_secs(1), + Duration::from_secs(2), + Duration::from_secs(4), + Duration::from_secs(8), + Duration::from_secs(16), Duration::from_secs(30), ]; for (i, &want) in expected.iter().enumerate() { @@ -366,7 +366,7 @@ mod tests { s.reset(); assert_eq!(s.next_delay(), Duration::from_millis(500)); - assert_eq!(s.next_delay(), Duration::from_millis(1000)); + assert_eq!(s.next_delay(), Duration::from_secs(1)); } #[test] diff --git a/src/buffer.rs b/src/buffer.rs index ce1a915..6b3b0e6 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -1050,10 +1050,9 @@ impl Buffer { let (lossy_owned, captured_crdt_op): ( Option>, Option>, - ) = if self.crdt.is_some() && !is_no_op_edit(current) { - Self::apply_to_crdt_then_normalize_bytes(self.crdt.as_ref().expect("checked"), current)? - } else { - (None, None) + ) = match (&self.crdt, is_no_op_edit(current)) { + (Some(crdt), false) => Self::apply_to_crdt_then_normalize_bytes(crdt, current)?, + _ => (None, None), }; // Stage 2: rope edit. In CRDT mode, the EditOp's byte payload diff --git a/src/completion_framework.rs b/src/completion_framework.rs index 31d8413..c16f6f3 100644 --- a/src/completion_framework.rs +++ b/src/completion_framework.rs @@ -295,7 +295,7 @@ impl CompletionRegistry { // the highest-priority hit. let mut order: Vec<&RegisteredProvider> = self.providers.iter().filter(|p| p.enabled).collect(); - order.sort_by(|a, b| b.priority.cmp(&a.priority)); + order.sort_by_key(|p| std::cmp::Reverse(p.priority)); let mut by_key: HashMap<(String, String), usize> = HashMap::new(); let mut out: Vec = Vec::new(); diff --git a/src/daemon.rs b/src/daemon.rs index 3e21ae4..31b08b7 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -798,7 +798,6 @@ fn per_attach_thread( clippy::needless_pass_by_value, clippy::too_many_lines )] -#[allow(clippy::needless_pass_by_value)] fn dispatcher_loop( dispatcher_rx: mpsc::Receiver, editor: &mut EditorState, diff --git a/src/daemon_attach.rs b/src/daemon_attach.rs index d1cb0d5..536be98 100644 --- a/src/daemon_attach.rs +++ b/src/daemon_attach.rs @@ -939,7 +939,7 @@ mod tests { let msg = format!("{err}"); assert!(msg.contains("/usr/local/bin/pmacs")); assert!(msg.contains("permission denied")); - assert!(msg.contains("PATH"), "should hint at PATH check: {msg}",); + assert!(msg.contains("PATH"), "should hint at PATH check: {msg}"); } /// F8 reproduction (M10.11 acceptance criterion 1, SSH transport). @@ -1017,7 +1017,7 @@ mod tests { .set_read_timeout(Some(Duration::from_secs(3))) .unwrap(); match output_reader.read_exact(&mut received) { - Ok(()) => assert_eq!(received, HELLO_FRAME, "Hello bytes corrupted in transit",), + Ok(()) => assert_eq!(received, HELLO_FRAME, "Hello bytes corrupted in transit"), Err(e) => panic!( "F8 reproduced: Hello never reached local output ({e}) — \ the bridge dropped the daemon→client direction on \ diff --git a/src/editor_core.rs b/src/editor_core.rs index 9ef8bea..52dda1c 100644 --- a/src/editor_core.rs +++ b/src/editor_core.rs @@ -323,7 +323,7 @@ impl EditorCore { #[must_use] pub fn active_buffer_len(&self) -> u64 { let id = self.active_buffer_id(); - self.registry.borrow().get(id).map(Buffer::len).unwrap_or(0) + self.registry.borrow().get(id).map_or(0, Buffer::len) } /// Active buffer's name. Returns an owned String to release the diff --git a/src/file_io.rs b/src/file_io.rs index c99217a..a462e9f 100644 --- a/src/file_io.rs +++ b/src/file_io.rs @@ -169,8 +169,7 @@ fn temp_sibling(target: &Path) -> PathBuf { // and `create_new` would error if hit. let nanos = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .map(|d| d.subsec_nanos()) - .unwrap_or(0); + .map_or(0, |d| d.subsec_nanos()); name.push(format!("{nanos:x}")); parent.join(name) } diff --git a/src/overlay_paint.rs b/src/overlay_paint.rs index 818dbdf..72ed9b4 100644 --- a/src/overlay_paint.rs +++ b/src/overlay_paint.rs @@ -249,21 +249,19 @@ fn paint_selection_in_window( break; }; match (disp.row as usize).checked_sub(window.view_top) { - Some(r) if r < inner_rows as usize => { - if disp.col < rect.size.cols { - let grid_row = rect.origin.row + r as u32; - let grid_col = rect.origin.col + disp.col; - if grid_row < grid.size.rows && grid_col < grid.size.cols { - let cell = grid.at(CellCoord::new(grid_row, grid_col)); - cell.style.underline = UnderlineStyle::Single; - // Use the source's color for the underline; if - // the cell already has a foreground style, the - // underline color comes from the fg. We don't - // override fg to preserve the cell's existing - // glyph appearance. - if cell.style.fg == Color::Default { - cell.style.fg = color; - } + Some(r) if r < inner_rows as usize && disp.col < rect.size.cols => { + let grid_row = rect.origin.row + r as u32; + let grid_col = rect.origin.col + disp.col; + if grid_row < grid.size.rows && grid_col < grid.size.cols { + let cell = grid.at(CellCoord::new(grid_row, grid_col)); + cell.style.underline = UnderlineStyle::Single; + // Use the source's color for the underline; if + // the cell already has a foreground style, the + // underline color comes from the fg. We don't + // override fg to preserve the cell's existing + // glyph appearance. + if cell.style.fg == Color::Default { + cell.style.fg = color; } } } diff --git a/src/rope.rs b/src/rope.rs index 1ea5164..d25aa16 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -1073,7 +1073,7 @@ mod tests { let pos = (rng() as usize) % (len + 1); let n = (rng() % 64 + 1) as usize; let bytes: Vec = (0..n) - .map(|i| ((rng() as u8).wrapping_add(i as u8))) + .map(|i| (rng() as u8).wrapping_add(i as u8)) .collect(); rope = rope.insert(pos as u64, &bytes).unwrap().new_rope; reference.splice(pos..pos, bytes); diff --git a/tests/m10_11_acceptance.rs b/tests/m10_11_acceptance.rs index 1938623..9ae61c1 100644 --- a/tests/m10_11_acceptance.rs +++ b/tests/m10_11_acceptance.rs @@ -252,17 +252,15 @@ impl Observer { InstanceMessage::BufferSnapshot { buffer_id, crdt_snapshot, - } => { + } if !self.replicas.contains_key(&buffer_id) => { // Bootstrap each buffer's replica on first // BufferSnapshot for that BufferId. Later snapshots // for the same buffer are ignored — the established // replica catches up via CrdtOps. - if !self.replicas.contains_key(&buffer_id) { - let r = CrdtState::new(self.frontend_id.0).expect("observer CrdtState::new"); - r.import_snapshot(&crdt_snapshot) - .expect("observer import_snapshot"); - self.replicas.insert(buffer_id, r); - } + let r = CrdtState::new(self.frontend_id.0).expect("observer CrdtState::new"); + r.import_snapshot(&crdt_snapshot) + .expect("observer import_snapshot"); + self.replicas.insert(buffer_id, r); } InstanceMessage::CrdtOp { buffer_id, op } => { // If we received a CrdtOp for a buffer whose snapshot @@ -279,10 +277,10 @@ impl Observer { } } } - InstanceMessage::PresenceUpdate { frontend_id, .. } => { - if frontend_id != self.frontend_id { - self.other_frontends.insert(frontend_id); - } + InstanceMessage::PresenceUpdate { frontend_id, .. } + if frontend_id != self.frontend_id => + { + self.other_frontends.insert(frontend_id); } _ => {} } diff --git a/tests/m7_5_acceptance.rs b/tests/m7_5_acceptance.rs index 61ae6a0..798d153 100644 --- a/tests/m7_5_acceptance.rs +++ b/tests/m7_5_acceptance.rs @@ -246,7 +246,7 @@ fn make_branched_package(name: &str) -> (TempDir, PathBuf, String) { ]); std::fs::write( work.join("init.lua"), - format!("return {{ name = '{name}', version = '1.0.0', flavor = 'feature' }}\n",), + format!("return {{ name = '{name}', version = '1.0.0', flavor = 'feature' }}\n"), ) .expect("write init.lua feature"); run_git(&[ diff --git a/tests/m8_1_acceptance.rs b/tests/m8_1_acceptance.rs index 9449202..5e5b899 100644 --- a/tests/m8_1_acceptance.rs +++ b/tests/m8_1_acceptance.rs @@ -121,7 +121,7 @@ fn read_dir_returns_one_entry_per_child_with_lstat_metadata() { if let Ok(err) = entries.get::("error") { panic!("read_dir errored: {err}"); } - let len: usize = entries.len().map(|n| n as usize).unwrap_or(0); + let len: usize = entries.len().map_or(0, |n| n as usize); assert_eq!(len, 3, "expected 3 entries, got {len}"); // Names are filesystem-iteration-ordered; gather and sort.