Skip to content

Commit cf51fb7

Browse files
committed
Update path clarity to reflect the preview period
Fixes #62
1 parent c5f4437 commit cf51fb7

File tree

1 file changed

+137
-142
lines changed

1 file changed

+137
-142
lines changed

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

+137-142
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Path clarity
22

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

56
The module system is often one of the hardest things for people new to Rust. Everyone
67
has their own things that take time to master, of course, but there's a root
@@ -12,34 +13,22 @@ As such, the 2018 edition of Rust introduces a few new module system
1213
features, but they end up *simplifying* the module system, to make it more
1314
clear as to what is going on.
1415

15-
Note: During the 2018 edition preview, there are two variants of the module
16-
system under consideration, the "uniform paths" variant and the "anchored use
17-
paths" variant. Most of these changes apply to both variants; the two variant
18-
sections call out the differences between the two. We encourage testing of the
19-
new "uniform paths" variant introduced in edition preview 2. The release of
20-
Rust 2018 will stabilize one of these two variants and drop the other.
21-
22-
To test Rust 2018 with the new "uniform paths" variant, put
23-
`#![feature(uniform_paths)]` at the top of your `lib.rs` or
24-
`main.rs`.
25-
2616
Here's a brief summary:
2717

2818
* `extern crate` is no longer needed
2919
* The `crate` keyword refers to the current crate.
30-
* Uniform paths variant: Paths work uniformly in both `use` declarations and in
31-
other code. Paths work uniformly both in the top-level module and in
32-
submodules. Any path may start with a crate, with `crate`, `super`, or
33-
`self`, or with a local name relative to the current module.
34-
* Anchored use paths variant: Paths in `use` declarations always start with a
35-
crate name, or with `crate`, `super`, or `self`. Paths in code other than
36-
`use` declarations may also start with names relative to the current module.
20+
* Absolute paths begin with a crate name, where the keyword `crate`
21+
refers to the current crate.
3722
* A `foo.rs` and `foo/` subdirectory may coexist; `mod.rs` is no longer needed
3823
when placing submodules in a subdirectory.
3924

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

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+
4332
## More details
4433

4534
Let's talk about each new feature in turn.
@@ -109,7 +98,136 @@ The prefix `::` previously referred to either the crate root or an external
10998
crate; it now unambiguously refers to an external crate. For instance,
11099
`::foo::bar` always refers to the name `bar` inside the external crate `foo`.
111100

