Skip to content

plan(v0.39): the rowan fork has a measured expiry, not a permanent one (REQ-350) - #932

Merged
avrabe merged 1 commit into
mainfrom
plan/req-350-rowan-watch-v2
Sep 10, 2026
Merged

plan(v0.39): the rowan fork has a measured expiry, not a permanent one (REQ-350)#932
avrabe merged 1 commit into
mainfrom
plan/req-350-rowan-watch-v2

Conversation

@avrabe

@avrabe avrabe commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

The rowan maintainer closed our #211 on 2026-09-07:

"We're about to rewrite rowan anyway and the new code should pass Miri (and is also a change of pretty much all code)."

That turns the fork from a permanent burden into one with a defined expiry, and the posture from maintaining to watching.

Two of our own notes were wrong

Corrected in Cargo.toml. There is no "Future Rowan" GSoC project — GSoC 2026's rust-analyzer project was "Migrating rust-analyzer assists to SyntaxEditor", the prerequisite, closed 2026-06-20 (#18285). The rewrite issue (#15710) has been open and untouched since 2024-09-02. The rewrite is landing as incremental breaking changes on master, not on a branch, with no announced date.

Measured on our own surface

Isolated worktree pinned to crates.io rowan 0.17.0 instead of the fork:

cargo check -p rivet-core   exit 0    ← compiles clean, no code changes
SB_EXIT=1   rowan-0.17.0/src/arc.rs:264      retag for SharedReadOnly, tag absent
TB_EXIT=1   rowan-0.17.0/src/cursor.rs:136   deallocation forbidden

Both reached via yaml_cst::parseparse_rootparse_block_mapping — a real consumer on ordinary construct-and-traverse, not rowan's own tests. SB site is the header-fattening cast of #108 (2021); TB site is #192's.

The fork earns its keep — dropping it turns the gate red under both models. And the rationale #211 was closed under ("rowan should pass Tree Borrows") does not hold for our usage on the current release.

The clean compile matters separately: the fork is not what keeps us on 0.16.x. rivet touches only the immutable core, untouched by #217's mutable-API removal.

Ecosystem context

Of 30 rowan consumers: zero carry a fork, zero execute rowan under Miri. rowan's own CI has no Miri job; rust-analyzer's covers only intern (no rowan). So this gate is a standard we hold, not shared pain we're fixing — defensible for a compliance tool, worth stating rather than assuming. cstree, a declared rowan fork with the same unsafe core, does run Miri under SB on three platforms and passes.

A second rowan problem

Raised as pulseengine/spar#446: rivet's default-on aadl feature pulls spar, and the lock carries two rowans — rivet forked 0.16.2, five spar crates unforked 0.16.1. Our gate covers yaml_cst/sexpr only, so spar's rowan is never interpreted. Framed as coordination, not a bug report — we have not tested whether spar's usage reaches the failing paths, and said so there.

Caveats on the artifact: nightly 2026-04-19 (~5 months stale), TB experimental. Re-run before citing upstream.

gate exit
fmt / clippy -D warnings (1.97.0) 0 / 0
cargo test --workspace 0 — 2368 passed
cargo test -p rivet-cli --test cli_commands 0 — 213 passed
validate / docs check / yamllint / diagnose_test.sh / cargo metadata 0

Refs: FEAT-001

…e (REQ-350)

The maintainer closed our rust-analyzer/rowan#211 on 2026-09-07 with "We're
about to rewrite rowan anyway and the new code should pass Miri (and is also a
change of pretty much all code)". That turns the fork from a permanent
maintenance burden into one with a defined expiry, and changes the posture from
maintaining to watching.

TWO OF OUR OWN NOTES WERE FACTUALLY WRONG and are corrected in Cargo.toml.
There is no "Future Rowan" GSoC project: GSoC 2026's rust-analyzer project was
"Migrating rust-analyzer assists to SyntaxEditor", the stated PREREQUISITE,
closed completed 2026-06-20 as rust-analyzer#18285. The rewrite issue itself,
rust-analyzer#15710, has been open and untouched since 2024-09-02. The rewrite
is landing as incremental breaking changes on rowan master — #213 tree-top,
#217 mutable-API removal, 0.17.0 on 2026-08-02, #219 trivia, #220 open — not on
a branch and with no announced date.

