Skip to content

chore(pacquet/lint): more clippy#11839

Merged
KSXGitHub merged 6 commits into
mainfrom
claude/wizardly-pasteur-veS49
May 22, 2026
Merged

chore(pacquet/lint): more clippy#11839
KSXGitHub merged 6 commits into
mainfrom
claude/wizardly-pasteur-veS49

Conversation

@KSXGitHub

@KSXGitHub KSXGitHub commented May 21, 2026

Copy link
Copy Markdown
Contributor

Enable three clippy restriction lints workspace-wide via [workspace.lints.clippy] in the root Cargo.toml:

  • clone_on_ref_ptr — makes Arc::clone(&x) / Rc::clone(&x) mandatory at the call site. Same requirement perfectionist::arc_rc_clone was already enforcing via Dylint, so disable the perfectionist rule in dylint.toml and consolidate on clippy. The requirement now shows up under any cargo clippy run, not just the Dylint job. The "Cloning Arc and Rc" section of CODE_STYLE_GUIDE.md is updated to point at the clippy lint.
  • if_then_some_else_none — prefer x.then(|| ...) over if x { Some(...) } else { None }.
  • unnecessary_lazy_evaluations — pair with the above; use .then_some(...) / .then(fn_ref) when the value is trivial.

Turning on if_then_some_else_none surfaced seven pre-existing patterns across the workspace (cmd-shim, engine-runtime-node-resolver, executor, package-manager ×2, registry, resolving-deps-resolver ×2, resolving-npm-resolver). Each is rewritten to the lint-compliant form; all rewrites are pure desugarings, behavior unchanged.

Verified locally: cargo clippy --locked --workspace --all-targets -- --deny warnings, cargo fmt --check, taplo format --check, and cargo check --locked --workspace --all-targets all pass.


Written by an agent (Claude Code, claude-opus-4-7).

Summary by CodeRabbit

Release Notes

  • Chores
    • Enhanced code quality standards through workspace-wide Clippy lints.
    • Updated code style guidelines and linting configuration for consistency.
    • Refactored conditional patterns across the codebase for improved maintainability.

Review Change Stack

Wire `clone_on_ref_ptr`, `if_then_some_else_none`, and
`unnecessary_lazy_evaluations` into `[workspace.lints.clippy]` so they
fire under the existing `just lint` (`--deny warnings`) gate. The first
of these makes `Arc::clone(&x)` / `Rc::clone(&x)` mandatory at the call
site, which is what `perfectionist::arc_rc_clone` was already enforcing
via Dylint — consolidate on clippy and disable the perfectionist rule in
`dylint.toml` so the requirement lives in one place and shows up under
any `cargo clippy` run, not just the Dylint job. Update the
`Cloning Arc and Rc` section of `CODE_STYLE_GUIDE.md` to point at the
clippy lint.

Turning on `if_then_some_else_none` surfaced seven pre-existing
`if x { Some(...) } else { None }` patterns across the workspace.
Rewrite each to `x.then(|| ...)` (or, for the registry deprecation
visitor, `value.then(String::new)` to also satisfy
`unnecessary_lazy_evaluations`). The rewrites are pure desugarings;
behavior is unchanged.
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a0d04ab-a1de-4647-9268-9be6951fe7fb

📥 Commits

Reviewing files that changed from the base of the PR and between 15cf7f9 and 2186a1a.

📒 Files selected for processing (3)
  • pacquet/crates/engine-runtime-node-resolver/src/node_resolver.rs
  • pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs
  • pacquet/crates/resolving-npm-resolver/src/resolve_from_workspace.rs
✅ Files skipped from review due to trivial changes (1)
  • pacquet/crates/engine-runtime-node-resolver/src/node_resolver.rs
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Lint and Test (ubuntu-latest)
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Lint and Test (macos-latest)
  • GitHub Check: Lint and Test (windows-latest)
  • GitHub Check: Code Coverage
  • GitHub Check: Compile & Lint
