diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/dev/style.md | 105 |
1 files changed, 94 insertions, 11 deletions
diff --git a/docs/dev/style.md b/docs/dev/style.md index 59067d234..7a64a0d22 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -186,6 +186,31 @@ impl Person { | |||
186 | } | 186 | } |
187 | ``` | 187 | ``` |
188 | 188 | ||
189 | ## Constructors | ||
190 | |||
191 | Prefer `Default` to zero-argument `new` function | ||
192 | |||
193 | ```rust | ||
194 | // Good | ||
195 | #[derive(Default)] | ||
196 | struct Foo { | ||
197 | bar: Option<Bar> | ||
198 | } | ||
199 | |||
200 | // Not as good | ||
201 | struct Foo { | ||
202 | bar: Option<Bar> | ||
203 | } | ||
204 | |||
205 | impl Foo { | ||
206 | fn new() -> Foo { | ||
207 | Foo { bar: None } | ||
208 | } | ||
209 | } | ||
210 | ``` | ||
211 | |||
212 | Prefer `Default` even it has to be implemented manually. | ||
213 | |||
189 | ## Avoid Monomorphization | 214 | ## Avoid Monomorphization |
190 | 215 | ||
191 | Rust uses monomorphization to compile generic code, meaning that for each instantiation of a generic functions with concrete types, the function is compiled afresh, *per crate*. | 216 | Rust uses monomorphization to compile generic code, meaning that for each instantiation of a generic functions with concrete types, the function is compiled afresh, *per crate*. |
@@ -223,6 +248,8 @@ fn frbonicate(f: impl AsRef<Path>) { | |||
223 | 248 | ||
224 | # Premature Pessimization | 249 | # Premature Pessimization |
225 | 250 | ||
251 | ## Avoid Allocations | ||
252 | |||
226 | Avoid writing code which is slower than it needs to be. | 253 | Avoid writing code which is slower than it needs to be. |
227 | Don't allocate a `Vec` where an iterator would do, don't allocate strings needlessly. | 254 | Don't allocate a `Vec` where an iterator would do, don't allocate strings needlessly. |
228 | 255 | ||
@@ -242,6 +269,8 @@ if words.len() != 2 { | |||
242 | } | 269 | } |
243 | ``` | 270 | ``` |
244 | 271 | ||
272 | ## Push Allocations to the Call Site | ||
273 | |||
245 | If allocation is inevitable, let the caller allocate the resource: | 274 | If allocation is inevitable, let the caller allocate the resource: |
246 | 275 | ||
247 | ```rust | 276 | ```rust |
@@ -257,6 +286,9 @@ fn frobnicate(s: &str) { | |||
257 | } | 286 | } |
258 | ``` | 287 | ``` |
259 | 288 | ||
289 | This is better because it reveals the costs. | ||
290 | It is also more efficient when the caller already owns the allocation. | ||
291 | |||
260 | ## Collection types | 292 | ## Collection types |
261 | 293 | ||
262 | Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`. | 294 | Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`. |
@@ -334,27 +366,66 @@ People read things from top to bottom, so place most important things first. | |||
334 | 366 | ||
335 | Specifically, if all items except one are private, always put the non-private item on top. | 367 | Specifically, if all items except one are private, always put the non-private item on top. |
336 | 368 | ||
337 | Put `struct`s and `enum`s first, functions and impls last. | ||
338 | |||
339 | Do | ||
340 | |||
341 | ```rust | 369 | ```rust |
342 | // Good | 370 | // Good |
343 | struct Foo { | 371 | pub(crate) fn frobnicate() { |
344 | bars: Vec<Bar> | 372 | Helper::act() |
345 | } | 373 | } |
346 | 374 | ||
347 | struct Bar; | 375 | #[derive(Default)] |
376 | struct Helper { stuff: i32 } | ||
377 | |||
378 | impl Helper { | ||
379 | fn act(&self) { | ||
380 | |||
381 | } | ||
382 | } | ||
383 | |||
384 | // Not as good | ||
385 | #[derive(Default)] | ||
386 | struct Helper { stuff: i32 } | ||
387 | |||
388 | pub(crate) fn frobnicate() { | ||
389 | Helper::act() | ||
390 | } | ||
391 | |||
392 | impl Helper { | ||
393 | fn act(&self) { | ||
394 | |||
395 | } | ||
396 | } | ||
348 | ``` | 397 | ``` |
349 | 398 | ||
350 | rather than | 399 | If there's a mixture of private and public items, put public items first. |
400 | If function bodies are folded in the editor, the source code should read as documentation for the public API. | ||
401 | |||
402 | Put `struct`s and `enum`s first, functions and impls last. Order types declarations in top-down manner. | ||
351 | 403 | ||
352 | ```rust | 404 | ```rust |
405 | // Good | ||
406 | struct Parent { | ||
407 | children: Vec<Child> | ||
408 | } | ||
409 | |||
410 | struct Child; | ||
411 | |||
412 | impl Parent { | ||
413 | } | ||
414 | |||
415 | impl Child { | ||
416 | } | ||
417 | |||
353 | // Not as good | 418 | // Not as good |
354 | struct Bar; | 419 | struct Child; |
355 | 420 | ||
356 | struct Foo { | 421 | impl Child { |
357 | bars: Vec<Bar> | 422 | } |
423 | |||
424 | struct Parent { | ||
425 | children: Vec<Child> | ||
426 | } | ||
427 | |||
428 | impl Parent { | ||
358 | } | 429 | } |
359 | ``` | 430 | ``` |
360 | 431 | ||
@@ -371,6 +442,18 @@ Default names: | |||
371 | * `n_foo` -- number of foos | 442 | * `n_foo` -- number of foos |
372 | * `foo_idx` -- index of `foo` | 443 | * `foo_idx` -- index of `foo` |
373 | 444 | ||
445 | Many names in rust-analyzer conflict with keywords. | ||
446 | We use mangled names instead of `r#ident` syntax: | ||
447 | |||
448 | ``` | ||
449 | struct -> strukt | ||
450 | crate -> krate | ||
451 | impl -> imp | ||
452 | trait -> trait_ | ||
453 | fn -> func | ||
454 | enum -> enum_ | ||
455 | mod -> module | ||
456 | ``` | ||
374 | 457 | ||
375 | ## Early Returns | 458 | ## Early Returns |
376 | 459 | ||