Futures 0.2 has been moved to futures-preview


The latest release of the futures crate, 0.2, has been moved to futures-preview. Since we’re rapidly iterating on the futures library in order to integrate with the recently-landed async/await feature, 0.2 no longer represents the latest and greatest we have to offer, and isn’t expected to be a long-lived stable release. Users who want a stable version of futures that is compatible with tokio should continue using futures 0.1.

Users who want to stay on the bleeding edge of futures development should track to the futures-preview crate. Be on the lookout for the upcoming 0.3-alpha release of futures-preview, which will include compatibility with std::future::Future and async/await.

TL;DR: futures users who want a stable library with ecosystem interop should use 0.1. Users who want the latest and greatest should use futures-preview (currently 0.2, soon to be 0.3).

Where has futures 0.2.1 gone?

That all the futures 0.2 releases are yanked from crates.io is not really great and breaks the futures support in gtk-rs. That was built on top of 0.2 as the API of that version made it much easier to implement futures support (and an executor, it has nothing to do at all with the tokio ecosystem) around the GLib API.

What do you suggest as a solution for this other than simply removing futures support for the time being again?


The 0.2 release is still available. Rather than thinking of futures 0.2 releases as yanked, think of them as having moved to their “-preview” counterparts. For example, I see gtk is using futures-core 0.2, it’s now futures-core-preview 0.2.


While this is true, the crates were renamed and changes to at least the Cargo.toml have to happen. Code does not compile anymore without changes.

Also the -preview crates still don’t compile with the nightly feature with latest nightly, but that’s a separate problem.


I was specifically responding to this question

What do you suggest as a solution for this other than simply removing futures support for the time being again?

so I thought making the necessary changes to use the -preview crates was an acceptable solution since you would also need to update your code if you were to remove futures support.


Ah sure, that already happened in git now but it’s a bit suboptimal that stuff using existing releases is broken :slight_smile:


Existing binaries that keep a Cargo.lock file should continue working, since yanked crates are still hosted via crates.io-- they just won’t be offered in version resolution. I understand, though, that this doesn’t work as well for downstream libraries which didn’t keep a Cargo.lock. Sorry for the breakage to your libraries!


Sorry, but removal of dependencies from crates.io is not justifiable. All these arguments have been had in the Java community 15 or more years ago. This is why Maven Central and JCentre never allow removal of published dependencies. crates.io should follow the same policy.

Simply breaking people’s builds like this is the fastest way of really pissing people off.

To remove the artefacts and not update the cargo.io Web index and also to have the GitHub repository still tell people to use 0.2.2 amounts to bad DevOps.

All in all Rust does not need this sort of approach to managing published dependencies. Am I angry, yes. This is the Java dependency management fiasco all over again.


I cannot second Russel enough. Removing old versions and breaking people’s builds is completely unwarranted, and is very poor treatment of the Rust user base, IMHO (Rust will not be the most loved language for very long with this kind of mistreatment of its users). It’s a shame that cargo even allows that kind of action to take place, given the kind of widespread destruction such a careless, reckless, and irresponsible move can entail (as we see with this very poor, very nearsighted decision here with the futures crate).


@kitsuneninetails Keep in mind that there are valid use cases for yanking, e.g. if a package release has a big security hole in it. The thing which many are complaining about here is that in the case of futures 0.2, the yanking seemed unwarranted. It is unclear, at this point in time, how we could both allow legitimate yanking and forbid illegitimate yanking.


@HadrienG A major security hole is one reason I’d agree to pulling packages, true. In fact, when it became clear that the futures package was indeed yanked from crates.io, the very first question I asked was if it was due to a security vulnerability. It quickly became obvious that was indeed not the issue here, and the futures crate was instead yanked on an irresponsible whim.

As far as dealing with both circumstances, I’d say just have a tag on certain crates that they are dangerous or not available due to a security vulnerability (if researched and found by the broader community, or issued by the crate developer(s)), and then have certain cargo parameters to allow one to get around that restriction (command line params or what-not), but by default treat “insecure” crates as if they didn’t exist. That way default behavior is safe, but it is still possible to get around the lockout using advanced techniques.

And this way, no yanking is required, or at least yanking can then be made deliberately without impulsive decisions impacting thousands, if not tens of thousands, of loyal users.


Unmaintained software is a security risk. Yanking only impacts ongoing development, your free to lock onto the yanked package, just it’s not the easiest thing to create the lock file if you don’t already have it.


Lets yank half of the crates ecosystem then? I still think that yanking futures v0.2 and introducing futures-preview was a very strange move and even more importantly its motivation was not communicated at all. Why not just write in documentation and readme that if user does not want bleeding-edge futures v0.1 should be used? In my opinion the right thing to do will be to de-yank futures v0.2.


Agreed, in my head yank should look like this:

