Skip to content

Remove support for serde - #212

Merged
jdno merged 1 commit into
mainfrom
remove-serde-support
Aug 21, 2026
Merged

jdno merged 1 commit into
mainfrom
remove-serde-support

Conversation

@jdno

@jdno jdno commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Cargo unifies features per package across the whole dependency graph, but a proc-macro crate emits its code into every crate that calls it. The serde feature therefore never stayed local to the crate that enabled it, and any crate sharing this instance received serde:: paths whether or not it depended on serde.

This is the defect behind jdno/labelflair#48. labelflair enables the feature; clawless uses this crate without it and has no serde dependency. While the two resolved to semver-incompatible versions Cargo kept them apart, but as soon as both reached 0.6.x they shared one instance and clawless stopped compiling:

error[E0433]: failed to resolve: use of unresolved module or unlinked crate `serde`
  --> clawless-0.4.0/src/context/current_working_directory.rs:4:1

I verified against a local checkout of that pull request, patched to this branch: clawless compiles and the whole labelflair suite passes.

What replaces it

The derives move to the call site, which the macros already forward:

name!(
    #[derive(serde::Deserialize, serde::Serialize)]
    LabelName
);

Nothing is lost. This works for all seven macros, and secret! takes #[derive(serde::Deserialize)] alone, as before.

The optional dependencies

secrecy, ulid, url and uuid move to dev-dependencies, and the four remaining features become plain markers that only decide which macros this crate exports. Those dependencies were never used by the macros. They existed to gate generated code and to propagate flags such as uuid?/serde, which has not reached a consumer since the second version of the feature resolver, so consumers already had to enable uuid/serde themselves. The tests declare them the way any consumer does.

This crate now depends on proc-macro2, quote and syn, and on nothing else.

The guard

just check-feature-unification runs cargo check --workspace --all-features, which builds tests/krate (which enables no features) against a fully featured build of this crate. It fails on main today, with the error above, and passes here. CI builds its matrix from just --list, so this becomes a job automatically.

Notes for review

  • Includes a fix for a regression I introduced in Rename and reorder the tests #211: the reorder script treated #[cfg(feature = "uuid")] use ... lines as test blocks and sorted them among the tests, leaving the imports and the type declaration below the tests in secret.rs, ulid.rs, url.rs and uuid.rs. It compiled, so the checks stayed green. Declarations are back at the top. Happy to split this into its own pull request if you would rather review it separately.
  • The feature powerset drops from 32 combinations to 16, and just check-features passes.
  • just pre-commit, just check-features and just check-feature-unification all pass. I could not run just check-unused-deps locally because cargo-udeps is not installed here, so that one is left to CI.
  • Breaking, like the SeaORM removal. Both belong in the same 0.7.0.

Cargo unifies features per package across the whole dependency graph,
but a proc-macro crate emits its code into every crate that calls it.
The `serde` feature therefore never stayed local to the crate that
enabled it, and any crate sharing this instance received `serde::` paths
whether or not it depended on serde. That is the defect that broke
labelflair, where one crate enabling the feature stopped an unrelated
dependency from compiling. A consumer who wants the derives now writes
them at the call site, which the macros already forward, so nothing is
lost.

The remaining optional dependencies move to dev-dependencies. This crate
never used them itself. They existed to gate generated code and to
propagate flags such as `uuid?/serde`, which has not reached a consumer
since the second version of the feature resolver, so consumers already
had to enable those features themselves.

The new recipe builds the test crate, which enables no features, against
a fully featured build of this crate. Any future feature that changes
generated code fails that check rather than somebody else's build.
@jdno jdno added the R-removed Add a now removed feature to the release notes label Aug 21, 2026
@jdno
jdno merged commit 2c57f18 into main Aug 21, 2026
22 checks passed
@jdno
jdno deleted the remove-serde-support branch August 21, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

R-removed Add a now removed feature to the release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant