Skip to content

Case-study sweep: rocket-0.4 vendor, lockfile bumps, policy/cargo wiring#7

Merged
JustusAdam merged 13 commits into
mainfrom
updated-paralegal
May 13, 2026
Merged

Case-study sweep: rocket-0.4 vendor, lockfile bumps, policy/cargo wiring#7
JustusAdam merged 13 commits into
mainfrom
updated-paralegal

Conversation

@JustusAdam
Copy link
Copy Markdown
Collaborator

@JustusAdam JustusAdam commented May 11, 2026

Summary

Companion to brownsys/paralegal#195. Nine commits unblocking the case-study sweep against `nightly-2026-04-20`.

  • Migrate bench to local paralegal + bump toolchain (`8c97ed0`)
  • Bump time-0.3.x in case-study lockfiles (`a82aedc`)
  • Fix `email::my_send` argument type at websubmit `apikey.rs:95` (`f5f57be`)
  • Hyperswitch: drop `--rustc-reset-for-linux`; shim now handles trivial probes (`1f28906`)
  • Contile: bump ahash for nightly-2026-04-20 (`4a78f5b`)
  • Websubmit: include sibling cluster when filtering scopes for sink (`4e493d1`)
  • Bump case-study ahash 0.7.6 → 0.7.8 (`e0f918a`)
  • Plume: vendor conv 0.3.3 with a no-op std feature (`d42ff7a`)
  • Plume: vendor-and-patch rocket-0.4 stack for current nightly (`323ddaa`)
    • vendor/devise_core (drop `concat_idents!`)
    • vendor/traitobject (delete duplicate `Send+Sync` permutation impls)
    • vendor/rocket_http (drop hand-rolled `ToString for RawStr`)
    • vendor/rocket (gate `try_trait_v2_residual` + `Residual for Outcome<!, B, C>`)
    • num-bigint 0.4.3 → 0.4.6
    • drop hard `--abort-after-analysis` in plume's policy bin

TODO before merge

Test plan

  • Each case study's modified policy / lockfile / cargo-args path runs through `cargo run --release --bin ` end-to-end with the companion paralegal commits.
  • Plume: V0/V2 fail policy correctly (`Could not find a function deleting all types`), V1/V3 pass.
  • Websubmit, contile, lemmy, hyperswitch, freedit: status documented in `case-study-learnings.md`.
  • Reviewer: rerun against the post-#195 analyzer pin (after that PR merges and this PR's workspace deps are repointed).

🤖 Generated with Claude Code

JustusAdam and others added 13 commits May 9, 2026 22:47
…6-04-20

Workspace deps: switch from a pinned git rev (~48 commits behind the local
analyzer, references the renamed `paralegal-spdg` crate) to local paths,
aliasing the renamed crate via `package = "paralegal-pdg"` so policy code
keeps importing `paralegal_spdg::*`. **Must be repinned to a fresh git rev
before merge** — see project memory.

Toolchain: 1.75 → nightly-2026-04-20. Newer transitive deps (time-core,
etc.) require the edition2024 Cargo feature, stabilized only in 1.85+.
Aligning with the analyzer's nightly also keeps both sides on one toolchain.

