Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions text/0000-crate-deletion-allowances.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
- Feature Name: N/A
- Start Date: 2026-03-11
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)

## Summary
[summary]: #summary

This RFC proposes adding a number of "reasonable changes" to the current crates.io deletion policy that will allow the deletion of several "reasonable to delete" crates which currently do not qualify.

See the [guide-level explanation](#guide-level-explanation) for the full list.

## Motivation
[motivation]: #motivation

[RFC 3660](https://rust-lang.github.io/rfcs/3660-crates-io-crate-deletions.html) currently details the requirements for deleting a crate which seem very reasonable:

* The crate has been published for less than 72 hours,
* or if all the following conditions are met:
Comment on lines +18 to +19
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it problematic to delete any crate with dependent crates, regardless of its age?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you read the rest of the RFC?

* The crate has a single owner,
* The crate is not depended upon by any other crate on crates.io (i.e. it has no reverse dependencies),
* The crate has been downloaded less than 100 times for each month it has been published.

However, there are a few obvious exceptions that could be added to this, based upon the RFC author's experience with attempting to delete some very old crates that should meet these requirements.

Specifically, those crates are:

* [bow](https://crates.io/crates/bow), which has been broken due to an incompatability hazard for almost a decade
* [value](https://crates.io/crates/value), which has a single reverse-dependency through a yanked version that almost certainly used it due to a typo

The additions from this RFC are directly inspired by these two examples, although they are also designed to apply as broadly as possible.

## Guide-level explanation (Proposal)
[guide-level-explanation]: #guide-level-explanation

The crate deletion criteria receives the following change, specifically regarding reverse dependencies which are considered by the deletion criteria:

* Yanked versions which are over a year old are not considered as valid reverse dependencies. If the depended crate passes the deletion criteria and gets deleted, these yanked versions may also get deleted.
Copy link
Copy Markdown
Member

@joshtriplett joshtriplett Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Yanked versions which are over a year old are not considered as valid reverse dependencies. If the depended crate passes the deletion criteria and gets deleted, these yanked versions may also get deleted.
* Yanked versions which are over a year old might not considered as valid reverse dependencies. This evaluation may take into account whether the dependency appears to be accidental/unused.

We should not be deleting old yanked versions of established crates; unless there's some malice involved, they should stick around for archival purposes. Also, consider that a crate might have a feature-flagged dependency using a feature that isn't intended for most people to use. I realize that "may also get deleted" is broad and subject to discretion, but I don't think we should leave that possibility open.

We could, potentially, say something like "If the depended crate passes the deletion criteria and gets deleted, that would be taken into account for any subsequent evaluation of the depending crate or its yanked versions."

Copy link
Copy Markdown
Contributor Author

@clarfonthey clarfonthey Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thought process here is to consider the case where only yanked versions contain the dependency: even just one non-yanked version having the dependency overrides this requirement and means that both versions remain.

That said, you're right that deleting the versions is probably excessive; we already have crates that might not compile on crates.io and that's fine, so, there's no harm in keeping yanked versions up. (I will edit that probably later today.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Have since updated the text to remove that bit.)

* If a version of a crate has been failing to compile on the latest stable for over 4 years (~1 edition cycle), it may be yanked without the approval of the crate author. Since these versions are necessarily at least four years old, they also satisfy the requirements for the above criteria.
Copy link
Copy Markdown
Member

@joshtriplett joshtriplett Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written, this criteria is much too broad. For instance, it's legitimate for a crate to only work on nightly, not on stable.

It seems like this is written in order to enable the previous requirement. But we shouldn't be force-yanking a crate version. We might, potentially want to ignore it for the purposes of evaluating the deletion criteria.

Suggested change
* If a version of a crate has been failing to compile on the latest stable for over 4 years (~1 edition cycle), it may be yanked without the approval of the crate author. Since these versions are necessarily at least four years old, they also satisfy the requirements for the above criteria.
* If a version of a crate has been failing to compile on the latest stable for over 4 years (more than a full edition cycle), it may be ignored for the purposes of evaluating reverse dependencies. This evaluation may take into account whether the dependency appears accidental/unused.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea behind yanking is that ultimately, the version does not compile, and so it's definitely doing something weird and obscure that probably doesn't apply any more. Given Rust's strong stability guarantees, this usually only happens for inference changes that have known-minimal breakages (meaning this was already evaluated to be within those known, minimal breakages) or explicit soundness issues, which again, would have already been evaluated.

And, we also can still keep yanked versions around, just, they've been signalled to not be recommended.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yanking versions that are broken on the default toolchain (latest stable) goes beyond what yanking has traditionally been for. There are legitimate reasons for a crate version to have a different toolchain in mind, such as latest nightly or fixed version/nightly.

Maybe it's relying on a feature that's on the path to stabilisation. This is the case with the Rust for Linux kernel crate for example, though that one isn't published to crates.io. Old versions with #![feature(...)] are going to fail to compile on stable, even when those features have been stabilised.

There are also crates that pin themselves to a certain version/nightly that's moved intermittently, usually because they rely on implementation details. The pinned version won't be the latest. I think this used to be (is?) the case for some crates in the formal verification ecosystem, but I don't recall the details. Force yanking old versions here might make it more difficult to verify old artifacts for projects that don't put Cargo.lock in version control.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right and I guess that we would have to pave a path specifically for allowing the current nightly if it turns out that a feature genuinely exists in the compiler for a full edition cycle, since it would still compile. I'll think a bit on how to word that.


The full deletion criteria becomes:

* The crate has been published for less than 72 hours,
* or if all the following conditions are met:
* The crate has a single owner,
* The crate has been downloaded less than 100 times for each month it has been published,
* The crate is not depended upon by any other crate on crates.io (i.e. it has no reverse dependencies), excluding yanked versions of crates that were published over a year ago
Comment thread
clarfonthey marked this conversation as resolved.
Outdated
Comment thread
kennytm marked this conversation as resolved.
Outdated

Similarly, a new policy is added, stating that:

* Any version of a crate which has been failing to compile on the latest stable version of Rust for over 4 years may be yanked without the approval of the crate author.

These changes effectively allow for long-broken crates and reverse dependencies due to mistakes to be still valid under the deletion criteria.

## Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

This section, for lack of anything better, will include extra comments on how these criteria will be implemented in practice.

In particular, the "not compiling on latest stable" requirement is effectively a catch-all for when a crate author is unavailable to yank a version, and would *always* be implemented as a manual override by crates.io staff. Since this kind of requirement would effectively only be used for passing the deletion criteria, it is very likely that the number of requests for this would be low; the requests will likely be even lower now that newer versions of cargo require that the crate compile before publishing, to avoid obvious mistakes.

The "yanked, older than a year" requirement should be easily doable with a PostgreSQL index, and since these reverse-dependents queries are run infrequently, it should be fine to implement into the existing code.

## Drawbacks
[drawbacks]: #drawbacks

The largest drawback is that this complicates the deletion criteria and thus makes it more difficult to understand.

## Rationale and alternatives
[rationale-and-alternatives]: #rationale-and-alternatives

The biggest motivation for this change is that it's simple and relatively uncontroversial. crates.io allows yanking but not unpublishing versions to help be a long-term archive of crate versions: if code was able to work before, it should be able to work now too, even if a version was yanked. However, the deletion criteria was developed explicitly to allow deleting "not very useful" crates, and it comes into obvious friction with yanked versions: a single accidental dependency can ruin a crate's opportunity to delete itself, and similarly, the crate versions that use these dependencies clearly did so by accident.

Cluttering the crates.io namespace with old, undesired crates helps nobody, and while there are obvious downsides to letting anyone delete whatever they want, hopefully, allowing a few more extra cases that preserve intent will be an overall improvement.

## Prior art
[prior-art]: #prior-art

* [`incoherent_fundamental_impls` lint](https://github.com/rust-lang/rust/issues/46205), which was directly linked to `bow` crate as an incompatibility. The crate published an empty latest version to avoid having to keep it on the crater exceptions list.
* [crates.io issue filed for `value` crate](https://github.com/rust-lang/crates.io/issues/12881), where the RFC author learned how a single yanked version depending on your crate can stop deletion entirely.

## Unresolved questions
[unresolved-questions]: #unresolved-questions

None currently.

## Future possibilities
[future-possibilities]: #future-possibilities

These are definitely not the only possible exceptions to the deletion criteria, although the emphasis on yanking can allow for more deletion opportunities if a creator explicitly yanks a version of a crate to allow this.