Warn against accidental use of 2015 edition?

Using 2015 edition by accident gives a very unpleasant experience to users, because code examples they copy fail to compile, tripping up on subtle differences in module paths and extern crates. For example:

a user has started a project using an innocent-looking template:

[package]
name = "hello-world-warp"
version = "0.1.0"

[dependencies]
warp = "0.1.18"

and got a super-confusing compile error with no hint of what is the real cause of failure.

I'm afraid that edition 2015 being the silent default, is going to haunt users forever, like the undead Quirks Mode of HTML.

Can this be helped?

For example, Cargo could warn if the edition key is missing in Cargo.toml, and there's no explicit opt-in from the user into the 2015 edition.

For recent compilers silencing this warning could be as easy as setting edition = "2015" in Cargo.toml. The only downside is for projects that insist supporting old Rust versions, including the few that recognize the edition key as unstable, and refuse to work.

So the "stop warning about 2015 edition" opt-in could be a flag in ~/.cargo/config instead, or a comment in Cargo.toml, or some key in metadata, or a command-line flag or something else.

16 Likes

If we guess that the lack of extern crate will be one of the first/most important things to trip folks up, we could also add some hints to the E0432 error message to help point people in the right direction?

On balance, I think it could make sense to warn-by-default on implicit edition at some point. It would be useful to know which was the first version of cargo to properly understand the edition key, so maybe we would wait until Debian stable has a new enough compiler?

1 Like

Great idea! The error messages about extern crates and missing modules could all warn about the 2015 edition, so only users who struggle with modules will be bothered with the warnings.

I'm not sure about the exact warning, but something like this:

^^^^ use of undeclared type or module `foo`
hint: this crate uses old module resolution rules from the Rust 2015 edition
2 Likes

Presumably this warning would only occur on the top-level crate, not on dependencies? (Much like other lints.)

Even then, though, this seems likely to bother a pile of people with existing crates that simply haven't been converted yet.

1 Like

That sounds like a great idea. We could also add hints to any other error related to behavior that has changed in the 2018 edition.

Debian 10 ("buster") shipped on July 6, and has a new enough rustc to understand the 2018 edition.

I've managed to add messages to E0432 and E0433 in the compiler.

Can you help me with the wording? I'm thinking about something along the lines of:

note: paths may not work as expected, because this crate has not enabled the 2018 edition

or

note: enable the 2018 edition to use the new crate and module resolution rules

1 Like

I like the idea of specific "did you mean to use 2018 edition?" lint hints, rather than warning about implicit 2015 edition as a whole.

The silent default here is indeed a bit frightening. Additionally, the issue at hand is important to solve, but are we looking past the heart of the issue?

Someone who doesn't understand what version to use is just going to slam in 2018 if it "shuts up" the compiler -- perhaps if it is implied that 2018 is the only version that is usable, then 2018 is the only version that should be used? To put that more bluntly -- would it be proper to move past warning and into the territory of assumptions? What is the case that someone would want the 2015 here and would --use-2015 not be a sufficient work-around for them, if they are of such expertise?

I only worry that we could give newbies the run around if we are simply having them tweak "magic numbers" in order to placate compilation "deficiencies" that they don't yet understand the nuances of. Where pathing may already be hard for a newbie, I wouldn't want to imply they should learn two styles and their differences before mastering one.

Truly I'm still new enough to the edition differences that I may be the theoretical user this issue and its solutions would take for a ride.

To return to topic, I find the second wording of "upgrade to use" a bit too passive and would prefer the warning of things "not working as expected". If that's what we're worried about, let's not obscure it.

Is there a reason we can't "just" make implicit extern crate prelude work in the 2015 edition? Or at the very least, give the 2015 edition that information such that it can actually say "you wanted an extern crate".

I think the ideal situation is that upon seeing something that would work in a non-2015 edition, the compiler in "default edition" mode has a good guess at what was intended, so can say how likely to fix it ("add an extern crate") and also give a "note: the language edition has been defaulted to 2015", which gives people something to Google.

1 Like

@ekuber probably has ideas about the specific wording...

I think I would prefer the more actionable/suggestive "enable the 2018 edition" with the more cautious "may" from the other version, since I'm pretty sure these errors could still happen for other reasons? I would consider giving a bit more context, maybe along the lines of:

"note: import resolution has changed from the default 2015 edition to the newer 2018 edition (check the package.edition field in your crate metadata). Enabling the 2018 edition may solve this problem."

1 Like

We actually do that for macros defined in 2015 edition and used from 2018 edition.
https://github.com/rust-lang/rust/pull/57745 implemented this for all 2015 code, but didn't found support among the lang team.

I really like this. We may have to support the flag being missing because of back-compat, but I don't think it's a hardship to ask that anyone explicitly choosing the old edition to say so. And it gives a nice teaching moment to link to the edition guide.

10 Likes

See also issue https://github.com/rust-lang/rust/issues/61914 for improving the error messages.

1 Like