Skip to content
This repository was archived by the owner on May 14, 2026. It is now read-only.

fix(package-manager): link_hoisted_modules PkgIdWithPatchHash types#508

Merged
zkochan merged 1 commit into
mainfrom
fix/438-slice-5-pkgid-types
May 13, 2026
Merged

fix(package-manager): link_hoisted_modules PkgIdWithPatchHash types#508
zkochan merged 1 commit into
mainfrom
fix/438-slice-5-pkgid-types

Conversation

@zkochan

@zkochan zkochan commented May 13, 2026

Copy link
Copy Markdown
Member

Summary

Main is broken on d5b33e75 — Slice 5 (#505) merged with String for pkg_id_with_patch_hash types after #504 had already switched the underlying DependenciesGraphNode field to the PkgIdWithPatchHash newtype. The GitHub auto-merge didn't surface the type mismatch.

cargo check -p pacquet-package-manager on origin/main:

error[E0277]: the trait bound `String: Borrow<PkgIdWithPatchHash>` is not satisfied
   --> crates/package-manager/src/link_hoisted_modules.rs:255:56
error[E0308]: mismatched types
   --> crates/package-manager/src/link_hoisted_modules.rs:260:37
expected `String`, found `PkgIdWithPatchHash`

Fix

Switch the two slice-5-introduced surfaces to use PkgIdWithPatchHash:

  • CasPathsByPkgIdHashMap<String, _>HashMap<PkgIdWithPatchHash, _>. The CAS index now keys on the brand the graph node carries.
  • LinkHoistedModulesError::MissingCasPaths.pkg_id_with_patch_hashStringPkgIdWithPatchHash. Same type the graph node has, so the error round-trips the value without .to_string().

Tests updated to construct PkgIdWithPatchHash::from(...) keys/fields.

Test plan

  • All 8 linker tests pass on the fix branch.
  • just ready (893 tests, all green).
  • cargo doc --document-private-items, taplo format --check, just dylint clean.

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

Summary by CodeRabbit

  • Refactor
    • Updated internal package manager data structures to use a more consistent identifier format for package metadata. This improves alignment between different parts of the system handling package information.

Review Change Stack

The Slice 5 linker (#505) was written against `String` for
`pkg_id_with_patch_hash` and merged onto a main that had already
switched the underlying `DependenciesGraphNode` field to the
`PkgIdWithPatchHash` newtype (#504). The merge auto-resolved
without flagging the type incompatibility — `cargo check` on
main now errors with:

    error[E0277]: the trait bound
      `String: Borrow<PkgIdWithPatchHash>` is not satisfied
    error[E0308]: mismatched types
      expected `String`, found `PkgIdWithPatchHash`

Switch the two slice-5-introduced surfaces to match the newtype:

- `CasPathsByPkgId = HashMap<PkgIdWithPatchHash, HashMap<String,
  PathBuf>>` — the per-package CAS index now keys on the brand
  the graph node carries, matching the post-#504 invariant
  across the workspace.
- `LinkHoistedModulesError::MissingCasPaths.pkg_id_with_patch_hash:
  PkgIdWithPatchHash` — same type the graph node has, so the
  error round-trips the value without `.to_string()`.

Tests updated to construct `PkgIdWithPatchHash::from(...)`
keys/fields. All 8 linker tests pass on the fixed branch.

This unblocks main building again.
Copilot AI review requested due to automatic review settings May 13, 2026 23:03
@coderabbitai

coderabbitai Bot commented May 13, 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: ccc843c9-72db-4ceb-8344-2c76613f230e

📥 Commits

Reviewing files that changed from the base of the PR and between c546892 and ceac049.

📒 Files selected for processing (2)
  • crates/package-manager/src/link_hoisted_modules.rs
  • crates/package-manager/src/link_hoisted_modules/tests.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: copilot-pull-request-reviewer
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Dylint
  • GitHub Check: Lint and Test (windows-latest)
  • GitHub Check: Lint and Test (ubuntu-latest)
  • GitHub Check: Code Coverage
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Preserve existing method chains and pipe-trait chains; do not break them into intermediate let bindings unless there is a concrete justification such as a compilation failure, borrow checker rejection, meaningful performance improvement, or other technical necessity. Refactoring for style alone is not sufficient justification.
Choose owned vs. borrowed parameters to minimize copies; prefer borrowed types (&Path over &PathBuf, &str over &String) when it does not force extra copies.
Prefer Arc::clone(&x) and Rc::clone(&x) over x.clone() for reference-counted types to make the cost visible at the call site.
Do not use star imports inside module bodies. Write use super::{Foo, bar} instead of use super::*; for any glob whose target is a module you control. External-crate preludes (e.g., use rayon::prelude::*;) and root-of-module re-exports (e.g., pub use submodule::*; in lib.rs) are exceptions.
Follow Rust API Guidelines for naming, as documented in https://rust-lang.github.io/api-guidelines/naming.html.
Declare a newtype wrapper for any branded string type being ported from TypeScript pnpm. Do not collapse the brand into a plain String or &str; give the type its own struct so misuse is a type error.
When porting branded string types where upstream TypeScript always validates before construction, validate in the Rust port too. Construct the wrapper only via TryFrom<String> and/or FromStr; do not provide an infallible public constructor that takes an arbitrary string.
For branded string types where upstream TypeScript never validates (used purely for type-safety to prevent confusion between string slots), expose an infallible From<String> and From<&str> constructor in the Rust wrapper.
When upstream TypeScript occasionally constructs a branded type without validation (via bare as assertion), add a from_str_unchecked (or similarly named) constructor on the Rust side. Keep the validating constructor as well; `from_str_u...

Files:

  • crates/package-manager/src/link_hoisted_modules.rs
  • crates/package-manager/src/link_hoisted_modules/tests.rs
🧠 Learnings (5)
📚 Learning: 2026-05-07T23:19:08.272Z
Learnt from: KSXGitHub
Repo: pnpm/pacquet PR: 401
File: tasks/integrated-benchmark/src/work_env.rs:343-344
Timestamp: 2026-05-07T23:19:08.272Z
Learning: When reviewing Rust code in pnpm/pacquet for deprecated API usage, do not automatically treat `serde_saphyr::to_string` as deprecated. In `serde-saphyr` v0.0.25, `serde_saphyr::to_string` has no `#[deprecated]` attribute (the `#[deprecated]` later in `serde-saphyr-0.0.25/src/lib.rs` applies to a different function). Only flag `serde_saphyr::to_string` as deprecated if the resolved dependency version’s source shows `#[deprecated]` on that specific function.

Applied to files:

  • crates/package-manager/src/link_hoisted_modules.rs
  • crates/package-manager/src/link_hoisted_modules/tests.rs
📚 Learning: 2026-05-13T22:52:32.579Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 506
File: crates/package-manager/src/link_bins.rs:238-241
Timestamp: 2026-05-13T22:52:32.579Z
Learning: In Rust code using `matches!` (or `match`) on a borrowed value (e.g., `meta: &PackageMetadata` and a field access like `meta.resolution`), it is safe to use wildcard/OR patterns such as `LockfileResolution::Binary(_) | LockfileResolution::Variations(_)` when the pattern does not bind the inner payload by value. `_` wildcard patterns (and similar discriminant-only patterns) should not move non-`Copy` data; they only test the variant and avoid ownership transfer. Do not flag these patterns as move-out-of-borrow/ownership compile errors. Only patterns that bind the inner value by value (e.g., `LockfileResolution::Binary(b)`) would require ownership and may trigger move errors when matching on data behind a borrow.

Applied to files:

  • crates/package-manager/src/link_hoisted_modules.rs
  • crates/package-manager/src/link_hoisted_modules/tests.rs
📚 Learning: 2026-05-13T19:22:48.951Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 478
File: crates/package-manager/src/hoisted_dep_graph.rs:51-55
Timestamp: 2026-05-13T19:22:48.951Z
Learning: When reviewing this Rust codebase, avoid introducing/using a newtype like `PkgIdWithPatchHash` in only one module (e.g., `hoisted_dep_graph.rs`) if other related pacquet modules still represent the upstream pnpm “pkg id with patch hash” as a plain `String` (e.g., `virtual_store_layout`). For type consistency, either keep `pkg_id_with_patch_hash` as `String` here, or require a workspace-wide sweep that defines/extracts the `PkgIdWithPatchHash` newtype once and updates all call sites together (otherwise defer the refactor to a coordinated follow-up PR).

Applied to files:

  • crates/package-manager/src/link_hoisted_modules.rs
  • crates/package-manager/src/link_hoisted_modules/tests.rs
📚 Learning: 2026-05-13T20:09:22.171Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 486
File: crates/package-manager/src/hoisted_dep_graph.rs:472-476
Timestamp: 2026-05-13T20:09:22.171Z
Learning: In pnpm/pacquet, when generating serialized `hoisted_locations` strings (used for `.modules.yaml`), normalize path separators to forward slashes (e.g., replace `\\` with `/`). This preserves cross-platform portability: the output must not use OS-native separators because upstream pnpm’s `path.relative` can return platform-specific separators, which would break consistency with pnpm/pacquet’s other serialized formats on Windows.

Applied to files:

  • crates/package-manager/src/link_hoisted_modules.rs
  • crates/package-manager/src/link_hoisted_modules/tests.rs
📚 Learning: 2026-05-01T10:01:33.766Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 349
File: crates/reporter/src/tests.rs:121-121
Timestamp: 2026-05-01T10:01:33.766Z
Learning: In Rust test code, follow the repo’s CODE_STYLE_GUIDE test-logging rule: add logging (e.g., `eprintln!`/`eprintln!(...)`) so that useful diagnostic values are printed when a test fails, unless the assertion is `assert_eq!` (where the differing values are already included). Concretely, if you use assertions like `assert!`, `assert_ne!`, etc., ensure the test logs the relevant actual/expected values (or context) before/around the assertion so failures can be diagnosed without rerunning.

Applied to files:

  • crates/package-manager/src/link_hoisted_modules/tests.rs
🔇 Additional comments (2)
crates/package-manager/src/link_hoisted_modules.rs (1)

34-34: LGTM!

Also applies to: 55-55, 103-103

crates/package-manager/src/link_hoisted_modules/tests.rs (1)

13-13: LGTM!

Also applies to: 36-36, 101-101, 216-216, 220-220, 273-273


📝 Walkthrough

Walkthrough

The PR re-keys the CAS path index and error reporting in the hoisted-modules linker from String-based package identifiers to PkgIdWithPatchHash, a typed identifier. The type alias and error variant signature are updated in the main module, and all tests are migrated to construct and use the new type for CAS path keying and error assertions.

Changes

CAS Index Type Migration

Layer / File(s) Summary
CAS index API contract update
crates/package-manager/src/link_hoisted_modules.rs
Import PkgIdWithPatchHash, change CasPathsByPkgId type alias to key by PkgIdWithPatchHash instead of String, and update LinkHoistedModulesError::MissingCasPaths to store pkg_id_with_patch_hash: PkgIdWithPatchHash instead of String.
Test suite alignment
crates/package-manager/src/link_hoisted_modules/tests.rs
Import PkgIdWithPatchHash, update test helpers (make_node, flat_layout) and nested-hierarchy test to populate and key CAS path maps by PkgIdWithPatchHash::from(pkg_id), and adjust error assertion to expect the typed identifier.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • pnpm/pacquet#505: The main PR updates link_hoisted_modules's CasPathsByPkgId and LinkHoistedModulesError::MissingCasPaths to use PkgIdWithPatchHash keys/values instead of String, directly modifying the same linker API introduced in the retrieved PR.
  • pnpm/pacquet#504: The main PR continues the same migration introduced in #504 by switching link_hoisted_modules' CasPathsByPkgId key and MissingCasPaths payload from String to PkgIdWithPatchHash, now that the typed identifier exists.

Poem

🐰 A hash brings clarity to the fold,
PkgIdWithPatchHash replaces strings of old.
The linker's path now typed and true,
Tests dance along with this typed view! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: fixing type mismatches in link_hoisted_modules by switching to PkgIdWithPatchHash types.
Description check ✅ Passed The description comprehensively explains the bug context, the fix applied, and provides thorough test evidence, but omits the optional 'Linked issue' and 'Upstream reference' sections that are not required for bug fixes.
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 fix/438-slice-5-pkgid-types

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

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@zkochan zkochan merged commit 72fb61b into main May 13, 2026
10 of 14 checks passed
@zkochan zkochan deleted the fix/438-slice-5-pkgid-types branch May 13, 2026 23:07
@github-actions

Copy link
Copy Markdown

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.01     16.4±0.70ms   264.7 KB/sec    1.00     16.2±0.10ms   267.8 KB/sec

@codecov

codecov Bot commented May 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.58%. Comparing base (fa41850) to head (ceac049).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #508      +/-   ##
==========================================
- Coverage   88.74%   88.58%   -0.16%     
==========================================
  Files         124      125       +1     
  Lines       13429    13575     +146     
==========================================
+ Hits        11917    12026     +109     
- Misses       1512     1549      +37     

☔ 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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants