Skip to content

Commit 88bec87

Browse files
authored
Merge pull request #141 from ehuss/uniform-paths
Update for uniform_path stabilization.
2 parents 7b493e4 + 494b45c commit 88bec87

File tree

2 files changed

+42
-124
lines changed

2 files changed

+42
-124
lines changed

src/rust-2018/edition-changes.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,8 @@ the 2018 edition compared to the 2015 edition.
77
- [Non-lexical lifetimes] (future inclusion planned for 2015 edition)
88
- [At most once] `?` macro repetition operator.
99
- [Path changes]:
10-
- `use` declarations must begin with:
11-
- `crate` – refers to the current crate.
12-
- `self` – refers to the current module.
13-
- `super` – refers to the parent module.
14-
- An external crate name.
15-
- `::` – must be followed by an external crate name. This is required
16-
if an external crate has the same name as an in-scope item, to catch
17-
possible ambiguities with [uniform paths] (which is planned for
18-
inclusion soon [#55618]).
10+
- Paths in `use` declarations work the same as other paths.
11+
- Paths starting with `::` must be followed with an external crate.
1912
- Paths in `pub(in path)` visibility modifiers must start with `crate`,
2013
`self`, or `super`.
2114
- [Anonymous trait function parameters] are not allowed.
@@ -35,7 +28,6 @@ the 2018 edition compared to the 2015 edition.
3528
- `cargo install` for the current directory is no longer allowed, you must
3629
specify `cargo install --path .` to install the current package.
3730

38-
[#55618]: https://github.com/rust-lang/rust/issues/55618
3931
[Anonymous trait function parameters]: rust-2018/trait-system/no-anon-params.html
4032
[At most once]: rust-2018/macros/at-most-once.html
4133
[Non-lexical lifetimes]: rust-2018/ownership-and-lifetimes/non-lexical-lifetimes.html
@@ -46,5 +38,4 @@ the 2018 edition compared to the 2015 edition.
4638
[reserved keywords]: https://doc.rust-lang.org/reference/keywords.html#reserved-keywords
4739
[strict keyword]: https://doc.rust-lang.org/reference/keywords.html#strict-keywords
4840
[tyvar_behind_raw_pointer]: https://github.com/rust-lang/rust/issues/46906
49-
[uniform paths]: rust-2018/module-system/path-clarity.html#uniform-paths
5041
[weak keyword]: https://doc.rust-lang.org/reference/keywords.html#weak-keywords

src/rust-2018/module-system/path-clarity.md

Lines changed: 40 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Path clarity
22

33
![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg)
4-
![Minimum Rust version: nightly](https://img.shields.io/badge/Minimum%20Rust%20Version-nightly-red.svg) for "uniform paths"
54

65
The module system is often one of the hardest things for people new to Rust. Everyone
76
has their own things that take time to master, of course, but there's a root
@@ -17,18 +16,15 @@ Here's a brief summary:
1716

1817
* `extern crate` is no longer needed in 99% of circumstances.
1918
* The `crate` keyword refers to the current crate.
20-
* Absolute paths begin with a crate name, where the keyword `crate`
21-
refers to the current crate.
19+
* Paths may start with a crate name, even within submodules.
20+
* Paths starting with `::` must reference an external crate.
2221
* A `foo.rs` and `foo/` subdirectory may coexist; `mod.rs` is no longer needed
2322
when placing submodules in a subdirectory.
23+
* Paths in `use` declarations work the same as other paths.
2424

2525
These may seem like arbitrary new rules when put this way, but the mental
2626
model is now significantly simplified overall. Read on for more details!
2727

28-
> Additionally, in nightly, there's an additional possible tweak to paths
29-
> called "Uniform paths". This is backwards compatible with the new path
30-
> changes. Uniform paths have a dedicated section at the end of this guide.
31-
3228
## More details
3329

3430
Let's talk about each new feature in turn.
@@ -124,122 +120,55 @@ The prefix `::` previously referred to either the crate root or an external
124120
crate; it now unambiguously refers to an external crate. For instance,
125121
`::foo::bar` always refers to the name `bar` inside the external crate `foo`.
126122

127-
### Changes to paths
128-
129-
In Rust 2018, paths in `use` declarations *must* begin with a crate name,
130-
`crate`, `self`, or `super`.
123+
### Extern crate paths
131124

132-
Code that looked like this:
125+
Previously, using an external crate in a module without a `use` import
126+
required a leading `::` on the path.
133127

134128
```rust,ignore
135129
// Rust 2015
136130
137-
extern crate futures;
131+
extern crate chrono;
138132
139-
use futures::Future;
140-
141-
mod foo {
142-
pub struct Bar;
143-
}
144-
145-
use foo::Bar;
146-
```
147-
148-
Now looks like this:
149-
150-
```rust,ignore
151-
// Rust 2018
152-
153-
// 'futures' is the name of a crate
154-
use futures::Future;
155-
156-
mod foo {
157-
pub struct Bar;
158-
}
159-
160-
// 'crate' means the current crate
161-
use crate::foo::Bar;
162-
```
163-
164-
In addition, all of these path forms are available outside of `use`
165-
declarations as well, which eliminates many sources of confusion. Consider
166-
this code in Rust 2015:
167-
168-
```rust,ignore
169-
// Rust 2015
170-
171-
extern crate futures;
172-
173-
mod submodule {
174-
// this works!
175-
use futures::Future;
176-
177-
// so why doesn't this work?
178-
fn my_poll() -> futures::Poll { ... }
179-
}
180-
181-
fn main() {
182-
// this works
183-
let five = std::sync::Arc::new(5);
133+
fn foo() {
134+
// this works in the crate root
135+
let x = chrono::Utc::now();
184136
}
185137
186138
mod submodule {
187139
fn function() {
188-
// ... so why doesn't this work
189-
let five = std::sync::Arc::new(5);
140+
// but in a submodule it requires a leading :: if not imported with `use`
141+
let x = ::chrono::Utc::now();
190142
}
191143
}
192144
```
193145

194-
> In real code, you couldn't repeat `mod submodule`, and `function` would be defined
195-
> in the first `mod` block.
196-
197-
In the `futures` example, the `my_poll` function signature is incorrect,
198-
because `submodule` contains no items named `futures`; that is, this path is
199-
considered relative. `use futures::` works even though a lone `futures::`
200-
doesn't! With `std` it can be even more confusing, as you never wrote the
201-
`extern crate std;` line at all. So why does it work in `main` but not in a
202-
submodule? Same thing: it's a relative path because it's not in a `use`
203-
declaration. `extern crate std;` is inserted at the crate root, so it's fine
204-
in `main`, but it doesn't exist in the submodule at all.
205-
206-
Let's look at how this change affects things:
146+
Now, extern crate names are in scope in the entire crate, including
147+
submodules.
207148

208149
```rust,ignore
209150
// Rust 2018
210151
211-
// no more `extern crate futures;`
152+
fn foo() {
153+
// this works in the crate root
154+
let x = chrono::Utc::now();
155+
}
212156
213157
mod submodule {
214-
// 'futures' is the name of a crate, so this works
215-
use futures::Future;
216-
217-
// 'futures' is the name of a crate, so this works
218-
fn my_poll<T, E>() -> futures::Poll {
219-
unimplemented!()
220-
}
221-
222158
fn function() {
223-
// 'std' is the name of a crate, so this works
224-
let five = std::sync::Arc::new(5);
159+
// crates may be referenced directly, even in submodules
160+
let x = chrono::Utc::now();
225161
}
226162
}
227-
228-
fn main() {
229-
// 'std' is the name of a crate, so this works
230-
let five = std::sync::Arc::new(5);
231-
}
232163
```
233164

234-
Much more straightforward.
235-
236165
### No more `mod.rs`
237166

238167
In Rust 2015, if you have a submodule:
239168

240169
```rust,ignore
241-
/// foo.rs
242-
/// or
170+
/// foo.rs
171+
/// or
243172
/// foo/mod.rs
244173
245174
mod foo;
@@ -249,10 +178,10 @@ It can live in `foo.rs` or `foo/mod.rs`. If it has submodules of its own, it
249178
*must* be `foo/mod.rs`. So a `bar` submodule of `foo` would live at
250179
`foo/bar.rs`.
251180

252-
In Rust 2018, `mod.rs` is no longer needed.
181+
In Rust 2018, `mod.rs` is no longer needed.
253182

254183
```rust,ignore
255-
/// foo.rs
184+
/// foo.rs
256185
/// foo/bar.rs
257186
258187
mod foo;
@@ -266,23 +195,22 @@ and the submodule is still `foo/bar.rs`. This eliminates the special
266195
name, and if you have a bunch of files open in your editor, you can clearly
267196
see their names, instead of having a bunch of tabs named `mod.rs`.
268197

269-
# Uniform paths
198+
### `use` paths
270199

271-
> Uniform paths are a nightly-only feature.
200+
![Minimum Rust version: 1.32](https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg)
272201

273-
The uniform paths variant of Rust 2018 simplifies and unifies path handling
274-
compared to Rust 2015. In Rust 2015, paths work differently in `use`
275-
declarations than they do elsewhere. In particular, paths in `use`
276-
declarations would always start from the crate root, while paths in other code
277-
implicitly started from the current module. Those differences didn't have any
278-
effect in the top-level module, which meant that everything would seem
279-
straightforward until working on a project large enough to have submodules.
202+
Rust 2018 simplifies and unifies path handling compared to Rust 2015. In Rust
203+
2015, paths work differently in `use` declarations than they do elsewhere. In
204+
particular, paths in `use` declarations would always start from the crate
205+
root, while paths in other code implicitly started from the current scope.
206+
Those differences didn't have any effect in the top-level module, which meant
207+
that everything would seem straightforward until working on a project large
208+
enough to have submodules.
280209

281-
In the uniform paths variant of Rust 2018, paths in `use` declarations and in
282-
other code always work the same way, both in the top-level module and in any
283-
submodule. You can always use a relative path from the current module, a path
284-
starting from an external crate name, or a path starting with `crate`, `super`,
285-
or `self`.
210+
In Rust 2018, paths in `use` declarations and in other code work the same way,
211+
both in the top-level module and in any submodule. You can use a relative path
212+
from the current scope, a path starting from an external crate name, or a path
213+
starting with `crate`, `super`, or `self`.
286214

287215
Code that looked like this:
288216

@@ -320,7 +248,7 @@ will look exactly the same in Rust 2018, except that you can delete the `extern
320248
crate` line:
321249

322250
```rust,ignore
323-
// Rust 2018 (uniform paths variant)
251+
// Rust 2018
324252
325253
use futures::Future;
326254
@@ -347,11 +275,10 @@ fn func() {
347275
}
348276
```
349277

350-
With uniform paths, however, the same code will also work completely unmodified in
351-
a submodule:
278+
The same code will also work completely unmodified in a submodule:
352279

353280
```rust,ignore
354-
// Rust 2018 (uniform paths variant)
281+
// Rust 2018
355282
356283
mod submodule {
357284
use futures::Future;

0 commit comments

Comments
 (0)