2021 edition?

Hmm... are we allowed to remove or change APIs? I understood this to be not allowed under edition changes. That said, it would be awesome if we could have "edition-deprecated" APIs in libstd where you can use the API until the deprecating edition (and after that, it's like it doesn't exist). And it would show up in the docs as "deprecated in edition 20XX" with a little caution sign or something.

1 Like

Some people say that an edition every 3 years is appropriate, but Rust 1.0 was released in May 2015, and Rust 1.31 in December 2018; that's more than 3.5 years. If we continued at this pace, the next edition would be released in 2022, but I don't think that we have to do that. Just release a new edition when it makes sense.

4 Likes

New lore -- Rust editions are 31 releases long, so the next edition at 1.62 will be due 2022-06-30.

27 Likes

So now one question remains: does anyone have a feature they want that would require new edition? Or would the edition be largely for the purposes of deprecating syntax?

4 Likes

There was some discussion about requiring unsafe {} blocks even in unsafe functions.

12 Likes

I'd like TryFrom, Path, PathBuf and HashMap in the prelude. These are the ones that keep annoying me all the time in all projects.

If stdlib could be edition-dependent, I'd like collect_vec() added (AFAIK it can't be done yet, because it'd conflict with itertools).

I'm actually not keen on removing any deprecated APIs or syntax. It would cause churn, and async has used up all of Rust's churn budget for the next decade.

14 Likes

It'd be a fun twist to release a Rust edition with literally no changes at all. Not even removing the deprecated stuff.

It could be used in Cargo.toml to just require a newer compiler version, and act like a tree ring that marks age of Rust crates.

12 Likes

I fully understand and respect this, especially the messaging part. However, we can either have some pain now, or more pain later. If we know for certain that something is deprecated, IMHO the sooner it's gone, the better. Otherwise we'll end up with projects that never quite get around to updating to current standards, but keep on being used (kind of like with banks and COBOL).

I'm completely comfortable with this but...

If we remove any features, even deprecated ones, then I consider that to be breaking change, which in my mind means that we need to make an edition release.

I fully agree with each of these points!

If that's what happens, just for the purpose of keeping the edition mechanism well-oiled I'm on board with it. I'd still prefer that we remove the deprecated stuff though... :wink:

This is actually a really important point. If it were possible to treat editions kind of like how we treat semver versions, then we have a number of interesting options:

  • Crates could easily state which ranges of editions that they work with.
  • crates.io could be modified to filter crates by the editions that they support.
  • A way of indicating that the crate is still maintained, even if only passively.

My feeling from this whole discussion is that the real concern is about messaging. If we didn't have to worry about messaging at all, then the concern about releasing a new edition would essentially go away.

So, assuming that a new edition does happen, what will the central message/theme for it be? My vote is 'Spring Cleaning'.

1 Like

The conflict is an allowable minor breaking change, otherwise std could almost never add anything for fear of conflicting with unknown user code. Of course, known conflicts are still weighed when considering such a change.

The more immediate problem for collect_vec() (or a defaulted collect<C = Vec>()) is that Vec doesn't exist when core::iter::Iterator is defined.

5 Likes

That's not really important.

Because of the way editions are set up, a compiler that can compile edition202a can also compile edition2018 and editon2015, and crates in any of these editions can seamlessly interoperate.

So a crate only has (or should have) one edition, because it doesn't matter to the outside world what edition it's on (other than compiler support). If a crate compiles identically on edition2015, edition2018, and edition202a, then it should pick the highest edition on the oldest compiler toolchain that it wants to support.

That said,

I kind of really like this idea.

For one, it really sends the message that editions aren't about breaking changes, that's just something they enable. Instead, they're about demarcating progress points of the compiler, and celebrating all of the progress that has been made in the past 3 years 31 releases.

It's sort of partway to the "suggested library LTS" MSRV proposals. Even if 3 years 31 releases is a long time back in terms of compiler support (and twice that is, well, twice that), an edition202a makes it a lot easier for crates currently supporting all the way back to pre-edition compilers to say that they now require 1.31 for edition2018 support.