🧰 Additional context used
📓 Path-based instructions (1)
pacquet/**/*.rs

📄 CodeRabbit inference engine (pacquet/AGENTS.md)

pacquet/**/*.rs: When porting a function that fires pnpm:<channel> events through globalLogger, logger.debug(), or streamParser.write(), mirror the call site, payload, and ordering so the reporter parses pacquet's NDJSON the same way it parses pnpm's.
Declare a newtype wrapper for branded string types. Do not collapse the brand into a plain String or &str.
If upstream always validates before construction, validate in pacquet's wrapper too. The wrapper must construct only via TryFrom<String> and/or FromStr. Do not provide an infallible public constructor.
If upstream never validates, just brand for type-safety. Expose an infallible From<String> (and From<&str> when convenient).
If upstream occasionally constructs without validation, expose from_str_unchecked as an escape hatch alongside the validating constructor.
Match upstream serde behavior for branded types that cross JSON, YAML, or INI boundaries. Use #[serde(try_from = "String")] for deserialization and #[serde(into = "String")] for serialization.
Use #[derive(derive_more::From)] and #[derive(derive_more::Into)] for mechanical conversion impls. Fall back to manual impl only when conversion needs custom logic.
String-literal unions should become enums, not newtype wrappers. Model closed sets of valid string values as enums.
Template literal types should be treated as branded strings with validation discipline from rules 2-5.
Choose owned vs. borrowed parameters to minimize copies. Widen to the most encompassing type (&Path over &PathBuf, &str over &String) when it doesn't force extra copies.
Prefer Arc::clone(&x) / Rc::clone(&x) over x.clone() for reference-counted types, so the cost is visible at the call site.
Follow Rust API Guidelines for naming conventions.
Do not use star imports inside module bodies. Write use super::{Foo, bar} instead of use super::*;. Two forms stay allowed: external-crate preludes like use rayon::prelude::*; and root-of-module re-...

Files:

  • pacquet/crates/resolving-npm-resolver/src/resolve_from_workspace.rs
  • pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs
🧠 Learnings (3)
📚 Learning: 2026-05-20T19:40:55.051Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11774
File: pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs:0-0
Timestamp: 2026-05-20T19:40:55.051Z
Learning: In the pacquet Rust code, ensure the semver implementation uses the `node-semver` crate (not `nodejs-semver`). `node-semver`’s public API does not include a `satisfies_with_prerelease`-style method; prerelease-tolerant matching should be implemented inline by first calling `Range::satisfies`, and when it rejects a prerelease version, retry matching against a stripped `MAJOR.MINOR.PATCH` base of the prerelease version.

Applied to files:

  • pacquet/crates/resolving-npm-resolver/src/resolve_from_workspace.rs
  • pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs
📚 Learning: 2026-05-22T00:08:44.646Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11837
File: pacquet/crates/resolving-npm-resolver/src/pick_package.rs:33-51
Timestamp: 2026-05-22T00:08:44.646Z
Learning: In the pnpm/pnpm repo’s pacquet Rust crates, do not flag Unicode ellipsis characters (U+2026, `…`) in Rust doc comments (`///` / `/** */`) as a lint violation. The pacquet crate’s `dylint.toml` only enables `perfectionist::derive_ordering`, and the Dylint `unicode-ellipsis` rule is not enabled for this project—so `…` in doc comments is an intentional, repo-consistent style.

Applied to files:

  • pacquet/crates/resolving-npm-resolver/src/resolve_from_workspace.rs
  • pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs
📚 Learning: 2026-05-20T23:07:58.444Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11784
File: pacquet/crates/resolving-deps-resolver/src/hoist_peers.rs:120-133
Timestamp: 2026-05-20T23:07:58.444Z
Learning: When reviewing code in this pacquet Rust port, follow the upstream pnpm compatibility rule: only match pnpm’s behavior exactly. Do not propose review changes that intentionally deviate from pnpm’s documented/observed behavior, even if pnpm appears buggy. If you identify a real bug in pnpm behavior, the review should prioritize fixing it upstream in pnpm first, and avoid implementing a pnpm-behavior workaround here unless the same fix has already landed upstream.

