1
1
# Path clarity
2
2
3
3
![ 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"
5
4
6
5
The module system is often one of the hardest things for people new to Rust. Everyone
7
6
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:
17
16
18
17
* ` extern crate ` is no longer needed in 99% of circumstances.
19
18
* 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.
22
21
* A ` foo.rs ` and ` foo/ ` subdirectory may coexist; ` mod.rs ` is no longer needed
23
22
when placing submodules in a subdirectory.
23
+ * Paths in ` use ` declarations work the same as other paths.
24
24
25
25
These may seem like arbitrary new rules when put this way, but the mental
26
26
model is now significantly simplified overall. Read on for more details!
27
27
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
-
32
28
## More details
33
29
34
30
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
124
120
crate; it now unambiguously refers to an external crate. For instance,
125
121
` ::foo::bar ` always refers to the name ` bar ` inside the external crate ` foo ` .
126
122
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
131
124
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.
133
127
134
128
``` rust,ignore
135
129
// Rust 2015
136
130
137
- extern crate futures ;
131
+ extern crate chrono ;
138
132
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();
184
136
}
185
137
186
138
mod submodule {
187
139
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( );
190
142
}
191
143
}
192
144
```
193
145
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.
207
148
208
149
``` rust,ignore
209
150
// Rust 2018
210
151
211
- // no more `extern crate futures;`
152
+ fn foo() {
153
+ // this works in the crate root
154
+ let x = chrono::Utc::now();
155
+ }
212
156
213
157
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
-
222
158
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( );
225
161
}
226
162
}
227
-
228
- fn main() {
229
- // 'std' is the name of a crate, so this works
230
- let five = std::sync::Arc::new(5);
231
- }
232
163
```
233
164
234
- Much more straightforward.
235
-
236
165
### No more ` mod.rs `
237
166
238
167
In Rust 2015, if you have a submodule:
239
168
240
169
``` rust,ignore
241
- /// foo.rs
242
- /// or
170
+ /// foo.rs
171
+ /// or
243
172
/// foo/mod.rs
244
173
245
174
mod foo;
@@ -249,10 +178,10 @@ It can live in `foo.rs` or `foo/mod.rs`. If it has submodules of its own, it
249
178
* must* be ` foo/mod.rs ` . So a ` bar ` submodule of ` foo ` would live at
250
179
` foo/bar.rs ` .
251
180
252
- In Rust 2018, ` mod.rs ` is no longer needed.
181
+ In Rust 2018, ` mod.rs ` is no longer needed.
253
182
254
183
``` rust,ignore
255
- /// foo.rs
184
+ /// foo.rs
256
185
/// foo/bar.rs
257
186
258
187
mod foo;
@@ -266,23 +195,22 @@ and the submodule is still `foo/bar.rs`. This eliminates the special
266
195
name, and if you have a bunch of files open in your editor, you can clearly
267
196
see their names, instead of having a bunch of tabs named ` mod.rs ` .
268
197
269
- # Uniform paths
198
+ ### ` use ` paths
270
199
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 )
272
201
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.
280
209
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 ` .
286
214
287
215
Code that looked like this:
288
216
@@ -320,7 +248,7 @@ will look exactly the same in Rust 2018, except that you can delete the `extern
320
248
crate` line:
321
249
322
250
``` rust,ignore
323
- // Rust 2018 (uniform paths variant)
251
+ // Rust 2018
324
252
325
253
use futures::Future;
326
254
@@ -347,11 +275,10 @@ fn func() {
347
275
}
348
276
```
349
277
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:
352
279
353
280
``` rust,ignore
354
- // Rust 2018 (uniform paths variant)
281
+ // Rust 2018
355
282
356
283
mod submodule {
357
284
use futures::Future;
0 commit comments