Skip to content

fix(deps): bump heck 0.3 -> 0.5 to drop the unbounded edition2024 landmine - #4960

Open
Eras256 wants to merge 4 commits into
otter-sec:masterfrom
Prova-Solana:fix/heck-0.5-remove-edition2024-transitive
Open

fix(deps): bump heck 0.3 -> 0.5 to drop the unbounded edition2024 landmine#4960
Eras256 wants to merge 4 commits into
otter-sec:masterfrom
Prova-Solana:fix/heck-0.5-remove-edition2024-transitive

Conversation

@Eras256

@Eras256 Eras256 commented Aug 23, 2026

Copy link
Copy Markdown

What

anchor-syn, anchor-attribute-program, and anchor-lang-idl pin heck = "0.3" (unconditional dependency, used for CamelCase/SnakeCase/MixedCase identifier conversion in codegen and IDL generation). heck 0.3 depends on unicode-segmentation with no upper bound. unicode-segmentation has since shipped releases that require edition2024, which the SBF toolchain's bundled rustc can't parse — so a fresh anchor build/anchor test that resolves a newer unicode-segmentation hits a feature edition2024 is required failure that gives no hint it's actually about this dependency.

This exact failure has already been reported and root-caused twice (#4770, #4676), both closed without a fix landing for it specifically.

Fix

Bump heck 0.3 → 0.5 in the three crates above (heck 0.5.0 has zero dependencies, so this removes the unicode-segmentation edge outright) and in cli (still on 0.4.0, which keeps unicode-segmentation as an optional dep even though cli already uses the 0.5-compatible trait names).

This is not a version-only bump — heck 0.4 renamed every trait with a verbal prefix:

heck 0.3 heck 0.5
CamelCase / .to_camel_case() ToUpperCamelCase / .to_upper_camel_case()
SnakeCase / .to_snake_case() ToSnakeCase / .to_snake_case() (method name unchanged)
MixedCase / .to_mixed_case() ToLowerCamelCase / .to_lower_camel_case()

Updated the 19 call sites across the three crates accordingly, confirmed against heck's actual 0.3.3/0.5.0 source rather than by analogy.

Verification

  • cargo check/cargo test clean across the whole workspace (host toolchain), including anchor-syn --features idl-build and its idl_attributes / idl_qualified_builtins / program_parse suites.
  • Traced Cargo.lock before/after: heck no longer appears among unicode-segmentation's dependents. The one remaining unicode-segmentation edge comes from cli's TUI deps (ratatui/unicode-truncate), unrelated to the SBF build path this bug affects.
  • Compared heck 0.3.3 vs 0.5.0 output, not just the API surface, on 28 identifiers — Anchor-shaped names (record_attestations, AgentAccount, SPLToken2022, ...) plus known edge cases (digit-letter transitions per Letter after number in functions and parameters name cause typescript to have undefined behavior #3043, acronyms, leading/trailing underscores). One divergence out of 28: heck 0.5 treats . as a word boundary, 0.3 didn't. Anchor only ever calls these traits on strings already parsed as Rust identifiers by syn, which can't contain a literal ., so this divergence isn't reachable from any real Anchor program.

Didn't touch the resolver/MSRV-declaration proposal from #4770 — that's a separate, broader design decision. This PR is scoped to the one dependency edge that's concretely, currently causing the reported failures.


Disclosure: this PR was prepared with AI assistance (Claude), verified and reviewed by me before submission — see the commit trailer.

…dmine

anchor-syn, anchor-attribute-program, and anchor-lang-idl pin heck =
"0.3", an unconditional dependency used for CamelCase/SnakeCase/MixedCase
identifier conversion in IDL and codegen. heck 0.3 depends on
unicode-segmentation without an upper bound; unicode-segmentation has
since shipped releases that require edition2024, which the SBF
toolchain's bundled rustc can't parse. Any `anchor build`/`anchor test`
that resolves a fresh unicode-segmentation version hits a confusing
`feature edition2024 is required` failure that doesn't point back to
this dependency at all.

This exact failure mode has already been reported and diagnosed twice
(otter-sec#4770, otter-sec#4676), both closed without landing a fix for it specifically.
heck 0.5.0 has zero dependencies, so bumping it removes this landmine
outright instead of asking every downstream project to pin
unicode-segmentation by hand (as we've had to in our own program's
Cargo.toml).

The bump is not source-compatible: heck 0.4 renamed every trait with a
verbal prefix (CamelCase -> ToUpperCamelCase, SnakeCase -> ToSnakeCase,
MixedCase -> ToLowerCamelCase; method names follow the same rename
except to_snake_case, which is unchanged). Updated the 19 call sites
across the three crates accordingly - confirmed against heck's actual
0.3.3 and 0.5.0 source, not by analogy. Also bumped `cli`'s existing
heck 0.4.0 pin to 0.5, since 0.4 still carries unicode-segmentation as
an optional dependency and cli already uses the 0.5-compatible trait
names.

Verified before opening this PR:
- `cargo check`/`cargo test` clean across the whole workspace (host
  toolchain) with the new pins, including anchor-syn's idl-build
  feature and its idl_attributes/idl_qualified_builtins/program_parse
  test suites.
- Traced Cargo.lock's dependency graph before/after: heck no longer
  appears among unicode-segmentation's dependents. The remaining
  unicode-segmentation edge in the lockfile comes from cli's TUI deps
  (ratatui/unicode-truncate), unrelated to the SBF build path this
  bug affects.
- Compared heck 0.3.3 vs 0.5.0 output directly (not just the API
  surface) on 28 identifiers, including Anchor-shaped names and known
  edge cases (digit-letter transitions per otter-sec#3043, acronyms, leading/
  trailing underscores). One divergence: heck 0.5 treats `.` as a
  word boundary, 0.3 didn't. Anchor only ever calls these traits on
  strings already parsed as Rust identifiers by `syn`, which can't
  contain a literal `.`, so this divergence isn't reachable from any
  real Anchor program.

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 23, 2026

Copy link
Copy Markdown

@Eras256 is attempting to deploy a commit to the OtterSec Team on Vercel.

A member of the Team first needs to authorize it.

Eras256 added a commit to Prova-Solana/Prova that referenced this pull request Aug 23, 2026
PR #4960 (github.com/otter-sec/anchor/pull/4960) is real evidence of
ecosystem contribution regardless of review outcome, so it goes in
now rather than waiting on a maintainer response. Worded as "open,
pending review" in both languages on both pages — never "merged" or
"accepted" until it actually is one of those. Update the line if the
PR's status changes.
@swaroop-osec

Copy link
Copy Markdown
Collaborator

@Eras256 Can you please address the failed tests?

CI's cargo +nightly fmt -- --check was failing on 4 files touched by
the heck 0.3->0.5 bump: import ordering (heck's ToUpperCamelCase/
ToSnakeCase, anchor_derive_serde's __erase) and two lines that now
exceed the wrap width after the trait rename. No logic changes.

Co-Authored-By: Claude <noreply@anthropic.com>
@Eras256

Eras256 commented Aug 24, 2026

Copy link
Copy Markdown
Author

Pushed a fix — the failure was `cargo +nightly fmt -- --check` on 4 files touched by the heck bump (import ordering in `common.rs`/`lib.rs`, two lines that now exceed the wrap width after the trait rename in `entry.rs`/`instruction.rs`). No logic changes, verified `cargo +nightly fmt -- --check` passes clean and `cargo check` is green on the affected crates.

Looks like the new commit's CI runs are sitting in `action_required` — let me know if there's anything else needed on my end.

CI's Core Tests job (run 32757571224) still failed cargo +nightly fmt
-- --check after the previous formatting commit: this repo's floating
"nightly" toolchain resolves to whatever's current when the job runs,
and my local nightly (rustfmt 1.8.0-nightly, 2026-01-09) sorted this
import group differently than the nightly CI actually used. Updated
rustup nightly to the latest build (rustfmt 1.10.0-nightly, 2026-08-23)
to match, re-ran fmt over the whole workspace, and confirmed cargo
+nightly fmt -- --check is clean. Only this one line changed, back to
its original order.

Co-Authored-By: Claude <noreply@anthropic.com>
@Eras256

Eras256 commented Aug 24, 2026

Copy link
Copy Markdown
Author

Found it — thanks for pointing at the exact job. `lang/src/lib.rs:62` was the one line my previous fmt pass got backwards: my local nightly rustfmt (dated 2026-01-09) sorted `anchor_derive_serde::{...}` differently than the nightly this repo's CI resolves to at run time. Updated to the latest nightly (rustfmt 1.10.0-nightly, 2026-08-23) to match, re-ran `cargo +nightly fmt` over the whole workspace, confirmed `cargo +nightly fmt -- --check` is clean, and pushed (`53c86c58`) — that's the only line it touched, back to its original order.

@jamie-osec

Copy link
Copy Markdown
Collaborator

As a driveby cleanup, please move the heck dep to the workspace dep table.

Driveby cleanup requested by jamie-osec: heck was pinned to "0.5"
separately in anchor-syn, anchor-attribute-program, anchor-lang-idl,
and cli, instead of going through the workspace dependency table like
the other shared deps in the root Cargo.toml. Added heck = "0.5" under
"# Non solana crates" in [workspace.dependencies] and switched the 4
crates to reference it (heck.workspace = true / heck = { workspace =
true } to match each file's existing style, heck = { workspace = true,
optional = true } in anchor-lang-idl since it's gated behind the
`convert` feature there).

No version or resolution change — Cargo.lock is untouched.

Verified: cargo check --workspace and cargo test --workspace both
clean (the 4 debugger_symbol_resolution tests that need a working
local SBF toolchain were skipped — pre-existing environment issue,
librustc_driver-*.so missing / platform-tools install failure,
unrelated to this change); cargo +nightly fmt -- --check clean on the
first pass, no repeat of the nightly-version mismatch from the last
two pushes.

Co-Authored-By: Claude <noreply@anthropic.com>
@Eras256

Eras256 commented Aug 26, 2026

Copy link
Copy Markdown
Author

@jamie-osec Done — moved `heck` into `[workspace.dependencies]` (`heck = "0.5"`, alongside the other non-Solana shared deps) and switched `anchor-syn`, `anchor-attribute-program`, `cli`, and `anchor-lang-idl` to reference it (`heck = { workspace = true, optional = true }` in `anchor-lang-idl` since it's gated behind the `convert` feature there, matching each crate's existing style otherwise). No version/resolution change, `Cargo.lock` untouched. `cargo check`/`cargo test` clean across the workspace and `cargo +nightly fmt -- --check` clean before pushing (`c644c501`).

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.

3 participants