aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/dev/README.md3
-rw-r--r--docs/dev/style.md49
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
252In particular, I have `export RA_PROFILE='*>10'` in my shell profile. 252In particular, I have `export RA_PROFILE='*>10'` in my shell profile.
253 253
254We also have a "counting" profiler which counts number of instances of popular structs.
255It is enabled by `RA_COUNT=1`.
256
254To measure time for from-scratch analysis, use something like this: 257To 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:
6It 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. 6It 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.
7Sending small cleanup PRs (like renaming a single local variable) is encouraged. 7Sending small cleanup PRs (like renaming a single local variable) is encouraged.
8 8
9When reviewing pull requests prefer extending this document to leaving
10non-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
286Use `Vec::new` rather than `vec![]`. **Rationale:** uniformity, strength
287reduction.
288
283## Functions Over Objects 289## Functions Over Objects
284 290
285Avoid creating "doer" objects. 291Avoid creating "doer" objects.
@@ -372,6 +378,15 @@ This allows for exceptionally good performance, but leads to increased compile t
372Runtime performance obeys 80%/20% rule -- only a small fraction of code is hot. 378Runtime performance obeys 80%/20% rule -- only a small fraction of code is hot.
373Compile time **does not** obey this rule -- all code has to be compiled. 379Compile time **does not** obey this rule -- all code has to be compiled.
374 380
381## Appropriate String Types
382
383When interfacing with OS APIs, use `OsString`, even if the original source of
384data is utf-8 encoded. **Rationale:** cleanly delineates the boundary when the
385data goes into the OS-land.
386
387Use `AbsPathBuf` and `AbsPath` over `std::Path`. **Rationale:** rust-analyzer is
388a long-lived process which handles several projects at the same time. It is
389important 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.
419It is also more efficient when the caller already owns the allocation. 434It is also more efficient when the caller already owns the allocation.
420 435
421## Collection types 436## Collection Types
422 437
423Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`. 438Prefer `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
444When writing a recursive function to compute a sets of things, use an accumulator parameter instead of returning a fresh collection.
445Accumulator goes first in the list of arguments.
446
447```rust
448// GOOD
449pub fn reachable_nodes(node: Node) -> FxHashSet<Node> {
450 let mut res = FxHashSet::default();
451 go(&mut res, node);
452 res
453}
454fn 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
462pub 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