You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/rust-2018/path-clarity.md
+161-21
Original file line number
Diff line number
Diff line change
@@ -12,11 +12,24 @@ As such, the 2018 edition of Rust introduces a few new module system
12
12
features, but they end up *simplifying* the module system, to make it more
13
13
clear as to what is going on.
14
14
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
+
15
22
Here's a brief summary:
16
23
17
24
*`extern crate` is no longer needed
18
-
* Absolute paths begin with a crate name, where the keyword `crate`
19
-
refers to the current crate.
25
+
* The `crate` keyword refers to the current crate.
26
+
* Uniform paths variant: Paths work uniformly in both `use` declarations and in
27
+
other code. Paths work uniformly both in the top-level module and in
28
+
submodules. Any path may start with a crate, with `crate`, `super`, or
29
+
`self`, or with a local name relative to the current module.
30
+
* Anchored use paths variant: Paths in `use` declarations always start with a
31
+
crate name, or with `crate`, `super`, or `self`. Paths in code other than
32
+
`use` declarations may also start with names relative to the current module.
20
33
* A `foo.rs` and `foo/` subdirectory may coexist; `mod.rs` is no longer needed
21
34
when placing submodules in a subdirectory.
22
35
@@ -60,14 +73,142 @@ keep doing what you were doing there as well.
60
73
One other use for `extern crate` was to import macros; that's no longer needed.
61
74
Check [the macro section](2018/transitioning/modules/macros.html) for more.
62
75
63
-
### Absolute paths begin with `crate` or the crate name
76
+
### The `crate` keyword refers to the current crate.
77
+
78
+
In `use` declarations and in other code, you can refer to the root of the
79
+
current crate with the `crate::` prefix. For instance, `crate::foo::bar` will
80
+
always refer to the name `bar` inside the module `foo`, from anywhere else in
81
+
the same crate.
82
+
83
+
The prefix `::` previously referred to either the crate root or an external
84
+
crate; it now unambiguously refers to an external crate. For instance,
85
+
`::foo::bar` always refers to the name `bar` inside the external crate `foo`.
86
+
87
+
### Uniform paths variant
88
+
89
+
The uniform paths variant of Rust 2018 simplifies and unifies path handling
90
+
compared to Rust 2015. In Rust 2015, paths work differently in `use`
91
+
declarations than they do elsewhere. In particular, paths in `use`
92
+
declarations would always start from the crate root, while paths in other code
93
+
implicitly started from the current module. Those differences didn't have any
94
+
effect in the top-level module, which meant that everything would seem
95
+
straightforward until working on a project large enough to have submodules.
96
+
97
+
In the uniform paths variant of Rust 2018, paths in `use` declarations and in
98
+
other code always work the same way, both in the top-level module and in any
99
+
submodule. You can always use a relative path from the current module, a path
100
+
starting from an external crate name, or a path starting with `crate`, `super`,
101
+
or `self`.
102
+
103
+
Code that looked like this:
104
+
105
+
```rust,ignore
106
+
// Rust 2015
107
+
108
+
extern crate futures;
109
+
110
+
use futures::Future;
111
+
112
+
mod foo {
113
+
pub struct Bar;
114
+
}
115
+
116
+
use foo::Bar;
117
+
118
+
fn my_poll() -> futures::Poll { ... }
119
+
120
+
enum SomeEnum {
121
+
V1(usize),
122
+
V2(String),
123
+
}
124
+
125
+
fn func() {
126
+
let five = std::sync::Arc::new(5);
127
+
use SomeEnum::*;
128
+
match ... {
129
+
V1(i) => { ... }
130
+
V2(s) => { ... }
131
+
}
132
+
}
133
+
```
134
+
135
+
will look exactly the same in Rust 2018, except that you can delete the `extern
136
+
crate` line:
137
+
138
+
```rust,ignore
139
+
// Rust 2018 (uniform paths variant)
140
+
141
+
use futures::Future;
142
+
143
+
mod foo {
144
+
pub struct Bar;
145
+
}
146
+
147
+
use foo::Bar;
148
+
149
+
fn my_poll() -> futures::Poll { ... }
150
+
151
+
enum SomeEnum {
152
+
V1(usize),
153
+
V2(String),
154
+
}
155
+
156
+
fn func() {
157
+
let five = std::sync::Arc::new(5);
158
+
use SomeEnum::*;
159
+
match ... {
160
+
V1(i) => { ... }
161
+
V2(s) => { ... }
162
+
}
163
+
}
164
+
```
165
+
166
+
With Rust 2018, however, the same code will also work completely unmodified in
167
+
a submodule:
168
+
169
+
```rust,ignore
170
+
// Rust 2018 (uniform paths variant)
171
+
172
+
mod submodule {
173
+
use futures::Future;
64
174
65
-
In Rust 2018, paths in `use` statements *must* begin with one of:
175
+
mod foo {
176
+
pub struct Bar;
177
+
}
66
178
67
-
- A crate name
68
-
-`crate` for the current crate's root
69
-
-`self` for the current module's root
70
-
-`super` for the current module's parent
179
+
use foo::Bar;
180
+
181
+
fn my_poll() -> futures::Poll { ... }
182
+
183
+
enum SomeEnum {
184
+
V1(usize),
185
+
V2(String),
186
+
}
187
+
188
+
fn func() {
189
+
let five = std::sync::Arc::new(5);
190
+
use SomeEnum::*;
191
+
match ... {
192
+
V1(i) => { ... }
193
+
V2(s) => { ... }
194
+
}
195
+
}
196
+
}
197
+
```
198
+
199
+
This makes it easy to move code around in a project, and avoids introducing
200
+
additional complexity to multi-module projects.
201
+
202
+
If a path is ambiguous, such as if you have an external crate and a local
203
+
module or item with the same name, you'll get an error, and you'll need to
204
+
either rename one of the conflicting names or explicitly disambiguate the path.
205
+
To explicitly disambiguate a path, use `::name` for an external crate name, or
206
+
`self::name` for a local module or item.
207
+
208
+
### Anchored use paths variant
209
+
210
+
In the anchored use paths variant of Rust 2018, paths in `use` declarations
211
+
*must* begin with a crate name, `crate`, `self`, or `super`.
71
212
72
213
Code that looked like this:
73
214
@@ -79,7 +220,7 @@ extern crate futures;
79
220
use futures::Future;
80
221
81
222
mod foo {
82
-
struct Bar;
223
+
pub struct Bar;
83
224
}
84
225
85
226
use foo::Bar;
@@ -88,22 +229,22 @@ use foo::Bar;
88
229
Now looks like this:
89
230
90
231
```rust,ignore
91
-
// Rust 2018
232
+
// Rust 2018 (anchored use paths variant)
92
233
93
234
// 'futures' is the name of a crate
94
235
use futures::Future;
95
236
96
237
mod foo {
97
-
struct Bar;
238
+
pub struct Bar;
98
239
}
99
240
100
241
// 'crate' means the current crate
101
242
use crate::foo::Bar;
102
243
```
103
244
104
-
In addition, all of these path forms are available outside of `use` statements
105
-
as well, which eliminates many sources of confusion. Consider this code in Rust
106
-
2015:
245
+
In addition, all of these path forms are available outside of `use`
246
+
declarations as well, which eliminates many sources of confusion. Consider this
247
+
code in Rust 2015:
107
248
108
249
```rust,ignore
109
250
// Rust 2015
@@ -133,7 +274,7 @@ mod submodule {
133
274
134
275
In the `futures` example, the `my_poll` function signature is incorrect, because `submodule`
135
276
contains no items named `futures`; that is, this path is considered relative. But because
136
-
`use` is absolute, `use futures::` works even though a lone `futures::` doesn't! With `std`
277
+
`use` is anchored, `use futures::` works even though a lone `futures::` doesn't! With `std`
137
278
it can be even more confusing, as you never wrote the `extern crate std;` line at all. So
138
279
why does it work in `main` but not in a submodule? Same thing: it's a relative path because
139
280
it's not in a `use` declaration. `extern crate std;` is inserted at the crate root, so
@@ -142,34 +283,33 @@ it's fine in `main`, but it doesn't exist in the submodule at all.
142
283
Let's look at how this change affects things:
143
284
144
285
```rust,ignore
145
-
// Rust 2018
286
+
// Rust 2018 (anchored use paths variant)
146
287
147
288
// no more `extern crate futures;`
148
289
149
290
mod submodule {
150
-
// 'futures' is the name of a crate, so this is absolute and works
291
+
// 'futures' is the name of a crate, so this is anchored and works
151
292
use futures::Future;
152
293
153
-
// 'futures' is the name of a crate, so this is absolute and works
294
+
// 'futures' is the name of a crate, so this is anchored and works
154
295
fn my_poll() -> futures::Poll { ... }
155
296
}
156
297
157
298
fn main() {
158
-
// 'std' is the name of a crate, so this is absolute and works
299
+
// 'std' is the name of a crate, so this is anchored and works
159
300
let five = std::sync::Arc::new(5);
160
301
}
161
302
162
303
mod submodule {
163
304
fn function() {
164
-
// 'std' is the name of a crate, so this is absolute and works
305
+
// 'std' is the name of a crate, so this is anchored and works
165
306
let five = std::sync::Arc::new(5);
166
307
}
167
308
}
168
309
```
169
310
170
311
Much more straightforward.
171
312
172
-
**Note**: an alternative syntax is also under consideration: writing `::some::Local` rather than `crate::some::Local`. If you have thoughts about this alternative, please leave a comment on [the tracking issue](https://github.com/rust-lang/rust/issues/44660) or start a thread on the [edition feedback category](https://internals.rust-lang.org/c/edition-2018-feedback).
0 commit comments