Applied to files:

  • pacquet/crates/resolving-npm-resolver/src/resolve_from_workspace.rs
  • pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs
🔇 Additional comments (2)
pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs (1)

34-34: LGTM!

Also applies to: 215-220, 311-311, 337-338, 362-362, 369-369, 410-410, 427-427, 443-445, 462-462, 497-497, 517-517, 572-573, 583-585, 587-587, 612-613

pacquet/crates/resolving-npm-resolver/src/resolve_from_workspace.rs (1)

224-225: LGTM!

Also applies to: 265-265


📝 Walkthrough

Walkthrough

This PR introduces workspace-level Clippy lints to enforce optional chaining patterns and Arc/Rc cloning idioms, then refactors eight implementation sites across the codebase to use .then(|| ...) instead of explicit if/else blocks returning Some/None.

Changes

Clippy Lint Configuration and Codebase Refactoring

Layer / File(s) Summary
Workspace Lint Configuration and Documentation
Cargo.toml, dylint.toml, pacquet/CODE_STYLE_GUIDE.md
Workspace Cargo.toml adds three Clippy lints (clone_on_ref_ptr, if_then_some_else_none, unnecessary_lazy_evaluations) at warn level. dylint.toml disables the equivalent perfectionist::arc_rc_clone check to avoid duplication. Code style guide updated to reference the new Clippy enforcement.
Codebase-wide Optional Chaining Pattern Refactors
pacquet/crates/cmd-shim/src/link_bins.rs, pacquet/crates/engine-runtime-node-resolver/src/node_resolver.rs, pacquet/crates/executor/src/lifecycle.rs, pacquet/crates/package-manager/src/create_virtual_store.rs, pacquet/crates/registry/src/package_version.rs, pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs, pacquet/crates/resolving-npm-resolver/src/resolve_from_workspace.rs
Eight locations refactored from explicit if/else blocks returning Some/None to boolean `.then(

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • zkochan

Poem

🐰 Clippy lints now guide the way,
with .then() patterns in play,
Arc and Rc stay close and true,
no more if/else—simpler to review! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'chore(pacquet/lint): more clippy' is vague and generic, using non-descriptive phrasing that doesn't convey the meaningful substance of the changes. Consider a more specific title that captures the main change, such as 'chore: enable clippy workspace lints and refactor conditional patterns' or 'chore(lint): enforce clone_on_ref_ptr and simplify if-then-some patterns'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/wizardly-pasteur-veS49

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Align the three lint keys to the longest key
(`unnecessary_lazy_evaluations`), which is what `taplo format` produces
under the workspace `.taplo.toml`. Caught by the `Format` CI job on the
previous commit.
Comment thread pacquet/CODE_STYLE_GUIDE.md Outdated
Comment thread Cargo.toml Outdated
Per review on #11839: the `[workspace.lints.clippy]` comment in
`Cargo.toml` and the "Cloning `Arc` and `Rc`" section in the style
guide don't need to mention the dylint-side disable — that detail lives
in `dylint.toml`, where it's locally relevant.
@github-actions

github-actions Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.00      8.4±0.42ms   515.8 KB/sec    1.00      8.4±0.54ms   514.7 KB/sec

@codecov-commenter

codecov-commenter commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.92308% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.55%. Comparing base (815e507) to head (2186a1a).

Files with missing lines Patch % Lines
pacquet/crates/cmd-shim/src/link_bins.rs 33.33% 2 Missing ⚠️
.../engine-runtime-node-resolver/src/node_resolver.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #11839   +/-   ##
=======================================
  Coverage   87.55%   87.55%           
=======================================
  Files         204      204           
  Lines       24394    24389    -5     
=======================================
- Hits        21358    21355    -3     
+ Misses       3036     3034    -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@KSXGitHub KSXGitHub marked this pull request as ready for review May 21, 2026 20:48
@KSXGitHub KSXGitHub requested a review from zkochan as a code owner May 21, 2026 20:48
Copilot AI review requested due to automatic review settings May 21, 2026 20:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens pacquet’s Rust linting by enabling additional Clippy restriction lints at the workspace level, and then updating existing code patterns across multiple crates to comply with the newly enabled lints while keeping behavior unchanged. It also consolidates the “Arc/Rc clone” enforcement onto Clippy by disabling the equivalent Perfectionist/Dylint rule and updating the style guide accordingly.

Changes:

  • Enabled clone_on_ref_ptr, if_then_some_else_none, and unnecessary_lazy_evaluations via [workspace.lints.clippy] in the root Cargo.toml.
  • Rewrote several if cond { Some(...) } else { None } patterns to cond.then(...) across affected crates.
  • Disabled perfectionist::arc_rc_clone in dylint.toml and updated CODE_STYLE_GUIDE.md to reference clippy::clone_on_ref_ptr.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pacquet/crates/resolving-npm-resolver/src/resolve_from_workspace.rs Replaces an if ... Some/None branch with .then(...) for Clippy compliance.
pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs Uses .then(...) for conditional alias propagation in peer resolution logic.
pacquet/crates/registry/src/package_version.rs Uses bool::then to encode deprecated boolean → Option<String> conversion.
pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs Gates lockfile construction with `.then(
pacquet/crates/package-manager/src/create_virtual_store.rs Refactors hoisted-mode optional CAS index assembly to `.then(
pacquet/crates/executor/src/lifecycle.rs Refactors conditional fallback install script selection to `.then(
pacquet/crates/engine-runtime-node-resolver/src/node_resolver.rs Uses `.then(
pacquet/crates/cmd-shim/src/link_bins.rs Uses `cfg!(windows).then(
pacquet/CODE_STYLE_GUIDE.md Updates guidance to reference the Clippy lint for Arc/Rc cloning.
dylint.toml Disables Perfectionist’s arc_rc_clone since Clippy now enforces it.
Cargo.toml Adds workspace-wide Clippy lint configuration for the newly enabled lints.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@KSXGitHub KSXGitHub enabled auto-merge (squash) May 21, 2026 20:55
@github-actions

Copy link
Copy Markdown
Contributor

Integrated-Benchmark Report (Linux)

Scenario: Frozen Lockfile

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 2.461 ± 0.096 2.323 2.619 1.01 ± 0.05
pacquet@main 2.434 ± 0.077 2.314 2.520 1.00
pnpm 4.829 ± 0.054 4.729 4.897 1.98 ± 0.07
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 2.46115845218,
      "stddev": 0.09555106799677077,
      "median": 2.47295701858,
      "user": 2.7105048199999997,
      "system": 3.7475204600000005,
      "min": 2.3229786930799996,
      "max": 2.61937797908,
      "times": [
        2.47971264008,
        2.4374201520799996,
        2.61937797908,
        2.56070228708,
        2.53211611508,
        2.4676834340799996,
        2.3603065320799996,
        2.3530560860799996,
        2.4782306030799996,
        2.3229786930799996
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 2.4337455323799992,
      "stddev": 0.07650717361742444,
      "median": 2.4363993320799997,
      "user": 2.7823518199999997,
      "system": 3.683980160000001,
      "min": 2.3139261300799996,
      "max": 2.5202091480799997,
      "times": [
        2.3641351330799996,
        2.4385420490799996,
        2.36864299308,
        2.51378347108,
        2.3139261300799996,
        2.5202091480799997,
        2.5097085840799997,
        2.5061942610799997,
        2.43425661508,
        2.3680569390799997
      ]
    },
    {
      "command": "pnpm",
      "mean": 4.82857822758,
      "stddev": 0.053746075677015386,
      "median": 4.83869240358,
      "user": 8.181519219999998,
      "system": 4.148016159999999,
      "min": 4.72913486008,
      "max": 4.89692366208,
      "times": [
        4.88135070008,
        4.84386708208,
        4.83351772508,
        4.84898585708,
        4.88133413708,
        4.72913486008,
        4.77520458308,
        4.81261805908,
        4.89692366208,
        4.78284561008
      ]
    }
  ]
}

Scenario: Frozen Lockfile (Hot Cache)

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 694.5 ± 25.7 675.7 765.7 1.00
pacquet@main 718.3 ± 51.7 685.4 854.1 1.03 ± 0.08
pnpm 2628.4 ± 181.0 2438.2 2956.3 3.78 ± 0.30
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.69454086166,
      "stddev": 0.02574221285905309,
      "median": 0.68899090776,
      "user": 0.4059614,
      "system": 1.55201028,
      "min": 0.67571437576,
      "max": 0.76566319676,
      "times": [
        0.76566319676,
        0.6904387777600001,
        0.6816029037600001,
        0.6824062107600001,
        0.69188370876,
        0.6948419107600001,
        0.67571437576,
        0.6935212927600001,
        0.6875430377600001,
        0.6817932017600001
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.7183406753600001,
      "stddev": 0.05167648093835655,
      "median": 0.6940961487600001,
      "user": 0.3912659,
      "system": 1.56262048,
      "min": 0.68543115476,
      "max": 0.8540975907600001,
      "times": [
        0.7260963147600001,
        0.6946236537600001,
        0.69356864376,
        0.7488235707600001,
        0.7073911637600001,
        0.6926858927600001,
        0.68543115476,
        0.8540975907600001,
        0.6881083507600001,
        0.6925804177600001
      ]
    },
    {
      "command": "pnpm",
      "mean": 2.6283746474600003,
      "stddev": 0.18100141326716326,
      "median": 2.54607030626,
      "user": 3.2167562999999992,
      "system": 2.1746878799999996,
      "min": 2.4382442007600003,
      "max": 2.95632711176,
      "times": [
        2.7999464887600003,
        2.53258608276,
        2.55284624976,
        2.8836934637600002,
        2.4941708837600003,
        2.4382442007600003,
        2.5681349357600003,
        2.51850269476,
        2.95632711176,
        2.53929436276
      ]
    }
  ]
}