112-
### Uniform paths variant
101+
### Changes to paths
102+
103+
In Rust 2018, paths in `use` declarations *must* begin with a crate name,
104+
`crate`, `self`, or `super`.
105+
106+
Code that looked like this:
107+
108+
```rust,ignore
109+
// Rust 2015
110+
111+
extern crate futures;
112+
113+
use futures::Future;
114+
115+
mod foo {
116+
pub struct Bar;
117+
}
118+
119+
use foo::Bar;
120+
```
121+
122+
Now looks like this:
123+
124+
```rust,ignore
125+
// Rust 2018
126+
127+
// 'futures' is the name of a crate
128+
use futures::Future;
129+
130+
mod foo {
131+
pub struct Bar;
132+
}
133+
134+
// 'crate' means the current crate
135+
use crate::foo::Bar;
136+
```
137+
138+
In addition, all of these path forms are available outside of `use`
139+
declarations as well, which eliminates many sources of confusion. Consider
140+
this code in Rust 2015:
141+
142+
```rust,ignore
143+
// Rust 2015
144+
145+
extern crate futures;
146+
147+
mod submodule {
148+
// this works!
149+
use futures::Future;
150+
151+
// so why doesn't this work?
152+
fn my_poll() -> futures::Poll { ... }
153+
}
154+
155+
fn main() {
156+
// this works
157+
let five = std::sync::Arc::new(5);
158+
}
159+
160+
mod submodule {
161+
fn function() {
162+
// ... so why doesn't this work
163+
let five = std::sync::Arc::new(5);
164+
}
165+
}
166+
```
167+
168+
> In real code, you couldn't repeat `mod submodule`, and `function` would be defined
169+
> in the first `mod` block.
170+
171+
In the `futures` example, the `my_poll` function signature is incorrect,
172+
because `submodule` contains no items named `futures`; that is, this path is
173+
considered relative. `use futures::` works even though a lone `futures::`
174+
doesn't! With `std` it can be even more confusing, as you never wrote the
175+
`extern crate std;` line at all. So why does it work in `main` but not in a
176+
submodule? Same thing: it's a relative path because it's not in a `use`
177+
declaration. `extern crate std;` is inserted at the crate root, so it's fine
178+
in `main`, but it doesn't exist in the submodule at all.
179+
180+
Let's look at how this change affects things:
181+
182+
```rust,ignore
183+
// Rust 2018
184+
185+
// no more `extern crate futures;`
186+
187+
mod submodule {
188+
// 'futures' is the name of a crate, so this works
189+
use futures::Future;
190+
191+
// 'futures' is the name of a crate, so this works
192+
fn my_poll<T, E>() -> futures::Poll {
193+
unimplemented!()
194+
}
195+
196+
fn function() {
197+
// 'std' is the name of a crate, so this works
198+
let five = std::sync::Arc::new(5);
199+
}
200+
}
201+
202+
fn main() {
203+
// 'std' is the name of a crate, so this works
204+
let five = std::sync::Arc::new(5);
205+
}
206+
```
207+
208+
Much more straightforward.
209+
210+
### No more `mod.rs`
211+
212+
In Rust 2015, if you have a submodule:
213+
214+
```rust,ignore
215+
mod foo;
216+
```
217+
218+
It can live in `foo.rs` or `foo/mod.rs`. If it has submodules of its own, it
219+
*must* be `foo/mod.rs`. So a `bar` submodule of `foo` would live at
220+
`foo/bar.rs`.
221+
222+
In Rust 2018, `mod.rs` is no longer needed. `foo.rs` can just be `foo.rs`,
223+
and the submodule is still `foo/bar.rs`. This eliminates the special
224+
name, and if you have a bunch of files open in your editor, you can clearly
225+
see their names, instead of having a bunch of tabs named `mod.rs`.
226+
227+
228+
# Uniform paths
229+
230+
> Uniform paths are a nightly-only feature.
113231
114232
The uniform paths variant of Rust 2018 simplifies and unifies path handling
115233
compared to Rust 2015. In Rust 2015, paths work differently in `use`
@@ -229,126 +347,3 @@ module or item with the same name, you'll get an error, and you'll need to
229347
either rename one of the conflicting names or explicitly disambiguate the path.
230348
To explicitly disambiguate a path, use `::name` for an external crate name, or
231349
`self::name` for a local module or item.
232-
233-
### Anchored use paths variant
234-
235-
In the anchored use paths variant of Rust 2018, paths in `use` declarations
236-
*must* begin with a crate name, `crate`, `self`, or `super`.
237-
238-
Code that looked like this:
239-
240-
```rust,ignore
241-
// Rust 2015
242-
243-
extern crate futures;
244-
245-
use futures::Future;
246-
247-
mod foo {
248-
pub struct Bar;
249-
}
250-
251-
use foo::Bar;
252-
```
253-
254-
Now looks like this:
255-
256-
```rust,ignore
257-
// Rust 2018 (anchored use paths variant)
258-
259-
// 'futures' is the name of a crate
260-
use futures::Future;
261-
262-
mod foo {
263-
pub struct Bar;
264-
}
265-
266-
// 'crate' means the current crate
267-
use crate::foo::Bar;
268-
```
269-
270-
In addition, all of these path forms are available outside of `use`
271-
declarations as well, which eliminates many sources of confusion. Consider this
272-
code in Rust 2015:
273-
274-
```rust,ignore
275-
// Rust 2015
276-
277-
extern crate futures;
278-
279-
mod submodule {
280-
// this works!
281-
use futures::Future;
282-
283-
// so why doesn't this work?
284-
fn my_poll() -> futures::Poll { ... }
285-
}
286-
287-
fn main() {
288-
// this works
289-
let five = std::sync::Arc::new(5);
290-
}
291-
292-
mod submodule {
293-
fn function() {
294-
// ... so why doesn't this work
295-
let five = std::sync::Arc::new(5);
296-
}
297-
}
298-
```
299-
300-
In the `futures` example, the `my_poll` function signature is incorrect, because `submodule`
301-
contains no items named `futures`; that is, this path is considered relative. But because
302-
`use` is anchored, `use futures::` works even though a lone `futures::` doesn't! With `std`
303-
it can be even more confusing, as you never wrote the `extern crate std;` line at all. So
304-
why does it work in `main` but not in a submodule? Same thing: it's a relative path because
305-
it's not in a `use` declaration. `extern crate std;` is inserted at the crate root, so
306-
it's fine in `main`, but it doesn't exist in the submodule at all.
307-
308-
Let's look at how this change affects things:
309-
310-
```rust,ignore
311-
// Rust 2018 (anchored use paths variant)
312-
313-
// no more `extern crate futures;`
314-
315-
mod submodule {
316-
// 'futures' is the name of a crate, so this is anchored and works
317-
use futures::Future;
318-
319-
// 'futures' is the name of a crate, so this is anchored and works
320-
fn my_poll() -> futures::Poll { ... }
321-
}
322-
323-
fn main() {
324-
// 'std' is the name of a crate, so this is anchored and works
325-
let five = std::sync::Arc::new(5);
326-
}
327-
328-
mod submodule {
329-
fn function() {
330-
// 'std' is the name of a crate, so this is anchored and works
331-
let five = std::sync::Arc::new(5);
332-
}
333-
}
334-
```
335-
336-
Much more straightforward.
337-
338-
339-
### No more `mod.rs`
340-
341-
In Rust 2015, if you have a submodule:
342-
343-
```rust,ignore
344-
mod foo;
345-
```
346-
347-
It can live in `foo.rs` or `foo/mod.rs`. If it has submodules of its own, it
348-
*must* be `foo/mod.rs`. So a `bar` submodule of `foo` would live at
349-
`foo/bar.rs`.
350-
351-
In Rust 2018, `mod.rs` is no longer needed. `foo.rs` can just be `foo.rs`,
352-
and the submodule is still `foo/bar.rs`. This eliminates the special
353-
name, and if you have a bunch of files open in your editor, you can clearly
354-
see their names, instead of having a bunch of tabs named `mod.rs`.

0 commit comments

Comments
 (0)