MEASURED ON OUR OWN SURFACE rather than on rowan's internals. An isolated
worktree pinned to crates.io rowan 0.17.0 instead of the fork:

  cargo check -p rivet-core   exit 0   compiles clean, no code changes
  SB_EXIT=1   rowan-0.17.0/src/arc.rs:264      retag for SharedReadOnly,
                                               tag absent from borrow stack
  TB_EXIT=1   rowan-0.17.0/src/cursor.rs:136   deallocation forbidden

Both reached through yaml_cst::parse -> parse_root -> parse_block_mapping, so
this is a real consumer failing on ordinary construction and traversal rather
than a synthetic exercise of rowan's own tests. The SB site is the same
header-fattening cast reported upstream as #108 in 2021; the TB site is #192's.

Two consequences. The fork earns its keep — dropping it today turns the Miri
gate red under BOTH aliasing models, not merely the stricter one. And the
rationale #211 was closed under, that rowan should pass Tree Borrows, does not
hold for our usage on the current release.

The clean compile matters separately: rivet touches only the immutable core and
none of the mutable API #217 removed, so the fork is NOT what keeps this project
on 0.16.x.

CONTEXT FROM AN ECOSYSTEM SURVEY: of 30 rowan consumers, zero carry a fork or
patch and zero execute rowan under Miri. rowan's own CI has no Miri job;
rust-analyzer's covers only the intern crate, which has no rowan dependency. So
this gate is a standard we hold rather than shared pain we are fixing — which is
defensible for a compliance tool, and worth stating rather than assuming.
cstree, a declared fork of rowan with the same unsafe core, does run Miri under
Stacked Borrows across three platforms and passes.

A SECOND ROWAN PROBLEM, raised cross-repo as pulseengine/spar#446: rivet's
default-on aadl feature pulls spar, and the lock carries two rowans — rivet on
the forked 0.16.2, five spar crates on unforked 0.16.1. Our Miri gate covers
yaml_cst and sexpr only, so spar's rowan is never interpreted. That issue is
framed as a coordination request, not a bug report, because we have NOT tested
whether spar's usage reaches the failing paths.

Caveats recorded on the artifact: toolchain is miri on nightly 2026-04-19,
roughly five months stale, and Tree Borrows is experimental and moves. Re-run
before citing upstream.

Confirmed with fmt 0, clippy 1.97.0 --all-targets -D warnings 0, cargo test
--workspace 0 (2368 passed), cargo test -p rivet-cli --test cli_commands 0
(213 passed), rivet validate 0, rivet docs check 0, yamllint 0,
diagnose_test.sh 0, cargo metadata 0. 319 artifacts, no duplicate ids.

Refs: FEAT-001
Trace: skip
@codecov

codecov Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

📐 Rivet artifact delta

Change Count
Added 1
Removed 0
Modified 0
Downstream impacted (depth ≤ 5) 0

Graph

graph LR
  REQ_350["REQ-350"]:::added
  classDef added fill:#d4edda,stroke:#28a745,color:#155724
  classDef removed fill:#f8d7da,stroke:#dc3545,color:#721c24
  classDef modified fill:#fff3cd,stroke:#ffc107,color:#856404
  classDef overflow fill:#e2e3e5,stroke:#6c757d,color:#495057,stroke-dasharray: 3 3
Loading
Added
  • REQ-350

📎 Full HTML dashboard attached as workflow artifact rivet-delta-pr-932download from the workflow run.

Posted by rivet-delta workflow. The graph shows only changed artifacts; open the HTML dashboard (above) for full context.

@avrabe
avrabe merged commit 32bf29e into main Sep 10, 2026
33 of 34 checks passed
@avrabe
avrabe deleted the plan/req-350-rowan-watch-v2 branch September 10, 2026 10:40
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