That wouldn't be the advertised purpose of the edition, of course. But I think it would be a benefit of a new edition; it gives crates who care strongly about MSRV a way to actually communicate it to the compiler in a limited way.

RFC 2495 is a more appropriate way to do this, imo, and also allows for intra-edition MSRVs.

5 Likes

Yes, obviously a targeted MSRV support feature would be better for enforcing MSRV, especially if it participates in version selection. But I still think editions as the "LTS" side of MSRV does make some amount of sense informally. (i.e. a core library would be well served to say "I work with any compiler that supports edition20XY" as an easily understandable cutoff.)

For those unfamiliar with past MSRV+LTS discussions: One frequently raised issue was that we're missing an obvious default policy for what MSRV crates should target. Most crates don't change every 6 weeks, and don't want to limit their users that heavily, so "my MSRV is the latest stable version" typically isn't feasible. But going all the way back to an MSRV of 1.0 is also pretty extreme overkill. So in practice it feels like every crate has a different, almost random MSRV, if they even thought about it at all (although 1.13 seems to be a popular choice for the ? operator). Targeting the last edition's MSRV seems like a time interval that would be feasible for (actively maintained) crates to keep up with, would make most users happy, and is "obvious" enough that if we started recommending it the ecosystem would likely converge on it and reduce arbitrary MSRV conflicts.

FWIW, I think I'm officially off the fence now and leaning towards a "light edition" of some kind.

5 Likes

One thing that comes to mind, reading these discussions, is, do we know if we're solving any pain points here?

Aside from the mentions of TryFrom, std::prelude and deprecating trait objects, I'm seeing a lot of suggestions that are centered around "make this thing sound like it's new" without actually mentioning any user-land problem they're solving.

Eg it's unclear to me whether centralizing MSRV or "keeping the edition mechanism oiled" have any practical advantages at all.

5 Likes

We should seriously consider wether we want to reserve a few more keywords with the next edition, so we could use them for (potential) new features.

For example:

  • "gen" to mark generator functions and/or closures (similar to async)
  • "is" as an alternative to if let (there was a thread here recently)
  • "throw" or "raise" for error handling?
  • maybe a proper keyword for specialization (can't be default because of Default::default though)
  • I think there was some syntactic ambiguity with const generics, maybe a keyword could help?
  • ...

My point is not that we necessarily need all of those, but that we should carefully consider whether some might be useful for certain features. That doesn't mean that the final syntax or shape of those features should be decided now, but that we give ourselves some design space, for when it is time to stabilize those features. Otherwise the solution will probably be to use some sigils, which will risk turning Rust into more and more of a sigil soup.

I know that the Rust community usually rates semantics as more important than syntax, and that's fair enough, but Syntax is also really important since that is what we write and (more importantly) read every day.

A clean and intuitive syntaxis especially important when we want to grow our user base. Compare the popularity of Python vs Perl for an example.

This possibility is for me one of the best features of the edition system.

5 Likes

I do feel that this is a significant practical advantage:

  • in principle, editions are a hugely powerful tool which we might need some day (for example, when we try to cleanup macro hygiene some day)
  • unless we do editions regularly, doing one when we really need one would be painful, for the “test restoration from backups” reasons.

Additionally, promoting deprecations to removals also seems somewhat beneficial, as it keeps the language smaller.

3 Likes

It gets a little smaller for people learning Rust, assuming they only write in the new edition, but the compiler still has to deal with the old editions, as do proc-macros.

2 Likes
2 Likes

(At least currently,) library changes can't be gated on editions, just language changes. (There is some talk of "hiding" deprecated items when using higher than a certain edition.) But on top of that, trait impls don't even participate in stability currently, so they definitely aren't at a spot where edition gating could be added to them.

OK, so if I understand this correctly, rustc version 1.N is able to compile code that was able to be compiled by version 1.0 - 1.N, inclusive, correct? Is this a requirement for any conforming rust compiler? Put another way, if I decided to write a new rust compiler, but only wanted to support edition2021 forwards, would that be a non-conforming compiler because it couldn't compile code that was valid earlier on?

1 Like