struct Yank {
    comment: String,
    redirect: Option<Crate,Version>

But both following the redirect or using the yanked crate should be possible without guru-level vodo.


@jonh I believe that shows a lack of confidence in developers to know what they are doing. Basically, much like how some highly-scorned OSs and apps will exhibit some very prosaic behavior and limit/omit anything that could be useful to advanced users because beginner users could make a mistake, castrating your packaging system and screwing over anyone who is relying on a set of packages (and who often cannot follow the cumbersome and impractical advice of “hanging to and not updating their Cargo.lock file”) for the sake of a small number of beginners who might not realize they are using an unmaintained package (especially if we are tagging and dating packages so everyone can see when the last update took place), is not good practice for building a community of trusting users, in my opinion.

Yanking only impacts ongoing development, your free to lock onto the yanked package, just it’s not the easiest thing to create the lock file if you don’t already have it.

Or if anyone else needs to pull that git repo and build the code, only they can’t because the Cargo file now points to a defunct, yanked package (with or without the Cargo.lock file). It’s just not practical nor does it solve or workaround the battery of problems that yanking a previously used package creates.

Yanking a package is essentially as bad or worse than force pushing a non-historic commit to github (worse in that, at least, github likely stores that old, force-pushed-over commit somewhere, whereas yanked packages are completely irretrievable). Anyone who WAS using that old commit is now SOL if they happen to clean, use a different account, or any of myriad possibilities where they cannot maintain a “locked, frozen” state indefinitely.


Some details about how yanking works, since it seems not everyone is aware of it:

  • Yanking does not delete any artifacts. It just toggles a flag in the index.
  • Yanked versions are still available to download.
  • If you obtain or manually create a Cargo.lock pointing to a yanked version, Cargo will automatically download that version from crates.io, just as if it were not yanked.
  • The only difference is that Cargo will no longer consider that version an option when updating that package or when generating a new Cargo.lock from scratch.

I’d still argue it’s best to yank a version only after publishing a new version that supercedes it. If there’s absolutely no way to publish a working version that’s semver-compatible with the yanked versions (e.g. if the API was fundamentally unsound and can’t be fixed without changes that break all consumers), it would still be a useful courtesy to publish a new version that does nothing but print a error message at build time explaining the situation.

In cases like futures, it might also make sense to publish version 0.3.0 which rolls back all the changes in 0.2 and just wraps the last 0.1 release. Then new users of the library will be directed to an appropriate version by default.


They can still build the code as long as the cargo file is there it will pick the same (yanked) dependency (see Matt’s reply above this message) and build the code no issue in that. Maybe cargo can emit a warning when the user is using a yanked version.


If your using [outside of a hobby] unmaintained libraries then you don’t know what your doing. This is an example of developers that know what they are doing. Your more likely to find there is a (substantial) security hold in some maintained package but the maintained package is considered secure as long as there is a channel to get a fix made.

The main advice is to switch packages or fork and take over maintenance. Locking is only if you want the quick way out.

Without the communication experienced professionals can be left in the dark.

The date gives no indication of security of a package.

git rebase is fun way to change history. Don’t rely on the cloud without backup.


If your using [outside of a hobby] unmaintained libraries then you don’t know what your doing.

Yes, that’s my point. Trust devs to know what they are doing instead of assuming they are bumbling around. Second, it is dangerous to make such a blanket statement without knowing individual contexts. Maybe some devs DO have a good reason to use unmaintained libraries and do understand what they are doing. Making absolutist rules is a quick way to fall into trouble when you find exceptions.

The main advice is to switch packages or fork and take over maintenance.

This seems even less practical than the Cargo.lock reconstruction idea.

Without the communication experienced professionals can be left in the dark.

Sure thing. My suggestion indeed focuses on using “communication” to solve problems rather than the blunt force trauma of deciding everyone’s crate availability policy for them.

The date gives no indication of security of a package.

In my post, I suggested using tagging and other communication mechanisms to let user’s know about the status of a crate, including the security status. I also suggested that packages marked as “insecure” or “yanked” still continue to not be included in the version search, rather just give devs a way to FORCE that inclusion (command line switch, etc.).


@mbrubeck & @dylan.dpc

Thank you both for the clarification. I was not aware of this, because my build just stopped working even though I had a Cargo.lock file already pointing to the old package. This led me to assume the package itself was also removed. I’m guessing something else happened in between which caused Cargo to clean the lock file and try to rebuild its dependency list (this happened to coincide with an outage in github and some of my deps were github dependencies…).

I think a warning about using yanked package is a great idea, but I think a command line switch, etc. to cargo to allow yanked packages to be considered in the dependency inspection would be helpful. I do still think default behavior should stay the same (exclude from dep search) for security and safety reasons, but it would be nice if we could force that package to be found so we could at least rebuild if we happened to clean out repo (for example, if we didn’t expect that the package was yanked), or someone else pulls our (private) code to collaborate, etc., just long enough to finish what we are doing and then find a path to upgrade the yanked package.

A hard stop in builds (due to Cargo not finding dependencies and being unable to reconstruct a Cargo.lock file on the fly) makes it difficult to even get to a stable point in my own code to even think about upgrading a random package I had no idea was going to suddenly be yanked, forcing an upgrade of code.

What are some downsides of adding a switch like this? Is it complicated to allow yanked packages to be included in the dep search? Or, are there worries that it can be abused/misused by people who don’t understand the full implications? Other concerns?


P.S. I also like the idea @mbrubeck suggested regarding this specific case of the futures crate. I think that would have been a big help to communicate what was going on.