rust-lang / edition-guide Goto Github PK
View Code? Open in Web Editor NEWA guide to changes between various editions of Rust
Home Page: https://doc.rust-lang.org/nightly/edition-guide/
License: Apache License 2.0
A guide to changes between various editions of Rust
Home Page: https://doc.rust-lang.org/nightly/edition-guide/
License: Apache License 2.0
The section "At most one repetition" does not specify a minimum Rust version. On the latest stable (rustc 1.31.0 (abe02cefd 2018-12-04)
), the operator is still unstable:
error[E0658]: using the `?` macro Kleene operator for "at most one" repetition is unstable (see issue #48075)
A comment on the PR adding the section suggests that the operator will actually be added in 1.32. If so, a badge should be added to the section.
We have the text "For example, async/await is available in Rust 2018, but not Rust 2015." in https://rust-lang-nursery.github.io/edition-guide/editions/transitioning.html#prepare-for-the-next-edition
But the Feature Status (https://rust-lang-nursery.github.io/edition-guide/2018/status.html) shows it as not yet available
In the more details part of the section about dyn Trait
(3.45) it is told that impl Trait
is explained in the next section, which is wrong, as it actually is in 3.39.
That should be updated or reordered.
Open https://rust-lang-nursery.github.io/edition-guide/introduction.html in a mobile browser like Android Chrome or Firefox Mobile.
Well-formatted page with discoverable navigation.
Tried it in Fixefox Android 60.0.2 and Android Chrome 67.0.3396.87.
Section 3.1.4.1 says "Therefore, starting with edition 2018, it is deprecated, for non-reference-types (types other than & and &mut), to leave of the lifetime parameters. "
The of
should be off
.
The above is all you need to know to get going with
impl Trait
, but for
some more nitty-gritty details: type parameters are universals,impl Trait
are existentials. Okay, maybe that's a bit too jargon-heavy. Let's step back.
This paragraph could be a bit confusing, as arg: impl Trait
constitutes universal quantification.
Maybe start with @steveklabnik's text here: https://news.ycombinator.com/item?id=16552515
We should eventually move the guide out of the https://rust-lang-nursery.github.io/ URL and give it a more official-looking, short and sweet URL instead.
We decided that we will punt on this for Preview 2; but we should do this for Release Candidate 1.
A suggested URL for the whole edition is https://rust-lang.org/edition/ and https://rust-lang.org/edition/2018/ then goes to the 2018 page.
We can also move it to https://docs.rust-lang.org/edition/
Some of the changes described in guide are already stable and available in current Rust without having to opt-in, such as default match bindings, and ?
support in main and tests.
So I was thinking: should these changes (or perhaps all changes described) mention the version as of which they're available?
From the Macro Changes site:
Note that you'll still need
#[macro_use]
to use macros you've defined in your own crate; this feature only works for importing macros from external crates.
Some questions that immediately came to mind:
I propose that we discuss slice patterns in the edition guide;
While it wasn't originally thought of as an edition feature, it was stabilized in 1.26, the same time as impl Trait
was. I also think the feature, which is quite awesome, hasn't been talked up enough, and it should/will be quite important for idiomatic Rust code going forward.
Concretely, I think we should split up the 3.1.4. Ownership and lifetimes
section into 3.1.4. Ownership and lifetimes
and 3.1.5 Pattern matching
where the latter includes 3.1.5.1. Default match bindings
and 3.1.5.2. Slice patterns
.
The More details section for impl Trait
describes the type theoretic meaning of impl Trait
in terms of existential types.
type parameters and
impl Trait
in argument position are universals (universally quantified types). Meanwhile,impl
Trait in return position are existentials (existentially quantified types).
This is not quite right: argument-position impl Trait
is also existentially-quantified, but is isomorphic to another universally-quantified type (as described here).
At the very least this explanation should be modified. Better still, all mention of existentially-quantified types could be removed entirely, as explaining impl Trait
in terms of existential types has time and time again proven to cause more confusion than it resolves. The intuitive explanations earlier do a better job of describing impl Trait
.
See rust-lang/rust#51208 (comment); copying:
So --all-targets
seems to work great. Feature handling is harder, but since rustfix supports incremental migration that's fine, for crates with non-mutually exclusive features, cargo +nightly fix --prepare-for 2018 -- --all-targets --no-default-features
and cargo +nightly fix --prepare-for 2018 --allow-dirty -- --all-targets --all-features
should be sufficient to migrate.
If exclusive features are present users need to run with --feature blah
and then --features baz
. For the alpha release that seems sufficient; we might want rustfix to automatically do this with some flag, but I don't think that's very feasible due to exclusionary feature groups.
We should update the migration docs.
A diff of the standard library, probably just a snapshot of all release notes concatenated would be of interest to me, at least so we can see what it looks like.
Do it :)
For example, in 2018/transitioning/traits/impl-trait.md
, it switches between first impl Trait
then T: Trait
to the other way around. I didn't read the sentence right after the code block, so I was confused about which is former and which is latter.
It would probably be good to decide on one way or the other. I think old way then new way is a better general rule than the other way around. (of course being free to change the order if it reads better.)
In the guide it says "In Rust 2018, you can import specific macros from external crates via use statements, rather than the old #[macro_use] attribute." This does say "from external crates", but IMO it should explicitly call out that this does not work for importing macros from the current crate, and that changing that isn't possible until declarative macros 2.0 macro
macros.
In Rust 2018, mod.rs is no longer needed. foo.rs can just be foo.rs, and the submodule is still foo/bar.rs. This eliminates the special name, and if you have a bunch of files open in your editor, you can clearly see their names, instead of having a bunch of tabs named mod.rs.
Emphasis mine. I discovered that this does not mean that mod.rs
can be eliminated from your projects once and for all -- instead, it means specifically that in the case where you have only src/foo/mod.rs
, you can instead name it src/foo.rs
and it'll work just fine.
Include a dedicated page that explains exactly what parts that are only available on 2018 + all the breakage.
This should be a tiny list.
The instructions on importing custom derives from external crates does not work.
The guide says to write
use serde_derive::{Serialize, Deserialize};
But this results in an error that Deserialize is not found (at the derive sites, not the import site). The instructions say to use the name of the derive macro, so I tried:
use serde_derive::{derive_serialize, derive_deserialize};
and got the same error.
I'm not sure, but this may be addressed by #55.
The edition guide contains a chapter on Path Clarity (3.1.2), which explains that for a module foo with submodules, foo/mod.rs is no longer required. From the text, it is not clear foo.rs should be created instead.
Currently I think the suggestion is to run cargo fix
but this currently means that unit tests, benchmarks, etc, will not be fixed. This can be a poor experience where you fix your way into the 2018 edition only to hit a roadblock when you execute cargo test
.
I see one of two possibilities here:
cargo fix
to automatically fix all Cargo targets by default. I like this in that it's sort of what I think we want, but I also don't like this in that it's still not guaranteed to fix everything. We'd need to encourage users to also do things like cargo fix -- --all-targets --all-features
(in today's sytnax)edition = '2018'
you should attempt to fix all targets. This would involve both the --all-targets
flag (perhaps) as well as things like --feature foo
for the specific local crate.I'm personally leaning towards the latter, but I'm curious what others think!
cc @killercup
Right now the compatibility section is fairly small and isolated -- we should perhaps split this out or emphasize it more. People are concerned about ecosystem splits, which AFAIK are (impossible).
https://www.reddit.com/r/rust/comments/8t5cas/rust_2018_an_early_preview/e1568c1/ for some context
Essentially we should make it clear(er) that editions are not a fixed point but we can add to them over time (as we have to 2015 edition).
It is not clear how code importing procedural macros using extern crate
should be updated. A typical example:
#[macro_use] extern crate serde_derive;
#[derive(Serialize, Deserialize)]
...
How should #[macro_use] extern crate
be replaced so that #[derive(...)]
still works?
We should indicate that rustfix will not handle removal of #[macro_use] extern crate foo;
and auto-add imports before the edition, and note that as an idiom change this is something that will/may be handled after the edition, not now.
cc @aturon @Centril -- we discussed this today in the edition meeting, and everyone seemed okay with this approach to this specific case
I looked at https://rust-lang-nursery.github.io/edition-guide/rust-2018/error-handling-and-panics/aborting-on-panic.html and saw a typo which I went to correct. It turns out it was corrected in early December 2018; what does it take to update the published version?
Once the module system changes as specified in https://internals.rust-lang.org/t/relative-paths-in-rust-2018/7883 is done, update guide.
Originally reported in rust-lang/rust#55133, and of late it seems I'm not the only one surprised by the continued need to use extern crate test
in each benchmark as a special case (and with edition="2018"
)
Currently the guide's Path clarity section doesn't seem to indicate there are any exceptions:
https://rust-lang-nursery.github.io/edition-guide/rust-2018/module-system/path-clarity.html
Here's a brief summary:
extern crate
is no longer needed
Wouldn't it be helpful to add this or other exceptional cases as a footnote or under the More details: No more extern crate
section, with some rationale as indicated in rust-lang/rust#55133? My attempt at a user-centric elaboration:
#![feature(test)]
is unstable and doesn't by itself import thetest
pseudo-crate for benchmarks.
Cc @Mark-Simulacrum (not sure if you also disagree with documenting this discrepancy)
Both https://rust-lang-nursery.github.io/edition-guide/2018/transitioning/modules/index.html and https://rust-lang-nursery.github.io/edition-guide/2018/transitioning/modules/path-clarity.html contain the quote that starts with "while there are simple and consistent rules...".
This is particularly obvious if consuming the single-page format https://rust-lang-nursery.github.io/edition-guide/print.html.
See #15 for a suggested change that rephrase the intro without the quote.
It is not clear how to handle optional dependencies now that extern crate
is no longer need.
For instance, say we have a project that optionally uses serde if the feature serde
is enabled. This is how it was done before:
In Cargo.toml
:
[dependencies]
serde = { version = "1", optional = true }
In src/lib.rs
:
#[cfg(feature = "serde")]
extern crate serde;
The guide should explain how to address this.
@nikomatsakis has done a lot of groundwork already: rust-lang/rust#46889
This one should be about things like
impl<I:MyIterator> MyIterator for &mut I {
impl<T> Drop for SetOnDrop<'_, T> {
Is it possible the wrong text got copied over in the refactor?
Full demo, in case it's helpful: https://play.rust-lang.org/?gist=f307a4f4f2a808c3eba9da6ff6bee55f&version=nightly&edition=2018
In "2018-specific changes":
This does not seem to be true - paths like "use foo::bar" will resolve a "foo" in local scope, not just a crate name.
That issue is closed and presumably in stable?
In "Path clarity":
It's not clear what "absolute paths" means. Is this for "::"? It should be explicit.
Again on this page I don't see mention of unprefixed paths resolving names in local scope, which they do.
Again, 'use' declarations seem to resolve names in local scope. No mention of "::" here.
All of the above applies with or with out the 'uniform_paths' feature.
This seems to work, but is not mentioned in the guide (in transitioning.html
):
cargo-features = ["edition"]
[workspace]
members = ["askama", "askama_derive", "askama_shared", "testing"]
edition = "2018"
Obviously, adding it one place instead of per-crate is rather attractive!
Every link here takes me to 404 - it creates URLS containing incorrect "rust-2018/rust-2018" paths.
This looks pretty bad and it's hopefully an easy fix.
The 2015 example:
impl<'a, 'b> SomeTrait<'a> for SomeType<'a, 'b> { ... }
The 2018 example:
impl SomeTrait<'tcx, 'gcx> for SomeType<'tcx, 'gcx> { ... }
but I think it should be:
impl SomeTrait<'tcx> for SomeType<'tcx, 'gcx> { ... }
(SomeTrait is only generic over one lifetime, not two)
#86 gave me an idea... should we translate this guide?
It will probably need to be deferred until after most of it has stabilized so we don't need to update the translations all the time...
We're going to want to create very brief explainers about the epoch concept and the various features in Rust 2018. It's not yet clear how we'll want to organize those, but it's obviously related to this guide!
Rust code isn’t always compiled via Cargo, and it’s surprisingly hard to figure out that Rust 2018 is not the default for rustc
and that you can run rustc --edition=2018
. This ought to be documented somewhere and the Edition Guide seems like a good place.
In the in-band lifetime section, the following syntax is introduced:
fn two_args(foo: &Foo, bar: &'bar Bar) -> &'bar Baz
Later, in the lifetime elision in impl section, it is said that the feature interacts with in-band lifetime syntax in the following way:
fn bar(&self, arg: &str) -> &'arg str
There is a little difference between these two syntaxes, however. The former syntax gives the impression that the lifetime parameter is named "bar" by choice, but could be anything, whereas the latter syntax gives the impression that one can use &'arg
as a shorthand to denote the lifetime of reference argument "arg" of a function.
Which syntax is the correct one?
For increased readability, improve the uniformity in writing style; for example, standardize on a "before / after" format...
This is very much under "polish"
The link "improved error messages" on this page is broken. The problem is due the underlying URL being this:
https://rust-lang-nursery.github.io/edition-guide/rust-2018/the-compiler/rust-2018/the-compiler/improved-error-messages.html
instead of this:
https://rust-lang-nursery.github.io/edition-guide/rust-2018/the-compiler/index.html
We currently tell people to install cargo-fix from github. This is no longer necessary for end-users of the tools. (People who specifically want to test and debug cargo-fix are of course still welcome to use the HEAD version.)
I was a bit confused by the chapter about macro imports. See this StackOverflow question. In short: there are some macros in std
that cannot be imported via use
. Maybe this should be mentioned? Right now it sounds like I can import all macros from extern crates via use
.
And/or: maybe this is a bug and it should be possible to import the macros via use
, too?
The guide has a great section on migrating an existing crate to the 2018 edition but if you want to start a new project that uses the 2018 edition is not obvious that you need to set package.edition = "2018"
in your Cargo.toml as this is only mentioned (AFAICT) in Section 1.1 Transitioning your code to a new edition.
It would be great to have a short section on this topic.
I was reading the Macro Changes page:
Note that you'll still need
#[macro_use]
to use macros you've defined in your own crate; this feature only works for importing macros from external crates.
A couple questions that immediately came to mind:
I think it would be helpful to add a little background about this, as I'm sure others will have similar questions.
The path-clarity section doesn't specifically explain that this no longer works in combination with use bar...;
statements. It should do so, and should describe the recommended fix (use foo as bar;
or use foo::{self as bar, ...};
in affected modules).
This has let s: &Option<&str> = Some("hello");
But should be let s: &Option<&str> = &Some("hello");
In both examples.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.