API migration in policies/* and griswold/*:
- `Context` is now a trait; the concrete struct is `RootContext`. So
  `Arc<Context>`/`&Context` → `Arc<RootContext>`/`&RootContext`. The
  `Context` trait still needs to be in scope for `marked_nodes` etc.
- Crate rename `paralegal-spdg` → `paralegal-pdg`. Re-export path is now
  `paralegal_policy::paralegal_pdg::...`. Websubmit aliases the import
  (`paralegal_pdg as paralegal_spdg`) to avoid touching the rest of the
  file.
- `ControllerId` removed → `Endpoint` (aliased on import in freedit and
  websubmit).
- `SourceUse` removed; atomic's `is_argument` rewritten to use the target
  node's `is_arg: Option<u16>` instead of `EdgeInfo::source_use`.
  Semantics close but not identical — verify when running atomic.
- `NodeInfo::description` field moved into `NodeKind::Place { description }`;
  uses inside format strings now pass `NodeInfo` (which `impl Display`).
- `write_analyzed_code` gained a third `include_elided_code: bool` arg.
- `assert_error\!`/`assert_warning\!` insist on a literal `$msg`; freedit
  and websubmit calls rewritten to literal-format-string forms.

Stub: `griswold::output::add_policy_stat` reads several fields off
`ProgramDescription` that have moved to `paralegal_pdg::AnalyzerStats`
(loaded via `GraphLocation::stats_path()`); `dedup_*` were also renamed
to `pdg_*`. Those `set\!(...)` calls are stubbed to `0`/`Duration::default()`
with `TODO(migration)` markers; results.csv will have zeros in those
columns until someone wires up `AnalyzerStats::load(...)` in `Run::run`.

Bench-side: tolerate `alloc::alloc::exchange_malloc` going missing in the
websubmit baseline-external-annotations (the lang item moved on newer
nightlies). Marked `_internal_can_fail_resolve_silently = true`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The frozen lockfiles in mCaptcha, freedit, contile, and hyperswitch pinned
`time` 0.3.20-0.3.23, which fail to compile under nightly-2026-04-20 with
E0282 (type inference change). Ran `cargo update -p time` per case study
to bump `time` to 0.3.44/0.3.47 plus transitives (`serde`, `time-core`,
`time-macros`, `proc-macro2`, `quote`, `syn`).

Websubmit's lockfile had a smaller bump from the same workspace pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 3rd parameter of `email::my_send` is `&[String]`; this call site
passed `vec\![data.email.clone()]` (Vec<String>), causing rustc to fail
with `mismatched types`. Other call sites in `questions.rs` use
`&[recipient]` / `&recipients`. Add the `&` to deref-coerce
`&Vec<String>` → `&[String]`.

This was previously masked by `--abort-after-analysis` in the policy
framework (rustc halted before typeck on the SUT). Now that the abort
flag is a no-op (paralegal commit on `test-case-recheck`), the type
error has to be fixed in the SUT.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…robes

The historical workaround forced the analyzer's wrapped rustc to fall
back to the stock rustc on transitive build-script invocations. That was
needed because the rustc_driver-linked analyzer binary couldn't even
start when libLLVM wasn't on the loader path -- e.g. when a build script
ran `rustc -vV`.

Paralegal's CLI now splits into a thin launcher (plain rust binary, no
librustc_driver DT_NEEDED) and a renamed analyzer impl, so trivial rustc
invocations are intercepted before the LLVM-load failure. The
`--rustc-reset-for-linux` flag is gone; remove it here so hyperswitch
runs on the new launcher unmodified.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ahash 0.7.6 / 0.8.3 use the removed `stdsimd` feature, so the case-study
fails to compile on the current toolchain whenever the cached rmeta is
invalidated. Pinned to 0.7.8 / 0.8.11 via `cargo update -p ahash@0.7.6
--precise 0.7.8` and `cargo update -p ahash@0.8.3 --precise 0.8.11`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
check_authorized_disclosure called `influencers(sink_callsite, …)` and
filtered for the `scopes` marker. But `siblings(sink)` returns the
sink's call-site sibling CallArgument/Return nodes, and the `scopes`
marker (declared via `marker(scopes, arguments=[2])` on the sink-callee
`email::my_send`) lives ON the sibling itself — not on its
predecessors. `influencers` excludes the input node, so the filter
always missed the marker and the policy emitted
"Did not find any scopes for this sink".

Restore the missing `.chain(sink_callsite.iter_global_nodes())` — the
same form that existed on the `cross-crate-experiments` branch (commit
3cea0ec) but never landed on main.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ahash 0.7.6 unconditionally gates `feature(stdsimd)` (removed from
rustc in 2023), so case-study compiles against the analyzer's pinned
nightly-2026-04-20 toolchain fail with `unknown feature 'stdsimd'` at
ahash/src/lib.rs:33. 0.7.8's build script gates the cfg on
`version_check::Version::at_most("1.77.9")` and emits a clean cfg set
on current nightlies. Pulls once_cell 1.12.0 → 1.21.4 (and proc-macro
sundry) for lemmy / websubmit.

Plume's Cargo.lock additionally drops the `paralegal_dfpp_attr_macro`
unused dep — orthogonal cleanup that fell out of running cargo update
with the workspace's nightly toolchain.

Workspace Cargo.lock bumps from version = 3 to version = 4; tear out
the `bitvec` entry that the policy crate stopped depending on after
the contile shortest_path BFS unification (paralegal 79e467bc7).

Mirrors the earlier per-case-study bumps in 4a78f5b (contile) and
applies the same fix to the remaining three case studies. See
`case-study-cache-fragility.md` for why the cache hid this on the
2026-05-09 sweep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chomp 0.3.1 — pulled in transitively by `guid-create` (a plume-models
dep) — declares `conv = { version = "^0.3.3", features = ["std"] }`.
conv 0.3.3 has zero features defined; the `std` feature was removed in
a later refactor in upstream conv, so newer cargo refuses to resolve
the tree with `package 'chomp' depends on 'conv' with feature 'std'
but 'conv' does not have that feature`. plume's frozen Cargo.lock
pinned conv 0.3.3 specifically, so we can't bump conv either.

Vendor conv 0.3.3 verbatim under vendor/conv/ and add `default = ["std"]`
+ `std = []` (no-op — the feature gates nothing in conv's source).
Wire it in via `[patch.crates-io] conv = { path = "vendor/conv" }`.
Same-source patches are rejected by cargo, but a path patch satisfies
the resolver without behavioural change.

Note: even with this in place, plume still fails to compile on the
analyzer's pinned toolchain because `devise_core 0.2.1` (rocket 0.4's
proc-macro support crate) uses the removed `concat_idents\!` macro;
unblocking that requires a multi-week rocket 0.4 → 0.5 SUT rewrite and
is out of scope for the analyzer-sweep work. This patch stays in tree
so a future rocket-upgrade effort doesn't have to re-derive it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The case study compiles + analyzes + policies end-to-end now (V0/V2 fail
correctly, V1/V3 pass).

- vendor/devise_core: drop `concat_idents\!` (removed in 1.90.0); thread
  the default-fn ident through the `mappers\!` macro explicitly.
- vendor/traitobject: delete the three `Send+Sync`-permutation impls
  that modern rustc collapses to the same trait-object type.
- vendor/rocket_http: drop the hand-rolled `ToString for RawStr` that
  shadowed alloc's blanket impl without `default fn`. `RawStr: Display`
  already supplies the same behavior via the blanket.
- vendor/rocket: gate `try_trait_v2_residual` and add the missing
  `Residual<A> for Outcome<\!, B, C>` impl so the `Try` impl satisfies
  the new trait bound.
- Cargo.lock: num-bigint 0.4.3 -> 0.4.6 (0.4.3 hides TryFrom impls
  behind a `has_try_from` autocfg probe that the analyzer environment
  doesn't pass).
- policies/plume: drop `--abort-after-analysis`; it was reaching the
  plugin directly (bypassing the deprecated no-op wrapper) and stopping
  metadata emission, which broke the `plume` bin's `use plume_models`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each case-study run writes paralegal-artifact.json + flow-graph.stat.json
+ flow-graph.marker_stats.json into its source dir; plume's build.rs
also regenerates `case-studies/plume/po/` (the existing `/plume/po/`
rule didn't match that path).

Also ignore local /.claude/ harness settings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
paralegal removed both the --abort-after-analysis CLI flag and the
SPDGGenCommand::abort_after_analysis() SDK method. Strip the matching
call sites in the case-study policies, the raw flag in lemmy's
eval_driver, the now-dead app_config.abort knob in griswold, and the
stale references in the plume/atomic-server READMEs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JustusAdam JustusAdam merged commit 80466b5 into main May 13, 2026
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.

1 participant