From bde9865533a206beb02ce53750af847d0eed16e9 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 12 Jun 2026 13:39:00 +0000 Subject: [PATCH] chore(rust/clippy): enable allow_attributes Convert every #[allow] in the workspace to #[expect]. The conversion immediately paid for itself by surfacing four suppressions whose lint no longer fires: - resolve_peers: a too_many_arguments expect on a three-argument method (stale since a refactor) - removed. - resolve_peers: two dead_code expects on MissingPeerInfo fields the compiler considers used - removed. - tarball: fetch_and_extract_zip_once stacked two copies of the same too_many_arguments suppression - deduplicated. - ensure_file: a cfg_attr(windows, allow(unused)) on a mode parameter that IS used on Windows (via verify_or_rewrite) - removed. The remaining windows-side cfg_attr suppressions become expect with a reason, and fire correctly there (the parameters are genuinely unused on that cfg). --- Cargo.toml | 5 +++++ pacquet/crates/fs/src/ensure_file.rs | 10 +++++++--- pacquet/crates/fs/src/ensure_file/tests.rs | 2 +- pacquet/crates/fs/src/file_mode.rs | 2 +- pacquet/crates/package-manager/src/build_modules.rs | 2 +- .../package-manager/src/symlink_direct_dependencies.rs | 2 +- .../resolving-deps-resolver/src/resolve_peers.rs | 6 ------ .../crates/resolving-npm-resolver/src/pick_package.rs | 2 +- pacquet/crates/tarball/src/lib.rs | 8 ++------ pacquet/tasks/integrated-benchmark/src/cli_args.rs | 2 +- 10 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2837752ddd..be90defd31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -256,6 +256,11 @@ pathbuf_init_then_push = "warn" string_add = "warn" verbose_file_reads = "warn" +# attribute hygiene (restriction): #[expect] over #[allow], so a suppression +# whose lint stops firing surfaces as an unfulfilled-expectation warning +# instead of silently going stale. +allow_attributes = "warn" + [profile.release] opt-level = 3 lto = "fat" diff --git a/pacquet/crates/fs/src/ensure_file.rs b/pacquet/crates/fs/src/ensure_file.rs index 685c17df30..de35232759 100644 --- a/pacquet/crates/fs/src/ensure_file.rs +++ b/pacquet/crates/fs/src/ensure_file.rs @@ -166,7 +166,7 @@ pub fn ensure_parent_dir(dir: &Path) -> Result<(), EnsureFileError> { pub fn ensure_file( file_path: &Path, content: &[u8], - #[cfg_attr(windows, allow(unused))] mode: Option, + mode: Option, ) -> Result<(), EnsureFileError> { // See the "Process-local per-path mutex" bullet above and // [`cas_write_lock`] for the rationale. @@ -375,7 +375,8 @@ fn file_equals_bytes(file_path: &Path, content: &[u8]) -> io::Result { fn write_atomic( file_path: &Path, content: &[u8], - #[cfg_attr(windows, allow(unused))] mode: Option, + #[cfg_attr(windows, expect(unused, reason = "mode is only applied on POSIX platforms"))] + mode: Option, ) -> Result<(), EnsureFileError> { /// Retries after `AlreadyExists` on the temp path. Sixteen fresh /// counter values is plenty — under benign conditions we never @@ -515,7 +516,10 @@ fn rename_with_retry(src: &Path, dst: &Path) -> io::Result<()> { /// classifier is disabled and any `rename` error propagates /// immediately. fn is_transient_rename_error( - #[cfg_attr(not(windows), allow(unused, reason = "only inspected in the Windows branch below"))] + #[cfg_attr( + not(windows), + expect(unused, reason = "only inspected in the Windows branch below") + )] error: &io::Error, ) -> bool { #[cfg(windows)] diff --git a/pacquet/crates/fs/src/ensure_file/tests.rs b/pacquet/crates/fs/src/ensure_file/tests.rs index b777f8eab3..50eee844ea 100644 --- a/pacquet/crates/fs/src/ensure_file/tests.rs +++ b/pacquet/crates/fs/src/ensure_file/tests.rs @@ -73,7 +73,7 @@ fn missing_parent_dir_errors() { } /// Unix mode is honoured on the new-file path. Skipped on Windows -/// where the `mode` argument is `#[cfg_attr(windows, allow(unused))]`. +/// where the `mode` argument is only applied on POSIX platforms. /// /// Asserts the **owner** bits specifically rather than the full /// `0o777` triplet because `OpenOptionsExt::mode` runs through the diff --git a/pacquet/crates/fs/src/file_mode.rs b/pacquet/crates/fs/src/file_mode.rs index b9e1473333..93e43172d5 100644 --- a/pacquet/crates/fs/src/file_mode.rs +++ b/pacquet/crates/fs/src/file_mode.rs @@ -19,7 +19,7 @@ pub fn is_executable(mode: u32) -> bool { /// Set file mode to 777 on POSIX platforms such as Linux or macOS, /// or do nothing on Windows. -#[cfg_attr(windows, allow(unused))] +#[cfg_attr(windows, expect(unused, reason = "the file param is only touched on POSIX platforms"))] pub fn make_file_executable(file: &std::fs::File) -> io::Result<()> { #[cfg(unix)] return { diff --git a/pacquet/crates/package-manager/src/build_modules.rs b/pacquet/crates/package-manager/src/build_modules.rs index f6dd7ad638..fb209040a0 100644 --- a/pacquet/crates/package-manager/src/build_modules.rs +++ b/pacquet/crates/package-manager/src/build_modules.rs @@ -605,7 +605,7 @@ impl BuildModules<'_> { /// dispatch can call it once per chunk member. The body is the same /// as the pre-`#12` sequential loop — `continue`s become `return Ok(())` /// here. -#[allow( +#[expect( clippy::too_many_arguments, reason = "the parameters are independent inputs; bundling them into a struct would not improve clarity" )] diff --git a/pacquet/crates/package-manager/src/symlink_direct_dependencies.rs b/pacquet/crates/package-manager/src/symlink_direct_dependencies.rs index 0a42299fdd..3d14eb5935 100644 --- a/pacquet/crates/package-manager/src/symlink_direct_dependencies.rs +++ b/pacquet/crates/package-manager/src/symlink_direct_dependencies.rs @@ -373,7 +373,7 @@ pub(crate) fn importer_root_dir(workspace_root: &Path, importer_id: &str) -> Pat } } -#[allow( +#[expect( clippy::too_many_arguments, reason = "the parameters are independent inputs; bundling them into a struct would not improve clarity" )] diff --git a/pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs b/pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs index 24ce6a42b8..c0757f17b2 100644 --- a/pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs +++ b/pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs @@ -559,9 +559,7 @@ struct NodeRecord { /// directly, so neither field is read after construction yet. #[derive(Debug, Clone)] struct MissingPeerInfo { - #[allow(dead_code, reason = "future peersCache validation")] range: String, - #[allow(dead_code, reason = "future peersCache validation")] optional: bool, /// See [`crate::dependencies_graph::MissingPeer::meta_only`]. meta_only: bool, @@ -1129,10 +1127,6 @@ impl Walker<'_> { } } - #[allow( - clippy::too_many_arguments, - reason = "splitting these into a struct would only obscure the call site" - )] /// `true` when a missing-peer issue for `peer_name` under the /// given ancestor chain must not be emitted for the hoist input. /// See [`ResolvePeersOptions::hoist_missing_scope`]. diff --git a/pacquet/crates/resolving-npm-resolver/src/pick_package.rs b/pacquet/crates/resolving-npm-resolver/src/pick_package.rs index fad02d9537..283ce59644 100644 --- a/pacquet/crates/resolving-npm-resolver/src/pick_package.rs +++ b/pacquet/crates/resolving-npm-resolver/src/pick_package.rs @@ -681,7 +681,7 @@ pub async fn pick_package( /// Bundling these into a struct would just shuffle the same fields /// into a wrapper without removing any work; allowing the lint is /// the lower-noise option. -#[allow( +#[expect( clippy::too_many_arguments, reason = "bundling these independent inputs into a struct moves the fields into a wrapper without removing work" )] diff --git a/pacquet/crates/tarball/src/lib.rs b/pacquet/crates/tarball/src/lib.rs index fec657ba1f..c28b411d74 100644 --- a/pacquet/crates/tarball/src/lib.rs +++ b/pacquet/crates/tarball/src/lib.rs @@ -1828,7 +1828,7 @@ pub fn download_priority(unpacked_size: Option, file_count: Option // hinting, store_dir + retry_opts are install-scoped, and // ignore_file_pattern is the per-fetch archive filter. Bundling // into a struct would just push the same fields into a wrapper. -#[allow( +#[expect( clippy::too_many_arguments, reason = "the parameters are independent install-scoped inputs; bundling them into a struct only moves the same fields into a wrapper" )] @@ -2378,13 +2378,9 @@ fn manifest_package_id(manifest: Option<&serde_json::Value>) -> Option { /// `addFilesFromDir` does on each tempdir file). // 8 arguments — over the default clippy threshold, but each is // distinct (see the matching note on `fetch_and_extract_zip_with_retry`). -#[allow( - clippy::too_many_arguments, - reason = "the parameters are independent install-scoped inputs; bundling them into a struct only moves the same fields into a wrapper" -)] #[expect( clippy::too_many_arguments, - reason = "arg count is set by upstream pnpm's fetcher signature" + reason = "the parameters are independent install-scoped inputs; bundling them into a struct only moves the same fields into a wrapper" )] async fn fetch_and_extract_zip_once( http_client: &ThrottledClient, diff --git a/pacquet/tasks/integrated-benchmark/src/cli_args.rs b/pacquet/tasks/integrated-benchmark/src/cli_args.rs index 1bcc44db7e..8b05c3a24f 100644 --- a/pacquet/tasks/integrated-benchmark/src/cli_args.rs +++ b/pacquet/tasks/integrated-benchmark/src/cli_args.rs @@ -178,7 +178,7 @@ pub enum RegistryMode { // will stop firing once the `Hoisted*` and `Pnp*` linker buckets land. // Keeping the prefix is intentional — it mirrors the slug's leading // segment and makes the linker grouping legible in code. -#[allow( +#[expect( clippy::enum_variant_names, reason = "the shared `Isolated` prefix mirrors the scenario slug and keeps the linker grouping legible; it stops firing once other linker buckets land" )]