diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/dev/README.md | 3 | ||||
-rw-r--r-- | docs/dev/style.md | 49 |
2 files changed, 51 insertions, 1 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md index dd2bfc493..24197b332 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -251,6 +251,9 @@ RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more tha | |||
251 | 251 | ||
252 | In particular, I have `export RA_PROFILE='*>10'` in my shell profile. | 252 | In particular, I have `export RA_PROFILE='*>10'` in my shell profile. |
253 | 253 | ||
254 | We also have a "counting" profiler which counts number of instances of popular structs. | ||
255 | It is enabled by `RA_COUNT=1`. | ||
256 | |||
254 | To measure time for from-scratch analysis, use something like this: | 257 | To measure time for from-scratch analysis, use something like this: |
255 | 258 | ||
256 | ``` | 259 | ``` |
diff --git a/docs/dev/style.md b/docs/dev/style.md index 21330948b..7e6cd49e0 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -6,6 +6,9 @@ Our approach to "clean code" is two-fold: | |||
6 | It is explicitly OK for a reviewer to flag only some nits in the PR, and then send a follow-up cleanup PR for things which are easier to explain by example, cc-ing the original author. | 6 | It is explicitly OK for a reviewer to flag only some nits in the PR, and then send a follow-up cleanup PR for things which are easier to explain by example, cc-ing the original author. |
7 | Sending small cleanup PRs (like renaming a single local variable) is encouraged. | 7 | Sending small cleanup PRs (like renaming a single local variable) is encouraged. |
8 | 8 | ||
9 | When reviewing pull requests prefer extending this document to leaving | ||
10 | non-reusable comments on the pull request itself. | ||
11 | |||
9 | # General | 12 | # General |
10 | 13 | ||
11 | ## Scale of Changes | 14 | ## Scale of Changes |
@@ -280,6 +283,9 @@ Prefer `Default` even it has to be implemented manually. | |||
280 | 283 | ||
281 | **Rationale:** less typing in the common case, uniformity. | 284 | **Rationale:** less typing in the common case, uniformity. |
282 | 285 | ||
286 | Use `Vec::new` rather than `vec![]`. **Rationale:** uniformity, strength | ||
287 | reduction. | ||
288 | |||
283 | ## Functions Over Objects | 289 | ## Functions Over Objects |
284 | 290 | ||
285 | Avoid creating "doer" objects. | 291 | Avoid creating "doer" objects. |
@@ -372,6 +378,15 @@ This allows for exceptionally good performance, but leads to increased compile t | |||
372 | Runtime performance obeys 80%/20% rule -- only a small fraction of code is hot. | 378 | Runtime performance obeys 80%/20% rule -- only a small fraction of code is hot. |
373 | Compile time **does not** obey this rule -- all code has to be compiled. | 379 | Compile time **does not** obey this rule -- all code has to be compiled. |
374 | 380 | ||
381 | ## Appropriate String Types | ||
382 | |||
383 | When interfacing with OS APIs, use `OsString`, even if the original source of | ||
384 | data is utf-8 encoded. **Rationale:** cleanly delineates the boundary when the | ||
385 | data goes into the OS-land. | ||
386 | |||
387 | Use `AbsPathBuf` and `AbsPath` over `std::Path`. **Rationale:** rust-analyzer is | ||
388 | a long-lived process which handles several projects at the same time. It is | ||
389 | important not to leak cwd by accident. | ||
375 | 390 | ||
376 | # Premature Pessimization | 391 | # Premature Pessimization |
377 | 392 | ||
@@ -418,12 +433,44 @@ fn frobnicate(s: &str) { | |||
418 | **Rationale:** reveals the costs. | 433 | **Rationale:** reveals the costs. |
419 | It is also more efficient when the caller already owns the allocation. | 434 | It is also more efficient when the caller already owns the allocation. |
420 | 435 | ||
421 | ## Collection types | 436 | ## Collection Types |
422 | 437 | ||
423 | Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`. | 438 | Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`. |
424 | 439 | ||
425 | **Rationale:** they use a hasher that's significantly faster and using them consistently will reduce code size by some small amount. | 440 | **Rationale:** they use a hasher that's significantly faster and using them consistently will reduce code size by some small amount. |
426 | 441 | ||
442 | ## Avoid Intermediate Collections | ||
443 | |||
444 | When writing a recursive function to compute a sets of things, use an accumulator parameter instead of returning a fresh collection. | ||
445 | Accumulator goes first in the list of arguments. | ||
446 | |||
447 | ```rust | ||
448 | // GOOD | ||
449 | pub fn reachable_nodes(node: Node) -> FxHashSet<Node> { | ||
450 | let mut res = FxHashSet::default(); | ||
451 | go(&mut res, node); | ||
452 | res | ||
453 | } | ||
454 | fn go(acc: &mut FxHashSet<Node>, node: Node) { | ||
455 | acc.insert(node); | ||
456 | for n in node.neighbors() { | ||
457 | go(acc, n); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | // BAD | ||
462 | pub fn reachable_nodes(node: Node) -> FxHashSet<Node> { | ||
463 | let mut res = FxHashSet::default(); | ||
464 | res.insert(node); | ||
465 | for n in node.neighbors() { | ||
466 | res.extend(reachable_nodes(n)); | ||
467 | } | ||
468 | res | ||
469 | } | ||
470 | ``` | ||
471 | |||
472 | **Rational:** re-use allocations, accumulator style is more concise for complex cases. | ||
473 | |||
427 | # Style | 474 | # Style |
428 | 475 | ||
429 | ## Order of Imports | 476 | ## Order of Imports |