Resolved two conflicts against upstream changes in
`perf(pacquet): close the warm-cache resolve gap to pnpm CLI` (#11837)
and `fix(installing.deps-resolver): deterministically order cyclic peer
suffixes` (#11826):

- `package-manager/src/install_with_fresh_lockfile.rs`: main dropped the
  `enable_global_virtual_store` conditional and now builds the lockfile
  unconditionally (renamed `layout_lockfile` → `built_lockfile`, added a
  tracing span). The clippy `if_then_some_else_none` rewrite this branch
  added to that block is no longer applicable — took main's version.
- `resolving-deps-resolver/src/resolve_peers.rs` (two sites): main
  changed `NodeId` from a `Copy` newtype to an `enum { Counter(u64),
  Leaf(Arc<str>) }`, so `Some(node_id)` had to become
  `Some(node_id.clone())`. Combined with this branch's
  `if_then_some_else_none` rewrite of the sibling `alias` field. The new
  `node_id.clone()` does not trip `clippy::clone_on_ref_ptr` because
  `NodeId` is an enum, not an `Arc`/`Rc`/`Weak`.

`engine-runtime-node-resolver/src/node_resolver.rs` and
`resolving-npm-resolver/src/resolve_from_workspace.rs` auto-merged; the
clippy fixes on those lines survived intact.

Verified locally: `cargo clippy --locked --workspace --all-targets -- --deny warnings`, `cargo fmt --check`, `taplo format --check`.
@KSXGitHub KSXGitHub merged commit d4136eb into main May 22, 2026
28 checks passed
@KSXGitHub KSXGitHub deleted the claude/wizardly-pasteur-veS49 branch May 22, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants