Thoughts on aggressive deprecation in libstd

Basically the longer it takes to deprecate stuff, the greater number of code will exist that will be affected by deprecation changes.

I (and obviously a number of others) think there is a good middle ground where we can steer people away from using deprecated features (and effectively remove them from their reach if they want to use a given version) without ever breaking things.

Yes, it will have a cost for those maintaining std (in that public facing APIs must be kept effectively forever unless its inherent breakage outweighs the breakage from removing it), but the resulting stability will be oh so worth it.

that’s true. there are constructs which are legal in c++03 but not c++11, and so on

however, what you won’t find is some cutover point where with release 3.5 of gcc or 2008 of MSVC you can no longer use X but have access to Y. there’s no ā€˜x.0’ releases in the sense used by semantic versioning of libraries, where an api is removed or replaced - there are standard versions, which implementations support to greater or lesser degrees (sometimes dropping support for old ones, but not as an immediate transition!)

rustc is an implementation which also serves as its own specification. unless serving quite a different set of users, it won’t be possible for it to go 1.x->2.0 in the traditional semver sense - not without experiencing exactly the same adoption problems as, say, python 3.

once an implementation is used in industry then a long term requirement for that implementation is support of older unchanged code. i say requirement rather than e.g. good idea because if this is not done, people will simply never upgrade.

none of that makes deprecation a bad idea, btw. at minimum there’s always java style ā€œdeprecate without ever removingā€ and you surely don’t need to be as backward compatible as java.

however I don’t think it should be planned or its ā€˜aggressiveness’ measured with reference to some cutover semver-major breaking release. that’s a recipe to stall adoption or scare it away from ever occurring.

Just a reminder that I’ve set up RFC PR #1147 on rust-lang/rfc. So I invite all of you who want to discuss how rust should handle deprecation, please come over there. General (not rust-specific) discussion about deprecation can then continue here. Thank you!

1 Like

I haven’t read all of the comments so far, but I’m curious if using a different mechanism for avoiding warnings would be useful. The idea would be to have a targeted rust version specified for a program and have each deprecation list a rust version that it applies to and the warning would only be shown when the targeted rust version is less than or equal to the version that the deprecation applies to.

That would also allow the reverse, which is warning when using features that are newer than the desired version, though I understand that’s an entirely different consideration.

As I already answered on the RFC PR, this is already taken care of with #[unstable(...)].

It no longer compiles with older versions of rust.

That is a given, code written for 1.1 is not required to compile on 1.0. Or would you recommend post 1.0 never add new methods?

Oh, and just to be clear, I support aggressive deprecation. For example, I like the way the Lua designers deal with removing things from the library (i.e. they do it when required to make things better).

Lua has a very different set of needs. With Lua, it is expected that your code lives embedded in an application, and all given code targets the same version. Incidentially, this is why so many gaming shops are still running 5.0 or 5.1 (and IIRC, ScummVM bundles an even older Lua still).

With target version based deprecation, we can (mostly) have all versions of std side-by-side, which each library using the one most suited. This affords us the much of the same flexibility as the Lua authors, while removing most avenues for breakage.

This discussion has become quite quiet (now say that three times, fast!), meanwhile the discussion is raging over the first breaking change over at Niko’s RFC PR and elsewhere.

I hope to rectify this (and hopefully get you people back to this discussion, because it’s important for Rust’s future) and also give a small overview of the changes I made to my RFC PR since I wrote it to capture the spirit of the discussion here:

  • Deprecation and removal because of security considerations are separate concerns and should be handled separately. Therefore my RFC proposes an additional #[insecure(reason="...")] attribute that can be used to warn even when deprecation would otherwise be allowed.
  • The idea of opt-in/opt-out was brought up (also in other RFC PRs) and I included it unter alternatives. Seeing that the base idea is very useful (and has been thrown around here under python’s from __future__ import ... moniker (perhaps a bit one-sided, one could also concievably want to import from past :smile: ), I want to include it as part of the main proposal (but I want to think the consequences through and have an appealing syntax for it).
  • Some people suggested we use the current rust version by default if no target version is specified. I rejected this, because it would break all current code by default. However, this solution basically blesses 1.0 as the default version, which we may want to reconsider in the future (e.g. when 2.0 hits, we may want to change the default).

The solution which @nikomatsakis originally proposed was that calling rustc directly would default to the latest version (since usually one would be testing small bits of code and want the latest version), while running cargo on a crate with no version specified in Cargo.toml would default to 1.0 (for backward compatibility with existing published crates). Additionally, Cargo would automatically add a version specifier to all newly created crates (defaulting to the current version).

This seems like the most sensible approach to me, if we go with a version-based system.

2 Likes

Seems like a good idea – perhaps putting the target version into Cargo.toml is the better solution after all. I’ll try to think it through and update the RFC if apropos.

Update: I have extensively rewritten my RFC PR #1147. It now covers both language and API changes, uses a rust = "1.2.0" pseudo-dependency within cargo + a --target argument on rustc and removes the more complicated machinery.

I’m broadly in favour of aggressive deprecation (e.g. because Java’s libraries are huge and a mess of inconsistencies). But I’m less in favour of #[allow(deprecated)], except for use with specific features.

In my opinion, the compiler should output only something like this by default:

5 deprecated features used. Re-run with --show-deprecations for details.

If my RFC gets implemented, we won’t need deprecation warning shortcuts, because there should.not be too many of them.in the first place.

Your RFC covers a lot of ground. My point is that (non-security) deprecations shouldn’t be overlooked entirely, but are low-priority enough that it’s not worth throwing a lot of messages at the user immediately. A one-liner seemed like a good compromise.

1 Like

What i really hope is that the major libraries, say a java nio, swing or concurrent package equivalents are specifically developed out of tree, so that people are forced to pull them and they can’t complain about major redesigns. It’s over ten years after maven and ivy.

What if my build just took 30 seconds?

Yeah, what then?

I think if you replace seconds with hours we have a problem. But even then, using --explain like for other errors seems like a better option.

The real deprecation trouble in my experience doesn’t come from std apis, which are always extremely careful to do stuff gradually and often leave the (wrong) code in just for bad code to keep working badly (like Thread.stop).

It comes from essential libraries upgrades. If Cargo and Rust compiler and linker keep being robust enough to keep building old versions of popular libraries and those versions targeted to old-rust-whatever, keep being upgraded as Rust deprecates parts on tip and backports and using them even on modern rust keeps being possible, 99% of the pain of ā€˜deprecations’ will be a non-issue, just upgrade for the next minor version of the library. Ofc this kinda requires that libraries are careful of what interfaces/traits they expose and are especially careful not to expose external ones (more for other sub-libraries than Rust std lib). This in turn leads to duplicated code.

Anyway it would be helpful if crates.io had a ā€˜wall of shame’ for minor releases, something like ā€˜v0.4 of this library uses deprecated APIs: [list]’ warning in its page.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.