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
+ * ` use ` declarations take [ uniform paths] ( #uniform-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,61 @@ 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;
138
-
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
131
+ extern crate chrono;
152
132
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
}
143
+
144
+ // unlike expressions, `use` paths were allowed to reference crates directly
145
+ use chrono::Local;
191
146
}
192
147
```
193
148
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:
149
+ Now, extern crate names are in scope in the entire crate, including
150
+ submodules.
207
151
208
152
``` rust,ignore
209
153
// Rust 2018
210
154
211
- // no more `extern crate futures;`
155
+ fn foo() {
156
+ // this works in the crate root
157
+ let x = chrono::Utc::now();
158
+ }
212
159
213
160
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
161
fn function() {
223
- // 'std' is the name of a crate, so this works
224
- let five = std::sync::Arc::new(5 );
162
+ // crates may be referenced directly, even in submodules
163
+ let x = chrono::Utc::now( );
225
164
}
226
- }
227
165
228
- fn main() {
229
- // 'std' is the name of a crate, so this works
230
- let five = std::sync::Arc::new(5);
166
+ // `use` paths have the same path style
167
+ use chrono::Local;
231
168
}
232
169
```
233
170
234
- Much more straightforward.
235
-
236
171
### No more ` mod.rs `
237
172
238
173
In Rust 2015, if you have a submodule:
239
174
240
175
``` rust,ignore
241
- /// foo.rs
242
- /// or
176
+ /// foo.rs
177
+ /// or
243
178
/// foo/mod.rs
244
179
245
180
mod foo;
@@ -249,10 +184,10 @@ It can live in `foo.rs` or `foo/mod.rs`. If it has submodules of its own, it
249
184
* must* be ` foo/mod.rs ` . So a ` bar ` submodule of ` foo ` would live at
250
185
` foo/bar.rs ` .
251
186
252
- In Rust 2018, ` mod.rs ` is no longer needed.
187
+ In Rust 2018, ` mod.rs ` is no longer needed.
253
188
254
189
``` rust,ignore
255
- /// foo.rs
190
+ /// foo.rs
256
191
/// foo/bar.rs
257
192
258
193
mod foo;
@@ -268,21 +203,21 @@ see their names, instead of having a bunch of tabs named `mod.rs`.
268
203
269
204
# Uniform paths
270
205
271
- > Uniform paths are a nightly-only feature.
206
+ ![ Minimum Rust version: 1.32 ] ( https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg )
272
207
273
208
The uniform paths variant of Rust 2018 simplifies and unifies path handling
274
209
compared to Rust 2015. In Rust 2015, paths work differently in ` use `
275
210
declarations than they do elsewhere. In particular, paths in ` use `
276
211
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
212
+ implicitly started from the current scope . Those differences didn't have any
278
213
effect in the top-level module, which meant that everything would seem
279
214
straightforward until working on a project large enough to have submodules.
280
215
281
216
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 ` .
217
+ other code almost always work the same way, both in the top-level module and
218
+ in any submodule. You can use a relative path from the current scope , a path
219
+ starting from an external crate name, or a path starting with ` crate ` ,
220
+ ` super ` , or ` self ` .
286
221
287
222
Code that looked like this:
288
223
0 commit comments