]> git.lizzy.rs Git - rust.git/commitdiff
Import rust-guidlines
authorSteve Klabnik <steve@steveklabnik.com>
Sat, 14 Feb 2015 17:02:45 +0000 (12:02 -0500)
committerSteve Klabnik <steve@steveklabnik.com>
Mon, 16 Feb 2015 22:04:16 +0000 (17:04 -0500)
at https://github.com/rust-lang/rust-guidelines/commit/16fa41b3b091e7e532c809c7145dd88b8e4a5513

Fixes #19315

59 files changed:
mk/docs.mk
src/doc/style/.gitignore [new file with mode: 0644]
src/doc/style/README.md [new file with mode: 0644]
src/doc/style/SUMMARY.md [new file with mode: 0644]
src/doc/style/changing/README.md [new file with mode: 0644]
src/doc/style/changing/post-1-0.md [new file with mode: 0644]
src/doc/style/changing/pre-1-0.md [new file with mode: 0644]
src/doc/style/changing/unclear.md [new file with mode: 0644]
src/doc/style/errors/README.md [new file with mode: 0644]
src/doc/style/errors/ergonomics.md [new file with mode: 0644]
src/doc/style/errors/handling.md [new file with mode: 0644]
src/doc/style/errors/propagation.md [new file with mode: 0644]
src/doc/style/errors/signaling.md [new file with mode: 0644]
src/doc/style/features/README.md [new file with mode: 0644]
src/doc/style/features/crates.md [new file with mode: 0644]
src/doc/style/features/functions-and-methods/README.md [new file with mode: 0644]
src/doc/style/features/functions-and-methods/convenience.md [new file with mode: 0644]
src/doc/style/features/functions-and-methods/input.md [new file with mode: 0644]
src/doc/style/features/functions-and-methods/output.md [new file with mode: 0644]
src/doc/style/features/let.md [new file with mode: 0644]
src/doc/style/features/loops.md [new file with mode: 0644]
src/doc/style/features/match.md [new file with mode: 0644]
src/doc/style/features/modules.md [new file with mode: 0644]
src/doc/style/features/traits/README.md [new file with mode: 0644]
src/doc/style/features/traits/common.md [new file with mode: 0644]
src/doc/style/features/traits/extensions.md [new file with mode: 0644]
src/doc/style/features/traits/generics.md [new file with mode: 0644]
src/doc/style/features/traits/objects.md [new file with mode: 0644]
src/doc/style/features/traits/overloading.md [new file with mode: 0644]
src/doc/style/features/traits/reuse.md [new file with mode: 0644]
src/doc/style/features/types/README.md [new file with mode: 0644]
src/doc/style/features/types/conversions.md [new file with mode: 0644]
src/doc/style/features/types/newtype.md [new file with mode: 0644]
src/doc/style/ownership/README.md [new file with mode: 0644]
src/doc/style/ownership/builders.md [new file with mode: 0644]
src/doc/style/ownership/cell-smart.md [new file with mode: 0644]
src/doc/style/ownership/constructors.md [new file with mode: 0644]
src/doc/style/ownership/destructors.md [new file with mode: 0644]
src/doc/style/ownership/raii.md [new file with mode: 0644]
src/doc/style/platform.md [new file with mode: 0644]
src/doc/style/safety/README.md [new file with mode: 0644]
src/doc/style/safety/lib-guarantees.md [new file with mode: 0644]
src/doc/style/safety/unsafe.md [new file with mode: 0644]
src/doc/style/style/README.md [new file with mode: 0644]
src/doc/style/style/braces.md [new file with mode: 0644]
src/doc/style/style/comments.md [new file with mode: 0644]
src/doc/style/style/features.md [new file with mode: 0644]
src/doc/style/style/imports.md [new file with mode: 0644]
src/doc/style/style/naming/README.md [new file with mode: 0644]
src/doc/style/style/naming/containers.md [new file with mode: 0644]
src/doc/style/style/naming/conversions.md [new file with mode: 0644]
src/doc/style/style/naming/iterators.md [new file with mode: 0644]
src/doc/style/style/naming/ownership.md [new file with mode: 0644]
src/doc/style/style/optional.md [new file with mode: 0644]
src/doc/style/style/organization.md [new file with mode: 0644]
src/doc/style/style/whitespace.md [new file with mode: 0644]
src/doc/style/testing/README.md [new file with mode: 0644]
src/doc/style/testing/unit.md [new file with mode: 0644]
src/doc/style/todo.md [new file with mode: 0644]

index 2a5a847d2a42508e4e8caa20a0eea284d9eccefa..04357e8fbae19b38ab00acca318fdcce8808db7a 100644 (file)
@@ -73,7 +73,7 @@ RUSTBOOK = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(RUSTBOOK_EXE)
 
 D := $(S)src/doc
 
-DOC_TARGETS := trpl
+DOC_TARGETS := trpl style
 COMPILER_DOC_TARGETS :=
 DOC_L10N_TARGETS :=
 
@@ -275,3 +275,9 @@ trpl: doc/book/index.html
 doc/book/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/trpl/*.md) | doc/
        $(Q)rm -rf doc/book
        $(Q)$(RUSTBOOK) build $(S)src/doc/trpl doc/book
+
+style: doc/style/index.html
+
+doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/
+       $(Q)rm -rf doc/style
+       $(Q)$(RUSTBOOK) build $(S)src/doc/style doc/style
diff --git a/src/doc/style/.gitignore b/src/doc/style/.gitignore
new file mode 100644 (file)
index 0000000..b8c1e63
--- /dev/null
@@ -0,0 +1,7 @@
+# Generated when running `gitbook build`
+_book/
+
+*~
+*.bak
+*.swp
+.DS_Store
diff --git a/src/doc/style/README.md b/src/doc/style/README.md
new file mode 100644 (file)
index 0000000..d84d3bd
--- /dev/null
@@ -0,0 +1,77 @@
+% Rust Guidelines [working title]
+
+This document collects the emerging principles, conventions, abstractions, and
+best practices for writing Rust code.
+
+Since Rust is evolving at a rapid pace, these guidelines are
+preliminary. The hope is that writing them down explicitly will help
+drive discussion, consensus and adoption.
+
+Whenever feasible, guidelines provide specific examples from Rust's standard
+libraries.
+
+For now, you can find a rendered snapshot at
+[http://aturon.github.io/](http://aturon.github.io/).  After
+[some infrastructure work](https://github.com/aturon/rust-guidelines/issues/17), the snapshot will move somewhere more
+official.
+
+### Building the document
+
+Like http://rustbyexample.com/, this guidelines document is written in
+the [`gitbook`](https://github.com/GitbookIO/gitbook) style. It can be
+compiled with a prototype tool,
+[`rustbook`](https://github.com/aturon/rust-book) that provides a
+minimal subset of `gitbook`'s functionality on top of `rustdoc`.
+
+### Guideline statuses
+
+Every guideline has a status:
+
+* **[FIXME]**: Marks places where there is more work to be done. In
+  some cases, that just means going through the RFC process.
+
+* **[FIXME #NNNNN]**: Like **[FIXME]**, but links to the issue tracker.
+
+* **[RFC #NNNN]**: Marks accepted guidelines, linking to the rust-lang
+  RFC establishing them.
+
+### Guideline stabilization
+
+One purpose of these guidelines is to reach decisions on a number of
+cross-cutting API and stylistic choices. Discussion and development of
+the guidelines will happen primarily on http://discuss.rust-lang.org/,
+using the Guidelines category. Discussion can also occur on the
+[guidelines issue tracker](https://github.com/rust-lang/rust-guidelines).
+
+Guidelines that are under development or discussion will be marked with the
+status **[FIXME]**, with a link to the issue tracker when appropriate.
+
+Once a concrete guideline is ready to be proposed, it should be filed
+as an [FIXME: needs RFC](https://github.com/rust-lang/rfcs). If the RFC is
+accepted, the official guidelines will be updated to match, and will
+include the tag **[RFC #NNNN]** linking to the RFC document.
+
+### What's in this document
+
+This document is broken into four parts:
+
+* **[Style](style/README.md)** provides a set of rules governing naming conventions,
+  whitespace, and other stylistic issues.
+
+* **[Guidelines by Rust feature](features/README.md)** places the focus on each of
+  Rust's features, starting from expressions and working the way out toward
+  crates, dispensing guidelines relevant to each.
+
+* **Topical guidelines and patterns**. The rest of the document proceeds by
+  cross-cutting topic, starting with
+  [Ownership and resources](ownership/README.md).
+
+* **[APIs for a changing Rust](changing/README.md)**
+  discusses the forward-compatibility hazards, especially those that interact
+  with the pre-1.0 library stabilization process.
+
+> **[FIXME]** Add cross-references throughout this document to the tutorial,
+> reference manual, and other guides.
+
+> **[FIXME]** What are some _non_-goals, _non_-principles, or _anti_-patterns that
+> we should document?
diff --git a/src/doc/style/SUMMARY.md b/src/doc/style/SUMMARY.md
new file mode 100644 (file)
index 0000000..41bc08f
--- /dev/null
@@ -0,0 +1,54 @@
+# Summary
+
+* [Style](style/README.md)
+    * [Whitespace](style/whitespace.md)
+    * [Comments](style/comments.md)
+    * [Braces, semicolons, commas](style/braces.md)
+    * [Naming](style/naming/README.md)
+        * [Ownership variants](style/naming/ownership.md)
+        * [Containers/wrappers](style/naming/containers.md)
+        * [Conversions](style/naming/conversions.md)
+        * [Iterators](style/naming/iterators.md)
+    * [Imports](style/imports.md)
+    * [Organization](style/organization.md)
+* [Guidelines by Rust feature](features/README.md)
+    * [Let binding](features/let.md)
+    * [Pattern matching](features/match.md)
+    * [Loops](features/loops.md)
+    * [Functions and methods](features/functions-and-methods/README.md)
+        * [Input](features/functions-and-methods/input.md)
+        * [Output](features/functions-and-methods/output.md)
+        * [For convenience](features/functions-and-methods/convenience.md)
+    * [Types](features/types/README.md)
+        * [Conversions](features/types/conversions.md)
+        * [The newtype pattern](features/types/newtype.md)
+    * [Traits](features/traits/README.md)
+        * [For generics](features/traits/generics.md)
+        * [For objects](features/traits/objects.md)
+        * [For overloading](features/traits/overloading.md)
+        * [For extensions](features/traits/extensions.md)
+        * [For reuse](features/traits/reuse.md)
+        * [Common traits](features/traits/common.md)
+    * [Modules](features/modules.md)
+    * [Crates](features/crates.md)
+* [Ownership and resources](ownership/README.md)
+    * [Constructors](ownership/constructors.md)
+    * [Builders](ownership/builders.md)
+    * [Destructors](ownership/destructors.md)
+    * [RAII](ownership/raii.md)
+    * [Cells and smart pointers](ownership/cell-smart.md)
+* [Errors](errors/README.md)
+    * [Signaling](errors/signaling.md)
+    * [Handling](errors/handling.md)
+    * [Propagation](errors/propagation.md)
+    * [Ergonomics](errors/ergonomics.md)
+* [Safety and guarantees](safety/README.md)
+    * [Using unsafe](safety/unsafe.md)
+    * [Library guarantees](safety/lib-guarantees.md)
+* [Testing](testing/README.md)
+    * [Unit testing](testing/unit.md)
+* [FFI, platform-specific code](platform.md)
+* [APIs for a changing Rust](changing/README.md)
+    * [Pre-1.0 changes](changing/pre-1-0.md)
+    * [Post-1.0 changes](changing/post-1-0.md)
+    * [Timing unclear](changing/unclear.md)
diff --git a/src/doc/style/changing/README.md b/src/doc/style/changing/README.md
new file mode 100644 (file)
index 0000000..38e76f6
--- /dev/null
@@ -0,0 +1,5 @@
+% API design for a changing Rust
+
+A number of planned Rust features will drastically affect the API design
+story. This section collects some of the biggest features with concrete examples
+of how the API will change.
diff --git a/src/doc/style/changing/post-1-0.md b/src/doc/style/changing/post-1-0.md
new file mode 100644 (file)
index 0000000..7ac1c83
--- /dev/null
@@ -0,0 +1,12 @@
+% Post-1.0 changes
+
+### Higher-kinded types
+
+* A trait encompassing both `Iterable<T>` for some fixed `T` and
+  `FromIterator<U>` for _all_ `U` (where HKT comes in).  The train
+  could provide e.g. a default `map` method producing the same kind of
+  the container, but with a new type parameter.
+
+* **Monadic-generic programming**? Can we add this without deprecating
+  huge swaths of the API (including `Option::map`, `option::collect`,
+  `result::collect`, `try!` etc.
diff --git a/src/doc/style/changing/pre-1-0.md b/src/doc/style/changing/pre-1-0.md
new file mode 100644 (file)
index 0000000..adadfe3
--- /dev/null
@@ -0,0 +1,17 @@
+% Pre-1.0 changes
+
+### `std` facade
+
+We should revisit some APIs in `libstd` now that the facade effort is complete.
+
+For example, the treatment of environment variables in the new
+`Command` API is waiting on access to hashtables before being
+approved.
+
+### Trait reform
+
+Potential for standard conversion traits (`to`, `into`, `as`).
+
+Probably many other opportunities here.
+
+### Unboxed closures
diff --git a/src/doc/style/changing/unclear.md b/src/doc/style/changing/unclear.md
new file mode 100644 (file)
index 0000000..e4b8a98
--- /dev/null
@@ -0,0 +1,28 @@
+% Changes with unclear timing
+
+### Associated items
+
+* Many traits that currently take type parameters should instead use associated
+  types; this will _drastically_ simplify signatures in some cases.
+
+* Associated constants would be useful in a few places, e.g. traits for
+  numerics, traits for paths.
+
+### Anonymous, unboxed return types (aka `impl Trait` types)
+
+* See https://github.com/rust-lang/rfcs/pull/105
+
+* Could affect API design in several places, e.g. the `Iterator` trait.
+
+### Default type parameters
+
+We are already using this in a few places (e.g. `HashMap`), but it's
+feature-gated.
+
+### Compile-time function evaluation (CTFE)
+
+https://github.com/mozilla/rust/issues/11621
+
+### Improved constant folding
+
+https://github.com/rust-lang/rust/issues/7834
diff --git a/src/doc/style/errors/README.md b/src/doc/style/errors/README.md
new file mode 100644 (file)
index 0000000..444da26
--- /dev/null
@@ -0,0 +1,3 @@
+% Errors
+
+> **[FIXME]** Add some general text here.
diff --git a/src/doc/style/errors/ergonomics.md b/src/doc/style/errors/ergonomics.md
new file mode 100644 (file)
index 0000000..33f1e82
--- /dev/null
@@ -0,0 +1,66 @@
+% Ergonomic error handling
+
+Error propagation with raw `Result`s can require tedious matching and
+repackaging. This tedium is largely alleviated by the `try!` macro,
+and can be completely removed (in some cases) by the "`Result`-`impl`"
+pattern.
+
+### The `try!` macro
+
+Prefer
+
+```rust
+use std::io::{File, Open, Write, IoError};
+
+struct Info {
+    name: String,
+    age: int,
+    rating: int
+}
+
+fn write_info(info: &Info) -> Result<(), IoError> {
+    let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
+                                   Open, Write);
+    // Early return on error
+    try!(file.write_line(format!("name: {}", info.name).as_slice()));
+    try!(file.write_line(format!("age: {}", info.age).as_slice()));
+    try!(file.write_line(format!("rating: {}", info.rating).as_slice()));
+    return Ok(());
+}
+```
+
+over
+
+```rust
+use std::io::{File, Open, Write, IoError};
+
+struct Info {
+    name: String,
+    age: int,
+    rating: int
+}
+
+fn write_info(info: &Info) -> Result<(), IoError> {
+    let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
+                                   Open, Write);
+    // Early return on error
+    match file.write_line(format!("name: {}", info.name).as_slice()) {
+        Ok(_) => (),
+        Err(e) => return Err(e)
+    }
+    match file.write_line(format!("age: {}", info.age).as_slice()) {
+        Ok(_) => (),
+        Err(e) => return Err(e)
+    }
+    return file.write_line(format!("rating: {}", info.rating).as_slice());
+}
+```
+
+See
+[the `result` module documentation](http://static.rust-lang.org/doc/master/std/result/index.html#the-try!-macro)
+for more details.
+
+### The `Result`-`impl` pattern [FIXME]
+
+> **[FIXME]** Document the way that the `io` module uses trait impls
+> on `IoResult` to painlessly propagate errors.
diff --git a/src/doc/style/errors/handling.md b/src/doc/style/errors/handling.md
new file mode 100644 (file)
index 0000000..cc5b5b4
--- /dev/null
@@ -0,0 +1,7 @@
+% Handling errors
+
+### Use task isolation to cope with failure. [FIXME]
+
+> **[FIXME]** Explain how to isolate tasks and detect task failure for recovery.
+
+### Consuming `Result` [FIXME]
diff --git a/src/doc/style/errors/propagation.md b/src/doc/style/errors/propagation.md
new file mode 100644 (file)
index 0000000..0a347cd
--- /dev/null
@@ -0,0 +1,8 @@
+% Propagation
+
+> **[FIXME]** We need guidelines on how to layer error information up a stack of
+> abstractions.
+
+### Error interoperation [FIXME]
+
+> **[FIXME]** Document the `FromError` infrastructure.
diff --git a/src/doc/style/errors/signaling.md b/src/doc/style/errors/signaling.md
new file mode 100644 (file)
index 0000000..95db4f8
--- /dev/null
@@ -0,0 +1,125 @@
+% Signaling errors [RFC #236]
+
+> The guidelines below were approved by [RFC #236](https://github.com/rust-lang/rfcs/pull/236).
+
+Errors fall into one of three categories:
+
+* Catastrophic errors, e.g. out-of-memory.
+* Contract violations, e.g. wrong input encoding, index out of bounds.
+* Obstructions, e.g. file not found, parse error.
+
+The basic principle of the convention is that:
+
+* Catastrophic errors and programming errors (bugs) can and should only be
+recovered at a *coarse grain*, i.e. a task boundary.
+* Obstructions preventing an operation should be reported at a maximally *fine
+grain* -- to the immediate invoker of the operation.
+
+## Catastrophic errors
+
+An error is _catastrophic_ if there is no meaningful way for the current task to
+continue after the error occurs.
+
+Catastrophic errors are _extremely_ rare, especially outside of `libstd`.
+
+**Canonical examples**: out of memory, stack overflow.
+
+### For catastrophic errors, panic
+
+For errors like stack overflow, Rust currently aborts the process, but
+could in principle panic, which (in the best case) would allow
+reporting and recovery from a supervisory task.
+
+## Contract violations
+
+An API may define a contract that goes beyond the type checking enforced by the
+compiler. For example, slices support an indexing operation, with the contract
+that the supplied index must be in bounds.
+
+Contracts can be complex and involve more than a single function invocation. For
+example, the `RefCell` type requires that `borrow_mut` not be called until all
+existing borrows have been relinquished.
+
+### For contract violations, panic
+
+A contract violation is always a bug, and for bugs we follow the Erlang
+philosophy of "let it crash": we assume that software *will* have bugs, and we
+design coarse-grained task boundaries to report, and perhaps recover, from these
+bugs.
+
+### Contract design
+
+One subtle aspect of these guidelines is that the contract for a function is
+chosen by an API designer -- and so the designer also determines what counts as
+a violation.
+
+This RFC does not attempt to give hard-and-fast rules for designing
+contracts. However, here are some rough guidelines:
+
+* Prefer expressing contracts through static types whenever possible.
+
+* It *must* be possible to write code that uses the API without violating the
+  contract.
+
+* Contracts are most justified when violations are *inarguably* bugs -- but this
+  is surprisingly rare.
+
+* Consider whether the API client could benefit from the contract-checking
+  logic.  The checks may be expensive. Or there may be useful programming
+  patterns where the client does not want to check inputs before hand, but would
+  rather attempt the operation and then find out whether the inputs were invalid.
+
+* When a contract violation is the *only* kind of error a function may encounter
+  -- i.e., there are no obstructions to its success other than "bad" inputs --
+  using `Result` or `Option` instead is especially warranted. Clients can then use
+  `unwrap` to assert that they have passed valid input, or re-use the error
+  checking done by the API for their own purposes.
+
+* When in doubt, use loose contracts and instead return a `Result` or `Option`.
+
+## Obstructions
+
+An operation is *obstructed* if it cannot be completed for some reason, even
+though the operation's contract has been satisfied. Obstructed operations may
+have (documented!) side effects -- they are not required to roll back after
+encountering an obstruction.  However, they should leave the data structures in
+a "coherent" state (satisfying their invariants, continuing to guarantee safety,
+etc.).
+
+Obstructions may involve external conditions (e.g., I/O), or they may involve
+aspects of the input that are not covered by the contract.
+
+**Canonical examples**: file not found, parse error.
+
+### For obstructions, use `Result`
+
+The
+[`Result<T,E>` type](http://static.rust-lang.org/doc/master/std/result/index.html)
+represents either a success (yielding `T`) or failure (yielding `E`). By
+returning a `Result`, a function allows its clients to discover and react to
+obstructions in a fine-grained way.
+
+#### What about `Option`?
+
+The `Option` type should not be used for "obstructed" operations; it
+should only be used when a `None` return value could be considered a
+"successful" execution of the operation.
+
+This is of course a somewhat subjective question, but a good litmus
+test is: would a reasonable client ever ignore the result? The
+`Result` type provides a lint that ensures the result is actually
+inspected, while `Option` does not, and this difference of behavior
+can help when deciding between the two types.
+
+Another litmus test: can the operation be understood as asking a
+question (possibly with sideeffects)? Operations like `pop` on a
+vector can be viewed as asking for the contents of the first element,
+with the side effect of removing it if it exists -- with an `Option`
+return value.
+
+## Do not provide both `Result` and `panic!` variants.
+
+An API should not provide both `Result`-producing and `panic`king versions of an
+operation. It should provide just the `Result` version, allowing clients to use
+`try!` or `unwrap` instead as needed. This is part of the general pattern of
+cutting down on redundant variants by instead using method chaining.
diff --git a/src/doc/style/features/README.md b/src/doc/style/features/README.md
new file mode 100644 (file)
index 0000000..0965750
--- /dev/null
@@ -0,0 +1,9 @@
+% Guidelines by language feature
+
+Rust provides a unique combination of language features, some new and some
+old. This section gives guidance on when and how to use Rust's features, and
+brings attention to some of the tradeoffs between different features.
+
+Notably missing from this section is an in-depth discussion of Rust's pointer
+types (both built-in and in the library). The topic of pointers is discussed at
+length in a [separate section on ownership](../ownership/README.md).
diff --git a/src/doc/style/features/crates.md b/src/doc/style/features/crates.md
new file mode 100644 (file)
index 0000000..4748b05
--- /dev/null
@@ -0,0 +1,6 @@
+% Crates
+
+> **[FIXME]** What general guidelines should we provide for crate design?
+
+> Possible topics: facades; per-crate preludes (to be imported as globs);
+> "lib.rs"
diff --git a/src/doc/style/features/functions-and-methods/README.md b/src/doc/style/features/functions-and-methods/README.md
new file mode 100644 (file)
index 0000000..2dcfc38
--- /dev/null
@@ -0,0 +1,43 @@
+% Functions and methods
+
+### Prefer methods to functions if there is a clear receiver. **[FIXME: needs RFC]**
+
+Prefer
+
+```rust
+impl Foo {
+    pub fn frob(&self, w: widget) { ... }
+}
+```
+
+over
+
+```rust
+pub fn frob(foo: &Foo, w: widget) { ... }
+```
+
+for any operation that is clearly associated with a particular
+type.
+
+Methods have numerous advantages over functions:
+* They do not need to be imported or qualified to be used: all you
+  need is a value of the appropriate type.
+* Their invocation performs autoborrowing (including mutable borrows).
+* They make it easy to answer the question "what can I do with a value
+  of type `T`" (especially when using rustdoc).
+* They provide `self` notation, which is more concise and often more
+  clearly conveys ownership distinctions.
+
+> **[FIXME]** Revisit these guidelines with
+> [UFCS](https://github.com/nick29581/rfcs/blob/ufcs/0000-ufcs.md) and
+> conventions developing around it.
+
+
+
+### Guidelines for inherent methods. **[FIXME]**
+
+> **[FIXME]** We need guidelines for when to provide inherent methods on a type,
+> versus methods through a trait or functions.
+
+> **NOTE**: Rules for method resolution around inherent methods are in flux,
+> which may impact the guidelines.
diff --git a/src/doc/style/features/functions-and-methods/convenience.md b/src/doc/style/features/functions-and-methods/convenience.md
new file mode 100644 (file)
index 0000000..69fd377
--- /dev/null
@@ -0,0 +1,43 @@
+% Convenience methods
+
+### Provide small, coherent sets of convenience methods. **[FIXME: needs RFC]**
+
+_Convenience methods_ wrap up existing functionality in a more convenient
+way. The work done by a convenience method varies widely:
+
+* _Re-providing functions as methods_. For example, the `std::path::Path` type
+  provides methods like `stat` on `Path`s that simply invoke the corresponding
+  function in `std::io::fs`.
+* _Skipping through conversions_. For example, the `str` type provides a
+  `.len()` convenience method which is also expressible as `.as_bytes().len()`.
+  Sometimes the conversion is more complex: the `str` module also provides
+  `from_chars`, which encapsulates a simple use of iterators.
+* _Encapsulating common arguments_. For example, vectors of `&str`s
+  provide a `connect` as well as a special case, `concat`, that is expressible
+  using `connect` with a fixed separator of `""`.
+* _Providing more efficient special cases_. The `connect` and `concat` example
+  also applies here: singling out `concat` as a special case allows for a more
+  efficient implementation.
+
+  Note, however, that the `connect` method actually detects the special case
+  internally and invokes `concat`. Usually, it is not necessary to add a public
+  convenience method just for efficiency gains; there should also be a
+  _conceptual_ reason to add it, e.g. because it is such a common special case.
+
+It is tempting to add convenience methods in a one-off, haphazard way as
+common use patterns emerge. Avoid this temptation, and instead _design_ small,
+coherent sets of convenience methods that are easy to remember:
+
+* _Small_: Avoid combinatorial explosions of convenience methods. For example,
+  instead of adding `_str` variants of methods that provide a `str` output,
+  instead ensure that the normal output type of methods is easily convertible to
+  `str`.
+* _Coherent_: Look for small groups of convenience methods that make sense to
+  include together. For example, the `Path` API mentioned above includes a small
+  selection of the most common filesystem operations that take a `Path`
+  argument.  If one convenience method strongly suggests the existence of others,
+  consider adding the whole group.
+* _Memorable_: It is not worth saving a few characters of typing if you have to
+  look up the name of a convenience method every time you use it. Add
+  convenience methods with names that are obvious and easy to remember, and add
+  them for the most common or painful use cases.
diff --git a/src/doc/style/features/functions-and-methods/input.md b/src/doc/style/features/functions-and-methods/input.md
new file mode 100644 (file)
index 0000000..b0912ea
--- /dev/null
@@ -0,0 +1,201 @@
+% Input to functions and methods
+
+### Let the client decide when to copy and where to place data. [FIXME: needs RFC]
+
+#### Copying:
+
+Prefer
+
+```rust
+fn foo(b: Bar) {
+   // use b as owned, directly
+}
+```
+
+over
+
+```rust
+fn foo(b: &Bar) {
+    let b = b.clone();
+    // use b as owned after cloning
+}
+```
+
+If a function requires ownership of a value of unknown type `T`, but does not
+otherwise need to make copies, the function should take ownership of the
+argument (pass by value `T`) rather than using `.clone()`. That way, the caller
+can decide whether to relinquish ownership or to `clone`.
+
+Similarly, the `Copy` trait bound should only be demanded it when absolutely
+needed, not as a way of signaling that copies should be cheap to make.
+
+#### Placement:
+
+Prefer
+
+```rust
+fn foo(b: Bar) -> Bar { ... }
+```
+
+over
+
+```rust
+fn foo(b: Box<Bar>) -> Box<Bar> { ... }
+```
+
+for concrete types `Bar` (as opposed to trait objects). This way, the caller can
+decide whether to place data on the stack or heap. No overhead is imposed by
+letting the caller determine the placement.
+
+### Minimize assumptions about parameters. [FIXME: needs RFC]
+
+The fewer assumptions a function makes about its inputs, the more widely usable
+it becomes.
+
+#### Minimizing assumptions through generics:
+
+Prefer
+
+```rust
+fn foo<T: Iterator<int>>(c: T) { ... }
+```
+
+over any of
+
+```rust
+fn foo(c: &[int]) { ... }
+fn foo(c: &Vec<int>) { ... }
+fn foo(c: &SomeOtherCollection<int>) { ... }
+```
+
+if the function only needs to iterate over the data.
+
+More generally, consider using generics to pinpoint the assumptions a function
+needs to make about its arguments.
+
+On the other hand, generics can make it more difficult to read and understand a
+function's signature. Aim for "natural" parameter types that a neither overly
+concrete nor overly abstract. See the discussion on
+[traits](../../traits/README.md) for more guidance.
+
+
+#### Minimizing ownership assumptions:
+
+Prefer either of
+
+```rust
+fn foo(b: &Bar) { ... }
+fn foo(b: &mut Bar) { ... }
+```
+
+over
+
+```rust
+fn foo(b: Bar) { ... }
+```
+
+That is, prefer borrowing arguments rather than transferring ownership, unless
+ownership is actually needed.
+
+### Prefer compound return types to out-parameters. [FIXME: needs RFC]
+
+Prefer
+
+```rust
+fn foo() -> (Bar, Bar)
+```
+
+over
+
+```rust
+fn foo(output: &mut Bar) -> Bar
+```
+
+for returning multiple `Bar` values.
+
+Compound return types like tuples and structs are efficiently compiled
+and do not require heap allocation. If a function needs to return
+multiple values, it should do so via one of these types.
+
+The primary exception: sometimes a function is meant to modify data
+that the caller already owns, for example to re-use a buffer:
+
+```rust
+fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>
+```
+
+(From the [Reader trait](http://static.rust-lang.org/doc/master/std/io/trait.Reader.html#tymethod.read).)
+
+### Consider validating arguments, statically or dynamically. [FIXME: needs RFC]
+
+_Note: this material is closely related to
+  [library-level guarantees](../../safety/lib-guarantees.md)._
+
+Rust APIs do _not_ generally follow the
+[robustness principle](http://en.wikipedia.org/wiki/Robustness_principle): "be
+conservative in what you send; be liberal in what you accept".
+
+Instead, Rust code should _enforce_ the validity of input whenever practical.
+
+Enforcement can be achieved through the following mechanisms (listed
+in order of preference).
+
+#### Static enforcement:
+
+Choose an argument type that rules out bad inputs.
+
+For example, prefer
+
+```rust
+fn foo(a: ascii::Ascii) { ... }
+```
+
+over
+
+```rust
+fn foo(a: u8) { ... }
+```
+
+Note that
+[`ascii::Ascii`](http://static.rust-lang.org/doc/master/std/ascii/struct.Ascii.html)
+is a _wrapper_ around `u8` that guarantees the highest bit is zero; see
+[newtype patterns]() for more details on creating typesafe wrappers.
+
+Static enforcement usually comes at little run-time cost: it pushes the
+costs to the boundaries (e.g. when a `u8` is first converted into an
+`Ascii`). It also catches bugs early, during compilation, rather than through
+run-time failures.
+
+On the other hand, some properties are difficult or impossible to
+express using types.
+
+#### Dynamic enforcement:
+
+Validate the input as it is processed (or ahead of time, if necessary).  Dynamic
+checking is often easier to implement than static checking, but has several
+downsides:
+
+1. Runtime overhead (unless checking can be done as part of processing the input).
+2. Delayed detection of bugs.
+3. Introduces failure cases, either via `fail!` or `Result`/`Option` types (see
+   the [error handling guidelines](../../errors/README.md)), which must then be
+   dealt with by client code.
+
+#### Dynamic enforcement with `debug_assert!`:
+
+Same as dynamic enforcement, but with the possibility of easily turning off
+expensive checks for production builds.
+
+#### Dynamic enforcement with opt-out:
+
+Same as dynamic enforcement, but adds sibling functions that opt out of the
+checking.
+
+The convention is to mark these opt-out functions with a suffix like
+`_unchecked` or by placing them in a `raw` submodule.
+
+The unchecked functions can be used judiciously in cases where (1) performance
+dictates avoiding checks and (2) the client is otherwise confident that the
+inputs are valid.
+
+> **[FIXME]** Should opt-out functions be marked `unsafe`?
diff --git a/src/doc/style/features/functions-and-methods/output.md b/src/doc/style/features/functions-and-methods/output.md
new file mode 100644 (file)
index 0000000..a83e2b7
--- /dev/null
@@ -0,0 +1,56 @@
+% Output from functions and methods
+
+### Don't overpromise. [FIXME]
+
+> **[FIXME]** Add discussion of overly-specific return types,
+> e.g. returning a compound iterator type rather than hiding it behind
+> a use of newtype.
+
+### Let clients choose what to throw away. [FIXME: needs RFC]
+
+#### Return useful intermediate results:
+
+Many functions that answer a question also compute interesting related data.  If
+this data is potentially of interest to the client, consider exposing it in the
+API.
+
+Prefer
+
+```rust
+struct SearchResult {
+    found: bool,          // item in container?
+    expected_index: uint  // what would the item's index be?
+}
+
+fn binary_search(&self, k: Key) -> SearchResult
+```
+or
+
+```rust
+fn binary_search(&self, k: Key) -> (bool, uint)
+```
+
+over
+
+```rust
+fn binary_search(&self, k: Key) -> bool
+```
+
+#### Yield back ownership:
+
+Prefer
+
+```rust
+fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>>
+```
+
+over
+
+```rust
+fn from_utf8_owned(vv: Vec<u8>) -> Option<String>
+```
+
+The `from_utf8_owned` function gains ownership of a vector.  In the successful
+case, the function consumes its input, returning an owned string without
+allocating or copying. In the unsuccessful case, however, the function returns
+back ownership of the original slice.
diff --git a/src/doc/style/features/let.md b/src/doc/style/features/let.md
new file mode 100644 (file)
index 0000000..87117a2
--- /dev/null
@@ -0,0 +1,103 @@
+% Let binding
+
+### Always separately bind RAII guards. [FIXME: needs RFC]
+
+Prefer
+
+```rust
+fn use_mutex(m: sync::mutex::Mutex<int>) {
+    let guard = m.lock();
+    do_work(guard);
+    drop(guard); // unlock the lock
+    // do other work
+}
+```
+
+over
+
+```rust
+fn use_mutex(m: sync::mutex::Mutex<int>) {
+    do_work(m.lock());
+    // do other work
+}
+```
+
+As explained in the [RAII guide](../ownership/raii.md), RAII guards are values
+that represent ownership of some resource and whose destructor releases the
+resource. Because the lifetime of guards are significant, they should always be
+explicitly `let`-bound to make the lifetime clear. Consider using an explicit
+`drop` to release the resource early.
+
+### Prefer conditional expressions to deferred initialization. [FIXME: needs RFC]
+
+Prefer
+
+```rust
+let foo = match bar {
+    Baz  => 0,
+    Quux => 1
+};
+```
+
+over
+
+```rust
+let foo;
+match bar {
+    Baz  => {
+        foo = 0;
+    }
+    Quux => {
+        foo = 1;
+    }
+}
+```
+
+unless the conditions for initialization are too complex to fit into a simple
+conditional expression.
+
+### Use type annotations for clarification; prefer explicit generics when inference fails. [FIXME: needs RFC]
+
+Prefer
+
+```rust
+s.iter().map(|x| x * 2)
+        .collect::<Vec<_>>()
+```
+
+over
+
+```rust
+let v: Vec<_> = s.iter().map(|x| x * 2)
+                        .collect();
+```
+
+When the type of a value might be unclear to the _reader_ of the code, consider
+explicitly annotating it in a `let`.
+
+On the other hand, when the type is unclear to the _compiler_, prefer to specify
+the type by explicit generics instantiation, which is usually more clear.
+
+### Shadowing [FIXME]
+
+> **[FIXME]** Repeatedly shadowing a binding is somewhat common in Rust code. We
+> need to articulate a guideline on when it is appropriate/useful and when not.
+
+### Prefer immutable bindings. [FIXME: needs RFC]
+
+Use `mut` bindings to signal the span during which a value is mutated:
+
+```rust
+let mut v = Vec::new();
+// push things onto v
+let v = v;
+// use v immutably henceforth
+```
+
+### Prefer to bind all `struct` or tuple fields. [FIXME: needs RFC]
+
+When consuming a `struct` or tuple via a `let`, bind all of the fields rather
+than using `..` to elide the ones you don't need. The benefit is that when
+fields are added, the compiler will pinpoint all of the places where that type
+of value was consumed, which will often need to be adjusted to take the new
+field properly into account.
diff --git a/src/doc/style/features/loops.md b/src/doc/style/features/loops.md
new file mode 100644 (file)
index 0000000..b144825
--- /dev/null
@@ -0,0 +1,13 @@
+% Loops
+
+### Prefer `for` to `while`. [FIXME: needs RFC]
+
+A `for` loop is preferable to a `while` loop, unless the loop counts in a
+non-uniform way (making it difficult to express using `for`).
+
+### Guidelines for `loop`. [FIXME]
+
+> **[FIXME]** When is `loop` recommended? Some possibilities:
+> * For optimistic retry algorithms
+> * For servers
+> * To avoid mutating local variables sometimes needed to fit `while`
diff --git a/src/doc/style/features/match.md b/src/doc/style/features/match.md
new file mode 100644 (file)
index 0000000..131e0fa
--- /dev/null
@@ -0,0 +1,26 @@
+% Pattern matching
+
+### Dereference `match` targets when possible. [FIXME: needs RFC]
+
+Prefer
+
+~~~~
+match *foo {
+    X(...) => ...
+    Y(...) => ...
+}
+~~~~
+
+over
+
+~~~~
+match foo {
+    box X(...) => ...
+    box Y(...) => ...
+}
+~~~~
+
+<!-- ### Clearly indicate important scopes. **[FIXME: needs RFC]** -->
+
+<!-- If it is important that the destructor for a value be executed at a specific -->
+<!-- time, clearly bind that value using a standalone `let` -->
diff --git a/src/doc/style/features/modules.md b/src/doc/style/features/modules.md
new file mode 100644 (file)
index 0000000..04aae22
--- /dev/null
@@ -0,0 +1,133 @@
+% Modules
+
+> **[FIXME]** What general guidelines should we provide for module design?
+
+> We should discuss visibility, nesting, `mod.rs`, and any interesting patterns
+> around modules.
+
+### Headers [FIXME: needs RFC]
+
+Organize module headers as follows:
+  1. [Imports](../style/imports.md).
+  1. `mod` declarations.
+  1. `pub mod` declarations.
+
+### Avoid `path` directives. [FIXME: needs RFC]
+
+Avoid using `#[path="..."]` directives; make the file system and
+module hierarchy match, instead.
+
+### Use the module hirearchy to organize APIs into coherent sections. [FIXME]
+
+> **[FIXME]** Flesh this out with examples; explain what a "coherent
+> section" is with examples.
+>
+> The module hirearchy defines both the public and internal API of your module.
+> Breaking related functionality into submodules makes it understandable to both
+> users and contributors to the module.
+
+### Place modules in their own file. [FIXME: needs RFC]
+
+> **[FIXME]**
+> - "<100 lines" is arbitrary, but it's a clearer recommendation
+>   than "~1 page" or similar suggestions that vary by screen size, etc.
+
+For all except very short modules (<100 lines) and [tests](../testing/README.md),
+place the module `foo` in a separate file, as in:
+
+```rust
+pub mod foo;
+
+// in foo.rs or foo/mod.rs
+pub fn bar() { println!("..."); }
+/* ... */
+```
+
+rather than declaring it inline:
+
+```rust
+pub mod foo {
+    pub fn bar() { println!("..."); }
+    /* ... */
+}
+```
+
+#### Use subdirectories for modules with children. [FIXME: needs RFC]
+
+For modules that themselves have submodules, place the module in a separate
+directory (e.g., `bar/mod.rs` for a module `bar`) rather than the same directory.
+
+Note the structure of
+[`std::io`](http://doc.rust-lang.org/std/io/). Many of the submodules lack
+children, like
+[`io::fs`](http://doc.rust-lang.org/std/io/fs/)
+and
+[`io::stdio`](http://doc.rust-lang.org/std/io/stdio/).
+On the other hand,
+[`io::net`](http://doc.rust-lang.org/std/io/net/)
+contains submodules, so it lives in a separate directory:
+
+```
+io/mod.rs
+   io/extensions.rs
+   io/fs.rs
+   io/net/mod.rs
+          io/net/addrinfo.rs
+          io/net/ip.rs
+          io/net/tcp.rs
+          io/net/udp.rs
+          io/net/unix.rs
+   io/pipe.rs
+   ...
+```
+
+While it is possible to define all of `io` within a single directory,
+mirroring the module hirearchy in the directory structure makes
+submodules of `io::net` easier to find.
+
+### Consider top-level definitions or reexports. [FIXME: needs RFC]
+
+For modules with submodules,
+define or [reexport](http://doc.rust-lang.org/std/io/#reexports) commonly used
+definitions at the top level:
+
+* Functionality relevant to the module itself or to many of its
+  children should be defined in `mod.rs`.
+* Functionality specific to a submodule should live in that
+  submodule. Reexport at the top level for the most important or
+  common definitions.
+
+For example,
+[`IoError`](http://doc.rust-lang.org/std/io/struct.IoError.html)
+is defined in `io/mod.rs`, since it pertains to the entirety of `io`,
+while
+[`TcpStream`](http://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
+is defined in `io/net/tcp.rs` and reexported in the `io` module.
+
+### Use internal module hirearchies for organization. [FIXME: needs RFC]
+
+> **[FIXME]**
+> - Referencing internal modules from the standard library is subject to
+>   becoming outdated.
+
+Internal module hirearchies (i.e., private submodules) may be used to
+hide implementation details that are not part of the module's API.
+
+For example, in [`std::io`](http://doc.rust-lang.org/std/io/), `mod mem`
+provides implementations for
+[`BufReader`](http://doc.rust-lang.org/std/io/struct.BufReader.html)
+and
+[`BufWriter`](http://doc.rust-lang.org/std/io/struct.BufWriter.html),
+but these are re-exported in `io/mod.rs` at the top level of the module:
+
+```rust
+// libstd/io/mod.rs
+
+pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};
+/* ... */
+mod mem;
+```
+
+This hides the detail that there even exists a `mod mem` in `io`, and
+helps keep code organized while offering freedom to change the
+implementation.
diff --git a/src/doc/style/features/traits/README.md b/src/doc/style/features/traits/README.md
new file mode 100644 (file)
index 0000000..1893db2
--- /dev/null
@@ -0,0 +1,22 @@
+% Traits
+
+Traits are probably Rust's most complex feature, supporting a wide range of use
+cases and design tradeoffs. Patterns of trait usage are still emerging.
+
+### Know whether a trait will be used as an object. [FIXME: needs RFC]
+
+Trait objects have some [significant limitations](objects.md): methods
+invoked through a trait object cannot use generics, and cannot use
+`Self` except in receiver position.
+
+When designing a trait, decide early on whether the trait will be used
+as an [object](objects.md) or as a [bound on generics](generics.md);
+the tradeoffs are discussed in each of the linked sections.
+
+If a trait is meant to be used as an object, its methods should take
+and return trait objects rather than use generics.
+
+
+### Default methods [FIXME]
+
+> **[FIXME]** Guidelines for default methods.
diff --git a/src/doc/style/features/traits/common.md b/src/doc/style/features/traits/common.md
new file mode 100644 (file)
index 0000000..48c37ea
--- /dev/null
@@ -0,0 +1,71 @@
+% Common traits
+
+### Eagerly implement common traits. [FIXME: needs RFC]
+
+Rust's trait system does not allow _orphans_: roughly, every `impl` must live
+either in the crate that defines the trait or the implementing
+type. Consequently, crates that define new types should eagerly implement all
+applicable, common traits.
+
+To see why, consider the following situation:
+
+* Crate `std` defines trait `Show`.
+* Crate `url` defines type `Url`, without implementing `Show`.
+* Crate `webapp` imports from both `std` and `url`,
+
+There is no way for `webapp` to add `Show` to `url`, since it defines neither.
+(Note: the newtype pattern can provide an efficient, but inconvenient
+workaround; see [newtype for views](../types/newtype.md))
+
+The most important common traits to implement from `std` are:
+
+```rust
+Clone, Show, Hash, Eq
+```
+
+#### When safe, derive or otherwise implement `Send` and `Share`. [FIXME]
+
+> **[FIXME]**. This guideline is in flux while the "opt-in" nature of
+> built-in traits is being decided. See https://github.com/rust-lang/rfcs/pull/127
+
+### Prefer to derive, rather than implement. [FIXME: needs RFC]
+
+Deriving saves implementation effort, makes correctness trivial, and
+automatically adapts to upstream changes.
+
+### Do not overload operators in surprising ways. [FIXME: needs RFC]
+
+Operators with built in syntax (`*`, `|`, and so on) can be provided for a type
+by implementing the traits in `core::ops`. These operators come with strong
+expectations: implement `Mul` only for an operation that bears some resemblance
+to multiplication (and shares the expected properties, e.g. associativity), and
+so on for the other traits.
+
+### The `Drop` trait
+
+The `Drop` trait is treated specially by the compiler as a way of
+associating destructors with types. See
+[the section on destructors](../../ownership/destructors.md) for
+guidance.
+
+### The `Deref`/`DerefMut` traits
+
+#### Use `Deref`/`DerefMut` only for smart pointers. [FIXME: needs RFC]
+
+The `Deref` traits are used implicitly by the compiler in many circumstances,
+and interact with method resolution. The relevant rules are designed
+specifically to accommodate smart pointers, and so the traits should be used
+only for that purpose.
+
+#### Do not fail within a `Deref`/`DerefMut` implementation. [FIXME: needs RFC]
+
+Because the `Deref` traits are invoked implicitly by the compiler in sometimes
+subtle ways, failure during dereferencing can be extremely confusing. If a
+dereference might not succeed, target the `Deref` trait as a `Result` or
+`Option` type instead.
+
+#### Avoid inherent methods when implementing `Deref`/`DerefMut` [FIXME: needs RFC]
+
+The rules around method resolution and `Deref` are in flux, but inherent methods
+on a type implementing `Deref` are likely to shadow any methods of the referent
+with the same name.
diff --git a/src/doc/style/features/traits/extensions.md b/src/doc/style/features/traits/extensions.md
new file mode 100644 (file)
index 0000000..fc3a03c
--- /dev/null
@@ -0,0 +1,7 @@
+% Using traits to add extension methods
+
+> **[FIXME]** Elaborate.
+
+### Consider using default methods rather than extension traits **[FIXME]**
+
+> **[FIXME]** Elaborate.
diff --git a/src/doc/style/features/traits/generics.md b/src/doc/style/features/traits/generics.md
new file mode 100644 (file)
index 0000000..ab4f9cb
--- /dev/null
@@ -0,0 +1,68 @@
+% Using traits for bounds on generics
+
+The most widespread use of traits is for writing generic functions or types. For
+example, the following signature describes a function for consuming any iterator
+yielding items of type `A` to produce a collection of `A`:
+
+```rust
+fn from_iter<T: Iterator<A>>(iterator: T) -> SomeCollection<A>
+```
+
+Here, the `Iterator` trait is specifies an interface that a type `T` must
+explicitly implement to be used by this generic function.
+
+**Pros**:
+
+* _Reusability_. Generic functions can be applied to an open-ended collection of
+  types, while giving a clear contract for the functionality those types must
+  provide.
+* _Static dispatch and optimization_. Each use of a generic function is
+  specialized ("monomorphized") to the particular types implementing the trait
+  bounds, which means that (1) invocations of trait methods are static, direct
+  calls to the implementation and (2) the compiler can inline and otherwise
+  optimize these calls.
+* _Inline layout_. If a `struct` and `enum` type is generic over some type
+  parameter `T`, values of type `T` will be laid out _inline_ in the
+  `struct`/`enum`, without any indirection.
+* _Inference_. Since the type parameters to generic functions can usually be
+  inferred, generic functions can help cut down on verbosity in code where
+  explicit conversions or other method calls would usually be necessary. See the
+  [overloading/implicits use case](#use-case:-limited-overloading-and/or-implicit-conversions)
+  below.
+* _Precise types_. Because generic give a _name_ to the specific type
+  implementing a trait, it is possible to be precise about places where that
+  exact type is required or produced. For example, a function
+
+  ```rust
+  fn binary<T: Trait>(x: T, y: T) -> T
+  ```
+
+  is guaranteed to consume and produce elements of exactly the same type `T`; it
+  cannot be invoked with parameters of different types that both implement
+  `Trait`.
+
+**Cons**:
+
+* _Code size_. Specializing generic functions means that the function body is
+  duplicated. The increase in code size must be weighed against the performance
+  benefits of static dispatch.
+* _Homogeneous types_. This is the other side of the "precise types" coin: if
+  `T` is a type parameter, it stands for a _single_ actual type. So for example
+  a `Vec<T>` contains elements of a single concrete type (and, indeed, the
+  vector representation is specialized to lay these out in line). Sometimes
+  heterogeneous collections are useful; see
+  [trait objects](#use-case:-trait-objects) below.
+* _Signature verbosity_. Heavy use of generics can bloat function signatures.
+  **[Ed. note]** This problem may be mitigated by some language improvements; stay tuned.
+
+### Favor widespread traits. **[FIXME: needs RFC]**
+
+Generic types are a form of abstraction, which entails a mental indirection: if
+a function takes an argument of type `T` bounded by `Trait`, clients must first
+think about the concrete types that implement `Trait` to understand how and when
+the function is callable.
+
+To keep the cost of abstraction low, favor widely-known traits. Whenever
+possible, implement and use traits provided as part of the standard library.  Do
+not introduce new traits for generics lightly; wait until there are a wide range
+of types that can implement the type.
diff --git a/src/doc/style/features/traits/objects.md b/src/doc/style/features/traits/objects.md
new file mode 100644 (file)
index 0000000..38494a9
--- /dev/null
@@ -0,0 +1,49 @@
+% Using trait objects
+
+> **[FIXME]** What are uses of trait objects other than heterogeneous collections?
+
+Trait objects are useful primarily when _heterogeneous_ collections of objects
+need to be treated uniformly; it is the closest that Rust comes to
+object-oriented programming.
+
+```rust
+struct Frame  { ... }
+struct Button { ... }
+struct Label  { ... }
+
+trait Widget  { ... }
+
+impl Widget for Frame  { ... }
+impl Widget for Button { ... }
+impl Widget for Label  { ... }
+
+impl Frame {
+    fn new(contents: &[Box<Widget>]) -> Frame {
+        ...
+    }
+}
+
+fn make_gui() -> Box<Widget> {
+    let b: Box<Widget> = box Button::new(...);
+    let l: Box<Widget> = box Label::new(...);
+
+    box Frame::new([b, l]) as Box<Widget>
+}
+```
+
+By using trait objects, we can set up a GUI framework with a `Frame` widget that
+contains a heterogeneous collection of children widgets.
+
+**Pros**:
+
+* _Heterogeneity_. When you need it, you really need it.
+* _Code size_. Unlike generics, trait objects do not generate specialized
+  (monomorphized) versions of code, which can greatly reduce code size.
+
+**Cons**:
+
+* _No generic methods_. Trait objects cannot currently provide generic methods.
+* _Dynamic dispatch and fat pointers_. Trait objects inherently involve
+  indirection and vtable dispatch, which can carry a performance penalty.
+* _No Self_. Except for the method receiver argument, methods on trait objects
+  cannot use the `Self` type.
diff --git a/src/doc/style/features/traits/overloading.md b/src/doc/style/features/traits/overloading.md
new file mode 100644 (file)
index 0000000..d7482c9
--- /dev/null
@@ -0,0 +1,7 @@
+% Using traits for overloading
+
+> **[FIXME]** Elaborate.
+
+> **[FIXME]** We need to decide on guidelines for this use case. There are a few
+> patterns emerging in current Rust code, but it's not clear how widespread they
+> should be.
diff --git a/src/doc/style/features/traits/reuse.md b/src/doc/style/features/traits/reuse.md
new file mode 100644 (file)
index 0000000..6735023
--- /dev/null
@@ -0,0 +1,30 @@
+% Using traits to share implementations
+
+> **[FIXME]** Elaborate.
+
+> **[FIXME]** We probably want to discourage this, at least when used in a way
+> that is publicly exposed.
+
+Traits that provide default implmentations for function can provide code reuse
+across types. For example, a `print` method can be defined across multiple
+types as follows:
+
+``` Rust
+trait Printable {
+    // Default method implementation
+    fn print(&self) { println!("{:?}", *self) }
+}
+
+impl Printable for int {}
+
+impl Printable for String {
+    fn print(&self) { println!("{}", *self) }
+}
+
+impl Printable for bool {}
+
+impl Printable for f32 {}
+```
+
+This allows the implementation of `print` to be shared across types, yet
+overridden where needed, as seen in the `impl` for `String`.
diff --git a/src/doc/style/features/types/README.md b/src/doc/style/features/types/README.md
new file mode 100644 (file)
index 0000000..c675eb5
--- /dev/null
@@ -0,0 +1,68 @@
+% Data types
+
+### Use custom types to imbue meaning; do not abuse `bool`, `Option` or other core types. **[FIXME: needs RFC]**
+
+Prefer
+
+```rust
+let w = Widget::new(Small, Round)
+```
+
+over
+
+```rust
+let w = Widget::new(true, false)
+```
+
+Core types like `bool`, `u8` and `Option` have many possible interpretations.
+
+Use custom types (whether `enum`s, `struct`, or tuples) to convey
+interpretation and invariants. In the above example,
+it is not immediately clear what `true` and `false` are conveying without
+looking up the argument names, but `Small` and `Round` are more suggestive.
+
+Using custom types makes it easier to expand the
+options later on, for example by adding an `ExtraLarge` variant.
+
+See [the newtype pattern](newtype.md) for a no-cost way to wrap
+existing types with a distinguished name.
+
+### Prefer private fields, except for passive data. **[FIXME: needs RFC]**
+
+Making a field public is a strong commitment: it pins down a representation
+choice, _and_ prevents the type from providing any validation or maintaining any
+invariants on the contents of the field, since clients can mutate it arbitrarily.
+
+Public fields are most appropriate for `struct` types in the C spirit: compound,
+passive data structures. Otherwise, consider providing getter/setter methods
+and hiding fields instead.
+
+> **[FIXME]** Cross-reference validation for function arguments.
+
+### Use custom `enum`s for alternatives, `bitflags` for C-style flags. **[FIXME: needs RFC]**
+
+Rust supports `enum` types with "custom discriminants":
+
+~~~~
+enum Color {
+  Red = 0xff0000,
+  Green = 0x00ff00,
+  Blue = 0x0000ff
+}
+~~~~
+
+Custom discriminants are useful when an `enum` type needs to be serialized to an
+integer value compatibly with some other system/language. They support
+"typesafe" APIs: by taking a `Color`, rather than an integer, a function is
+guaranteed to get well-formed inputs, even if it later views those inputs as
+integers.
+
+An `enum` allows an API to request exactly one choice from among many. Sometimes
+an API's input is instead the presence or absence of a set of flags. In C code,
+this is often done by having each flag correspond to a particular bit, allowing
+a single integer to represent, say, 32 or 64 flags. Rust's `std::bitflags`
+module provides a typesafe way for doing so.
+
+### Phantom types. [FIXME]
+
+> **[FIXME]** Add some material on phantom types (https://blog.mozilla.org/research/2014/06/23/static-checking-of-units-in-servo/)
diff --git a/src/doc/style/features/types/conversions.md b/src/doc/style/features/types/conversions.md
new file mode 100644 (file)
index 0000000..f0f230f
--- /dev/null
@@ -0,0 +1,22 @@
+% Conversions between types
+
+### Associate conversions with the most specific type involved. **[FIXME: needs RFC]**
+
+When in doubt, prefer `to_`/`as_`/`into_` to `from_`, because they are
+more ergonomic to use (and can be chained with other methods).
+
+For many conversions between two types, one of the types is clearly more
+"specific": it provides some additional invariant or interpretation that is not
+present in the other type. For example, `str` is more specific than `&[u8]`,
+since it is a utf-8 encoded sequence of bytes.
+
+Conversions should live with the more specific of the involved types. Thus,
+`str` provides both the `as_bytes` method and the `from_utf8` constructor for
+converting to and from `&[u8]` values. Besides being intuitive, this convention
+avoids polluting concrete types like `&[u8]` with endless conversion methods.
+
+### Explicitly mark lossy conversions, or do not label them as conversions. **[FIXME: needs RFC]**
+
+If a function's name implies that it is a conversion (prefix `from_`, `as_`,
+`to_` or `into_`), but the function loses information, add a suffix `_lossy` or
+otherwise indicate the lossyness. Consider avoiding the conversion name prefix.
diff --git a/src/doc/style/features/types/newtype.md b/src/doc/style/features/types/newtype.md
new file mode 100644 (file)
index 0000000..60c17fc
--- /dev/null
@@ -0,0 +1,69 @@
+% The newtype pattern
+
+A "newtype" is a tuple or `struct` with a single field. The terminology is borrowed from Haskell.
+
+Newtypes are a zero-cost abstraction: they introduce a new, distinct name for an
+existing type, with no runtime overhead when converting between the two types.
+
+### Use newtypes to provide static distinctions. [FIXME: needs RFC]
+
+Newtypes can statically distinguish between different interpretations of an
+underlying type.
+
+For example, a `f64` value might be used to represent a quantity in miles or in
+kilometers. Using newtypes, we can keep track of the intended interpretation:
+
+```rust
+struct Miles(pub f64);
+struct Kilometers(pub f64);
+
+impl Miles {
+    fn as_kilometers(&self) -> Kilometers { ... }
+}
+impl Kilometers {
+    fn as_miles(&self) -> Miles { ... }
+}
+```
+
+Once we have separated these two types, we can statically ensure that we do not
+confuse them. For example, the function
+
+```rust
+fn are_we_there_yet(distance_travelled: Miles) -> bool { ... }
+```
+
+cannot accidentally be called with a `Kilometers` value. The compiler will
+remind us to perform the conversion, thus averting certain
+[catastrophic bugs](http://en.wikipedia.org/wiki/Mars_Climate_Orbiter).
+
+### Use newtypes with private fields for hiding. [FIXME: needs RFC]
+
+A newtype can be used to hide representation details while making precise
+promises to the client.
+
+For example, consider a function `my_transform` that returns a compound iterator
+type `Enumerate<Skip<vec::MoveItems<T>>>`. We wish to hide this type from the
+client, so that the client's view of the return type is roughly `Iterator<(uint,
+T)>`. We can do so using the newtype pattern:
+
+```rust
+struct MyTransformResult<T>(Enumerate<Skip<vec::MoveItems<T>>>);
+impl<T> Iterator<(uint, T)> for MyTransformResult<T> { ... }
+
+fn my_transform<T, Iter: Iterator<T>>(iter: Iter) -> MyTransformResult<T> {
+    ...
+}
+```
+
+Aside from simplifying the signature, this use of newtypes allows us to make a
+expose and promise less to the client. The client does not know _how_ the result
+iterator is constructed or represented, which means the representation can
+change in the future without breaking client code.
+
+> **[FIXME]** Interaction with auto-deref.
+
+### Use newtypes to provide cost-free _views_ of another type. **[FIXME]**
+
+> **[FIXME]** Describe the pattern of using newtypes to provide a new set of
+> inherent or trait methods, providing a different perspective on the underlying
+> type.
diff --git a/src/doc/style/ownership/README.md b/src/doc/style/ownership/README.md
new file mode 100644 (file)
index 0000000..11bdb03
--- /dev/null
@@ -0,0 +1,3 @@
+% Ownership and resource management
+
+> **[FIXME]** Add general remarks about ownership/resources here.
diff --git a/src/doc/style/ownership/builders.md b/src/doc/style/ownership/builders.md
new file mode 100644 (file)
index 0000000..94eda59
--- /dev/null
@@ -0,0 +1,176 @@
+% The builder pattern
+
+Some data structures are complicated to construct, due to their construction needing:
+
+* a large number of inputs
+* compound data (e.g. slices)
+* optional configuration data
+* choice between several flavors
+
+which can easily lead to a large number of distinct constructors with
+many arguments each.
+
+If `T` is such a data structure, consider introducing a `T` _builder_:
+
+1. Introduce a separate data type `TBuilder` for incrementally configuring a `T`
+   value. When possible, choose a better name: e.g. `Command` is the builder for
+   `Process`.
+2. The builder constructor should take as parameters only the data _required_ to
+   to make a `T`.
+3. The builder should offer a suite of convenient methods for configuration,
+   including setting up compound inputs (like slices) incrementally.
+   These methods should return `self` to allow chaining.
+4. The builder should provide one or more "_terminal_" methods for actually building a `T`.
+
+The builder pattern is especially appropriate when building a `T` involves side
+effects, such as spawning a task or launching a process.
+
+In Rust, there are two variants of the builder pattern, differing in the
+treatment of ownership, as described below.
+
+### Non-consuming builders (preferred):
+
+In some cases, constructing the final `T` does not require the builder itself to
+be consumed. The follow variant on
+[`std::io::process::Command`](http://static.rust-lang.org/doc/master/std/io/process/struct.Command.html)
+is one example:
+
+```rust
+// NOTE: the actual Command API does not use owned Strings;
+// this is a simplified version.
+
+pub struct Command {
+    program: String,
+    args: Vec<String>,
+    cwd: Option<String>,
+    // etc
+}
+
+impl Command {
+    pub fn new(program: String) -> Command {
+        Command {
+            program: program,
+            args: Vec::new(),
+            cwd: None,
+        }
+    }
+
+    /// Add an argument to pass to the program.
+    pub fn arg<'a>(&'a mut self, arg: String) -> &'a mut Command {
+        self.args.push(arg);
+        self
+    }
+
+    /// Add multiple arguments to pass to the program.
+    pub fn args<'a>(&'a mut self, args: &[String])
+                    -> &'a mut Command {
+        self.args.push_all(args);
+        self
+    }
+
+    /// Set the working directory for the child process.
+    pub fn cwd<'a>(&'a mut self, dir: String) -> &'a mut Command {
+        self.cwd = Some(dir);
+        self
+    }
+
+    /// Executes the command as a child process, which is returned.
+    pub fn spawn(&self) -> IoResult<Process> {
+        ...
+    }
+}
+```
+
+Note that the `spawn` method, which actually uses the builder configuration to
+spawn a process, takes the builder by immutable reference. This is possible
+because spawning the process does not require ownership of the configuration
+data.
+
+Because the terminal `spawn` method only needs a reference, the configuration
+methods take and return a mutable borrow of `self`.
+
+#### The benefit
+
+By using borrows throughout, `Command` can be used conveniently for both
+one-liner and more complex constructions:
+
+```rust
+// One-liners
+Command::new("/bin/cat").arg("file.txt").spawn();
+
+// Complex configuration
+let mut cmd = Command::new("/bin/ls");
+cmd.arg(".");
+
+if size_sorted {
+    cmd.arg("-S");
+}
+
+cmd.spawn();
+```
+
+### Consuming builders:
+
+Sometimes builders must transfer ownership when constructing the final type
+`T`, meaning that the terminal methods must take `self` rather than `&self`:
+
+```rust
+// A simplified excerpt from std::task::TaskBuilder
+
+impl TaskBuilder {
+    /// Name the task-to-be. Currently the name is used for identification
+    /// only in failure messages.
+    pub fn named(mut self, name: String) -> TaskBuilder {
+        self.name = Some(name);
+        self
+    }
+
+    /// Redirect task-local stdout.
+    pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder {
+        self.stdout = Some(stdout);
+        //   ^~~~~~ this is owned and cannot be cloned/re-used
+        self
+    }
+
+    /// Creates and executes a new child task.
+    pub fn spawn(self, f: proc():Send) {
+        // consume self
+        ...
+    }
+}
+```
+
+Here, the `stdout` configuration involves passing ownership of a `Writer`,
+which must be transferred to the task upon construction (in `spawn`).
+
+When the terminal methods of the builder require ownership, there is a basic tradeoff:
+
+* If the other builder methods take/return a mutable borrow, the complex
+  configuration case will work well, but one-liner configuration becomes
+  _impossible_.
+
+* If the other builder methods take/return an owned `self`, one-liners
+  continue to work well but complex configuration is less convenient.
+
+Under the rubric of making easy things easy and hard things possible, _all_
+builder methods for a consuming builder should take and returned an owned
+`self`. Then client code works as follows:
+
+```rust
+// One-liners
+TaskBuilder::new().named("my_task").spawn(proc() { ... });
+
+// Complex configuration
+let mut task = TaskBuilder::new();
+task = task.named("my_task_2"); // must re-assign to retain ownership
+
+if reroute {
+    task = task.stdout(mywriter);
+}
+
+task.spawn(proc() { ... });
+```
+
+One-liners work as before, because ownership is threaded through each of the
+builder methods until being consumed by `spawn`. Complex configuration,
+however, is more verbose: it requires re-assigning the builder at each step.
diff --git a/src/doc/style/ownership/cell-smart.md b/src/doc/style/ownership/cell-smart.md
new file mode 100644 (file)
index 0000000..cd027cc
--- /dev/null
@@ -0,0 +1,4 @@
+% Cells and smart pointers
+
+> **[FIXME]** Add guidelines about when to use Cell, RefCell, Rc and
+> Arc (and how to use them together).
diff --git a/src/doc/style/ownership/constructors.md b/src/doc/style/ownership/constructors.md
new file mode 100644 (file)
index 0000000..b4a1147
--- /dev/null
@@ -0,0 +1,62 @@
+% Constructors
+
+### Define constructors as static, inherent methods. [FIXME: needs RFC]
+
+In Rust, "constructors" are just a convention:
+
+```rust
+impl<T> Vec<T> {
+    pub fn new() -> Vec<T> { ... }
+}
+```
+
+Constructors are static (no `self`) inherent methods for the type that they
+construct. Combined with the practice of
+[fully importing type names](../style/imports.md), this convention leads to
+informative but concise construction:
+
+```rust
+use vec::Vec;
+
+// construct a new vector
+let mut v = Vec::new();
+```
+
+This convention also applied to conversion constructors (prefix `from` rather
+than `new`).
+
+### Provide constructors for passive `struct`s with defaults. [FIXME: needs RFC]
+
+Given the `struct`
+
+```rust
+pub struct Config {
+    pub color: Color,
+    pub size:  Size,
+    pub shape: Shape,
+}
+```
+
+provide a constructor if there are sensible defaults:
+
+```rust
+impl Config {
+    pub fn new() -> Config {
+        Config {
+            color: Brown,
+            size: Medium,
+            shape: Square,
+        }
+    }
+}
+```
+
+which then allows clients to concisely override using `struct` update syntax:
+
+```rust
+Config { color: Red, .. Config::new() };
+```
+
+See the [guideline for field privacy](../features/types/README.md) for
+discussion on when to create such "passive" `struct`s with public
+fields.
diff --git a/src/doc/style/ownership/destructors.md b/src/doc/style/ownership/destructors.md
new file mode 100644 (file)
index 0000000..8f58aa6
--- /dev/null
@@ -0,0 +1,22 @@
+% Destructors
+
+Unlike constructors, destructors in Rust have a special status: they are added
+by implementing `Drop` for a type, and they are automatically invoked as values
+go out of scope.
+
+> **[FIXME]** This section needs to be expanded.
+
+### Destructors should not fail. [FIXME: needs RFC]
+
+Destructors are executed on task failure, and in that context a failing
+destructor causes the program to abort.
+
+Instead of failing in a destructor, provide a separate method for checking for
+clean teardown, e.g. a `close` method, that returns a `Result` to signal
+problems.
+
+### Destructors should not block. [FIXME: needs RFC]
+
+Similarly, destructors should not invoke blocking operations, which can make
+debugging much more difficult. Again, consider providing a separate method for
+preparing for an infallible, nonblocking teardown.
diff --git a/src/doc/style/ownership/raii.md b/src/doc/style/ownership/raii.md
new file mode 100644 (file)
index 0000000..244e809
--- /dev/null
@@ -0,0 +1,12 @@
+% RAII
+
+Resource Acquisition is Initialization
+
+> **[FIXME]** Explain the RAII pattern and give best practices.
+
+### Whenever possible, tie resource access to guard scopes [FIXME]
+
+> **[FIXME]** Example: Mutex guards guarantee that access to the
+> protected resource only happens when the guard is in scope.
+
+`must_use`
diff --git a/src/doc/style/platform.md b/src/doc/style/platform.md
new file mode 100644 (file)
index 0000000..d29d060
--- /dev/null
@@ -0,0 +1,7 @@
+% FFI and platform-specific code **[FIXME]**
+
+> **[FIXME]** Not sure where this should live.
+
+When writing cross-platform code, group platform-specific code into a
+module called `platform`. Avoid `#[cfg]` directives outside this
+`platform` module.
diff --git a/src/doc/style/safety/README.md b/src/doc/style/safety/README.md
new file mode 100644 (file)
index 0000000..1ac6e70
--- /dev/null
@@ -0,0 +1,19 @@
+% Safety and guarantees
+
+> **[FIXME]** Is there a better phrase than "strong guarantees" that encompasses
+> both e.g. memory safety and e.g. data structure invariants?
+
+A _guarantee_ is a property that holds no matter what client code does, unless
+the client explicitly opts out:
+
+* Rust guarantees memory safety and data-race freedom, with `unsafe`
+  blocks as an opt-out mechanism.
+
+* APIs in Rust often provide their own guarantees. For example, `std::str`
+guarantees that its underlying buffer is valid utf-8. The `std::path::Path` type
+guarantees no interior nulls. Both strings and paths provide `unsafe` mechanisms
+for opting out of these guarantees (and thereby avoiding runtime checks).
+
+Thinking about guarantees is an essential part of writing good Rust code.  The
+rest of this subsection outlines some cross-cutting principles around
+guarantees.
diff --git a/src/doc/style/safety/lib-guarantees.md b/src/doc/style/safety/lib-guarantees.md
new file mode 100644 (file)
index 0000000..aa87223
--- /dev/null
@@ -0,0 +1,81 @@
+% Library-level guarantees
+
+Most libraries rely on internal invariants, e.g. about their data, resource
+ownership, or protocol states. In Rust, broken invariants cannot produce
+segfaults, but they can still lead to wrong answers.
+
+### Provide library-level guarantees whenever practical. **[FIXME: needs RFC]**
+
+Library-level invariants should be turned into guarantees whenever
+practical. They should hold no matter what the client does, modulo
+explicit opt-outs. Depending on the kind of invariant, this can be
+achieved through a combination of static and dynamic enforcement, as
+described below.
+
+#### Static enforcement:
+
+Guaranteeing invariants almost always requires _hiding_,
+i.e. preventing the client from directly accessing or modifying
+internal data.
+
+For example, the representation of the `str` type is hidden,
+which means that any value of type `str` must have been produced
+through an API under the control of the `str` module, and these
+APIs in turn ensure valid utf-8 encoding.
+
+Rust's type system makes it possible to provide guarantees even while
+revealing more of the representation than usual. For example, the
+`as_bytes()` method on `&str` gives a _read-only_ view into the
+underlying buffer, which cannot be used to violate the utf-8 property.
+
+#### Dynamic enforcement:
+
+Malformed inputs from the client are hazards to library-level
+guarantees, so library APIs should validate their input.
+
+For example, `std::str::from_utf8_owned` attempts to convert a `u8`
+slice into an owned string, but dynamically checks that the slice is
+valid utf-8 and returns `Err` if not.
+
+See
+[the discussion on input validation](../features/functions-and-methods/input.md)
+for more detail.
+
+
+### Prefer static enforcement of guarantees. **[FIXME: needs RFC]**
+
+Static enforcement provides two strong benefits over dynamic enforcement:
+
+* Bugs are caught at compile time.
+* There is no runtime cost.
+
+Sometimes purely static enforcement is impossible or impractical. In these
+cases, a library should check as much as possible statically, but defer to
+dynamic checks where needed.
+
+For example, the `std::string` module exports a `String` type with the guarantee
+that all instances are valid utf-8:
+
+* Any _consumer_ of a `String` is statically guaranteed utf-8 contents. For example,
+  the `append` method can push a `&str` onto the end of a `String` without
+  checking anything dynamically, since the existing `String` and `&str` are
+  statically guaranteed to be in utf-8.
+
+* Some _producers_ of a `String` must perform dynamic checks. For example, the
+  `from_utf8` function attempts to convert a `Vec<u8>` into a `String`, but
+  dynamically checks that the contents are utf-8.
+
+### Provide opt-outs with caution; make them explicit. **[FIXME: needs RFC]**
+
+Providing library-level guarantees sometimes entails inconvenience (for static
+checks) or overhead (for dynamic checks). So it is sometimes desirable to allow
+clients to sidestep this checking, while promising to use the API in a way that
+still provides the guarantee. Such escape hatches should only be be introduced
+when there is a demonstrated need for them.
+
+It should be trivial for clients to audit their use of the library for
+escape hatches.
+
+See
+[the discussion on input validation](../features/functions-and-methods/input.md)
+for conventions on marking opt-out functions.
diff --git a/src/doc/style/safety/unsafe.md b/src/doc/style/safety/unsafe.md
new file mode 100644 (file)
index 0000000..a8a50af
--- /dev/null
@@ -0,0 +1,22 @@
+% Using `unsafe`
+
+### Unconditionally guarantee safety, or mark API as `unsafe`. **[FIXME: needs RFC]**
+
+Memory safety, type safety, and data race freedom are basic assumptions for all
+Rust code.
+
+APIs that use `unsafe` blocks internally thus have two choices:
+
+* They can guarantee safety _unconditionally_ (i.e., regardless of client
+  behavior or inputs) and be exported as safe code. Any safety violation is then
+  the library's fault, not the client's fault.
+
+* They can export potentially unsafe functions with the `unsafe` qualifier. In
+  this case, the documentation should make very clear the conditions under which
+  safety is guaranteed.
+
+The result is that a client program can never violate safety merely by having a
+bug; it must have explicitly opted out by using an `unsafe` block.
+
+Of the two options for using `unsafe`, creating such safe abstractions (the
+first option above) is strongly preferred.
diff --git a/src/doc/style/style/README.md b/src/doc/style/style/README.md
new file mode 100644 (file)
index 0000000..8744971
--- /dev/null
@@ -0,0 +1,5 @@
+% Style
+
+This section gives a set of strict rules for styling Rust code.
+
+> **[FIXME]** General remarks about the style guidelines
diff --git a/src/doc/style/style/braces.md b/src/doc/style/style/braces.md
new file mode 100644 (file)
index 0000000..0f61bac
--- /dev/null
@@ -0,0 +1,77 @@
+% Braces, semicolons, and commas [FIXME: needs RFC]
+
+### Opening braces always go on the same line.
+
+``` rust
+fn foo() {
+    ...
+}
+
+fn frobnicate(a: Bar, b: Bar,
+              c: Bar, d: Bar)
+              -> Bar {
+    ...
+}
+
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Baz {
+    fn baz(&self) {
+        ...
+    }
+}
+
+frob(|x| {
+    x.transpose()
+})
+```
+
+### `match` arms get braces, except for single-line expressions.
+
+``` rust
+match foo {
+    bar => baz,
+    quux => {
+        do_something();
+        do_something_else()
+    }
+}
+```
+
+### `return` statements get semicolons.
+
+``` rust
+fn foo() {
+    do_something();
+
+    if condition() {
+        return;
+    }
+
+    do_something_else();
+}
+```
+
+### Trailing commas
+
+> **[FIXME]** We should have a guideline for when to include trailing
+> commas in `struct`s, `match`es, function calls, etc.
+>
+> One possible rule: a trailing comma should be included whenever the
+> closing delimiter appears on a separate line:
+
+```rust
+Foo { bar: 0, baz: 1 }
+
+Foo {
+    bar: 0,
+    baz: 1,
+}
+
+match a_thing {
+    None => 0,
+    Some(x) => 1,
+}
+```
diff --git a/src/doc/style/style/comments.md b/src/doc/style/style/comments.md
new file mode 100644 (file)
index 0000000..347750c
--- /dev/null
@@ -0,0 +1,87 @@
+% Comments [FIXME: needs RFC]
+
+### Avoid block comments.
+
+Use line comments:
+
+``` rust
+// Wait for the main task to return, and set the process error code
+// appropriately.
+```
+
+Instead of:
+
+``` rust
+/*
+ * Wait for the main task to return, and set the process error code
+ * appropriately.
+ */
+```
+
+## Doc comments
+
+Doc comments are prefixed by three slashes (`///`) and indicate
+documentation that you would like to be included in Rustdoc's output.
+They support
+[Markdown syntax](https://en.wikipedia.org/wiki/Markdown)
+and are the main way of documenting your public APIs.
+
+The supported markdown syntax includes all of the extensions listed in the
+[GitHub Flavored Markdown]
+(https://help.github.com/articles/github-flavored-markdown) documentation,
+plus superscripts.
+
+### Summary line
+
+The first line in any doc comment should be a single-line short sentence
+providing a summary of the code. This line is used as a short summary
+description throughout Rustdoc's output, so it's a good idea to keep it
+short.
+
+### Sentence structure
+
+All doc comments, including the summary line, should begin with a
+capital letter and end with a period, question mark, or exclamation
+point. Prefer full sentences to fragments.
+
+The summary line should be written in
+[third person singular present indicative form]
+(http://en.wikipedia.org/wiki/English_verbs#Third_person_singular_present).
+Basically, this means write "Returns" instead of "Return".
+
+For example:
+
+``` rust
+/// Sets up a default runtime configuration, given compiler-supplied arguments.
+///
+/// This function will block until the entire pool of M:N schedulers has
+/// exited. This function also requires a local task to be available.
+///
+/// # Arguments
+///
+/// * `argc` & `argv` - The argument vector. On Unix this information is used
+///                     by `os::args`.
+/// * `main` - The initial procedure to run inside of the M:N scheduling pool.
+///            Once this procedure exits, the scheduling pool will begin to shut
+///            down. The entire pool (and this function) will only return once
+///            all child tasks have finished executing.
+///
+/// # Return value
+///
+/// The return value is used as the process return code. 0 on success, 101 on
+/// error.
+```
+
+### Code snippets
+
+> **[FIXME]**
+
+### Avoid inner doc comments.
+
+Use inner doc comments _only_ to document crates and file-level modules:
+
+``` rust
+//! The core library.
+//!
+//! The core library is a something something...
+```
diff --git a/src/doc/style/style/features.md b/src/doc/style/style/features.md
new file mode 100644 (file)
index 0000000..f73517c
--- /dev/null
@@ -0,0 +1,13 @@
+## `return` [FIXME: needs RFC]
+
+Terminate `return` statements with semicolons:
+
+``` rust
+fn foo(bar: int) -> Option<int> {
+    if some_condition() {
+        return None;
+    }
+
+    ...
+}
+```
diff --git a/src/doc/style/style/imports.md b/src/doc/style/style/imports.md
new file mode 100644 (file)
index 0000000..207a3fd
--- /dev/null
@@ -0,0 +1,50 @@
+% Imports [FIXME: needs RFC]
+
+The imports of a crate/module should consist of the following
+sections, in order, with a blank space between each:
+
+* `extern crate` directives
+* external `use` imports
+* local `use` imports
+* `pub use` imports
+
+For example:
+
+```rust
+// Crates.
+extern crate getopts;
+extern crate mylib;
+
+// Standard library imports.
+use getopts::{optopt, getopts};
+use std::os;
+
+// Import from a library that we wrote.
+use mylib::webserver;
+
+// Will be reexported when we import this module.
+pub use self::types::Webdata;
+```
+
+### Avoid `use *`, except in tests.
+
+Glob imports have several downsides:
+* They make it harder to tell where names are bound.
+* They are forwards-incompatible, since new upstream exports can clash
+  with existing names.
+
+When writing a [`test` submodule](../testing/README.md), importing `super::*` is appropriate
+as a convenience.
+
+### Prefer fully importing types/traits while module-qualifying functions.
+
+For example:
+
+```rust
+use option::Option;
+use mem;
+
+let i: int = mem::transmute(Option(0));
+```
+
+> **[FIXME]** Add rationale.
diff --git a/src/doc/style/style/naming/README.md b/src/doc/style/style/naming/README.md
new file mode 100644 (file)
index 0000000..9d78721
--- /dev/null
@@ -0,0 +1,115 @@
+% Naming conventions
+
+### General conventions [RFC #430]
+
+> The guidelines below were approved by [RFC #430](https://github.com/rust-lang/rfcs/pull/430).
+
+In general, Rust tends to use `CamelCase` for "type-level" constructs
+(types and traits) and `snake_case` for "value-level" constructs. More
+precisely:
+
+| Item | Convention |
+| ---- | ---------- |
+| Crates | `snake_case` (but prefer single word) |
+| Modules | `snake_case` |
+| Types | `CamelCase` |
+| Traits | `CamelCase` |
+| Enum variants | `CamelCase` |
+| Functions | `snake_case` |
+| Methods | `snake_case` |
+| General constructors | `new` or `with_more_details` |
+| Conversion constructors | `from_some_other_type` |
+| Local variables | `snake_case` |
+| Static variables | `SCREAMING_SNAKE_CASE` |
+| Constant variables | `SCREAMING_SNAKE_CASE` |
+| Type parameters | concise `CamelCase`, usually single uppercase letter: `T` |
+| Lifetimes | short, lowercase: `'a` |
+
+<p>
+In `CamelCase`, acronyms count as one word: use `Uuid` rather than
+`UUID`.  In `snake_case`, acronyms are lower-cased: `is_xid_start`.
+
+In `snake_case` or `SCREAMING_SNAKE_CASE`, a "word" should never
+consist of a single letter unless it is the last "word". So, we have
+`btree_map` rather than `b_tree_map`, but `PI_2` rather than `PI2`.
+
+### Referring to types in function/method names [RFC 344]
+
+> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
+
+Function names often involve type names, the most common example being conversions
+like `as_slice`. If the type has a purely textual name (ignoring parameters), it
+is straightforward to convert between type conventions and function conventions:
+
+Type name | Text in methods
+--------- | ---------------
+`String`  | `string`
+`Vec<T>`  | `vec`
+`YourType`| `your_type`
+
+Types that involve notation follow the convention below. There is some
+overlap on these rules; apply the most specific applicable rule:
+
+Type name | Text in methods
+--------- | ---------------
+`&str`    | `str`
+`&[T]`    | `slice`
+`&mut [T]`| `mut_slice`
+`&[u8]`   | `bytes`
+`&T`      | `ref`
+`&mut T`  | `mut`
+`*const T`| `ptr`
+`*mut T`  | `mut_ptr`
+
+### Avoid redundant prefixes [RFC 356]
+
+> The guidelines below were approved by [RFC #356](https://github.com/rust-lang/rfcs/pull/356).
+
+Names of items within a module should not be prefixed with that module's name:
+
+Prefer
+
+``` rust
+mod foo {
+    pub struct Error { ... }
+}
+```
+
+over
+
+``` rust
+mod foo {
+    pub struct FooError { ... }
+}
+```
+
+This convention avoids stuttering (like `io::IoError`). Library clients can
+rename on import to avoid clashes.
+
+### Getter/setter methods [RFC 344]
+
+> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
+
+Some data structures do not wish to provide direct access to their fields, but
+instead offer "getter" and "setter" methods for manipulating the field state
+(often providing checking or other functionality).
+
+The convention for a field `foo: T` is:
+
+* A method `foo(&self) -> &T` for getting the current value of the field.
+* A method `set_foo(&self, val: T)` for setting the field. (The `val` argument
+  here may take `&T` or some other type, depending on the context.)
+
+Note that this convention is about getters/setters on ordinary data types, *not*
+on [builder objects](../ownership/builders.html).
+
+### Escape hatches [FIXME]
+
+> **[FIXME]** Should we standardize a convention for functions that may break API
+> guarantees? e.g. `ToCStr::to_c_str_unchecked`
+
+### Predicates
+
+* Simple boolean predicates should be prefixed with `is_` or another
+  short question word, e.g., `is_empty`.
+* Common exceptions: `lt`, `gt`, and other established predicate names.
diff --git a/src/doc/style/style/naming/containers.md b/src/doc/style/style/naming/containers.md
new file mode 100644 (file)
index 0000000..04204f0
--- /dev/null
@@ -0,0 +1,69 @@
+% Common container/wrapper methods [FIXME: needs RFC]
+
+Containers, wrappers, and cells all provide ways to access the data
+they enclose.  Accessor methods often have variants to access the data
+by value, by reference, and by mutable reference.
+
+In general, the `get` family of methods is used to access contained
+data without any risk of task failure; they return `Option` as
+appropriate. This name is chosen rather than names like `find` or
+`lookup` because it is appropriate for a wider range of container types.
+
+#### Containers
+
+For a container with keys/indexes of type `K` and elements of type `V`:
+
+```rust
+// Look up element without failing
+fn get(&self, key: K) -> Option<&V>
+fn get_mut(&mut self, key: K) -> Option<&mut V>
+
+// Convenience for .get(key).map(|elt| elt.clone())
+fn get_clone(&self, key: K) -> Option<V>
+
+// Lookup element, failing if it is not found:
+impl Index<K, V> for Container { ... }
+impl IndexMut<K, V> for Container { ... }
+```
+
+#### Wrappers/Cells
+
+Prefer specific conversion functions like `as_bytes` or `into_vec` whenever
+possible. Otherwise, use:
+
+```rust
+// Extract contents without failing
+fn get(&self) -> &V
+fn get_mut(&mut self) -> &mut V
+fn unwrap(self) -> V
+```
+
+#### Wrappers/Cells around `Copy` data
+
+```rust
+// Extract contents without failing
+fn get(&self) -> V
+```
+
+#### `Option`-like types
+
+Finally, we have the cases of types like `Option` and `Result`, which
+play a special role for failure.
+
+For `Option<V>`:
+
+```rust
+// Extract contents or fail if not available
+fn assert(self) -> V
+fn expect(self, &str) -> V
+```
+
+For `Result<V, E>`:
+
+```rust
+// Extract the contents of Ok variant; fail if Err
+fn assert(self) -> V
+
+// Extract the contents of Err variant; fail if Ok
+fn assert_err(self) -> E
+```
diff --git a/src/doc/style/style/naming/conversions.md b/src/doc/style/style/naming/conversions.md
new file mode 100644 (file)
index 0000000..0287919
--- /dev/null
@@ -0,0 +1,32 @@
+% Conversions [Rust issue #7087]
+
+> The guidelines below were approved by [rust issue #7087](https://github.com/rust-lang/rust/issues/7087).
+
+> **[FIXME]** Should we provide standard traits for conversions? Doing
+> so nicely will require
+> [trait reform](https://github.com/rust-lang/rfcs/pull/48) to land.
+
+Conversions should be provided as methods, with names prefixed as follows:
+
+| Prefix | Cost | Consumes convertee |
+| ------ | ---- | ------------------ |
+| `as_` | Free | No |
+| `to_` | Expensive | No |
+| `into_` | Variable | Yes |
+
+<p>
+For example:
+
+* `as_bytes()` gives a `&[u8]` view into a `&str`, which is a no-op.
+* `to_owned()` copies a `&str` to a new `String`.
+* `into_bytes()` consumes a `String` and yields the underlying
+  `Vec<u8>`, which is a no-op.
+
+Conversions prefixed `as_` and `into_` typically _decrease abstraction_, either
+exposing a view into the underlying representation (`as`) or deconstructing data
+into its underlying representation (`into`). Conversions prefixed `to_`, on the
+other hand, typically stay at the same level of abstraction but do some work to
+change one representation into another.
+
+> **[FIXME]** The distinctions between conversion methods does not work
+> so well for `from_` conversion constructors. Is that a problem?
diff --git a/src/doc/style/style/naming/iterators.md b/src/doc/style/style/naming/iterators.md
new file mode 100644 (file)
index 0000000..38138b5
--- /dev/null
@@ -0,0 +1,32 @@
+% Iterators
+
+#### Method names [RFC #199]
+
+> The guidelines below were approved by [RFC #199](https://github.com/rust-lang/rfcs/pull/199).
+
+For a container with elements of type `U`, iterator methods should be named:
+
+```rust
+fn iter(&self) -> T           // where T implements Iterator<&U>
+fn iter_mut(&mut self) -> T   // where T implements Iterator<&mut U>
+fn into_iter(self) -> T       // where T implements Iterator<U>
+```
+
+The default iterator variant yields shared references `&U`.
+
+#### Type names [RFC #344]
+
+> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
+
+The name of an iterator type should be the same as the method that
+produces the iterator.
+
+For example:
+
+* `iter` should yield an `Iter`
+* `iter_mut` should yield an `IterMut`
+* `into_iter` should yield an `IntoIter`
+* `keys` should yield `Keys`
+
+These type names make the most sense when prefixed with their owning module,
+e.g. `vec::IntoIter`.
diff --git a/src/doc/style/style/naming/ownership.md b/src/doc/style/style/naming/ownership.md
new file mode 100644 (file)
index 0000000..32cd8a1
--- /dev/null
@@ -0,0 +1,34 @@
+% Ownership variants [RFC #199]
+
+> The guidelines below were approved by [RFC #199](https://github.com/rust-lang/rfcs/pull/199).
+
+Functions often come in multiple variants: immutably borrowed, mutably
+borrowed, and owned.
+
+The right default depends on the function in question. Variants should
+be marked through suffixes.
+
+#### Immutably borrowed by default
+
+If `foo` uses/produces an immutable borrow by default, use:
+
+* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant.
+* The `_move` suffix (e.g. `foo_move`) for the owned variant.
+
+#### Owned by default
+
+If `foo` uses/produces owned data by default, use:
+
+* The `_ref` suffix (e.g. `foo_ref`) for the immutably borrowed variant.
+* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant.
+
+#### Exceptions
+
+In the case of iterators, the moving variant can also be understood as
+an `into` conversion, `into_iter`, and `for x in v.into_iter()` reads
+arguably better than `for x in v.iter_move()`, so the convention is
+`into_iter`.
+
+For mutably borrowed variants, if the `mut` qualifier is part of a
+type name (e.g. `as_mut_slice`), it should appear as it would appear
+in the type.
diff --git a/src/doc/style/style/optional.md b/src/doc/style/style/optional.md
new file mode 100644 (file)
index 0000000..d3c2178
--- /dev/null
@@ -0,0 +1,3 @@
+*
+
+*
diff --git a/src/doc/style/style/organization.md b/src/doc/style/style/organization.md
new file mode 100644 (file)
index 0000000..8506540
--- /dev/null
@@ -0,0 +1,14 @@
+% Organization [FIXME: needs RFC]
+
+> **[FIXME]** What else?
+
+### Reexport the most important types at the crate level.
+
+Crates `pub use` the most common types for convenience, so that clients do not
+have to remember or write the crate's module hierarchy to use these types.
+
+### Define types and operations together.
+
+Type definitions and the functions/methods that operate on them should be
+defined together in a single module, with the type appearing above the
+functions/methods.
diff --git a/src/doc/style/style/whitespace.md b/src/doc/style/style/whitespace.md
new file mode 100644 (file)
index 0000000..b21b280
--- /dev/null
@@ -0,0 +1,133 @@
+% Whitespace [FIXME: needs RFC]
+
+* Lines must not exceed 99 characters.
+* Use 4 spaces for indentation, _not_ tabs.
+* No trailing whitespace at the end of lines or files.
+
+### Spaces
+
+* Use spaces around binary operators, including the equals sign in attributes:
+
+``` rust
+#[deprecated = "Use `bar` instead."]
+fn foo(a: uint, b: uint) -> uint {
+    a + b
+}
+```
+
+* Use a space after colons and commas:
+
+``` rust
+fn foo(a: Bar);
+
+MyStruct { foo: 3, bar: 4 }
+
+foo(bar, baz);
+```
+
+* Use a space after the opening and before the closing brace for
+  single line blocks or `struct` expressions:
+
+``` rust
+spawn(proc() { do_something(); })
+
+Point { x: 0.1, y: 0.3 }
+```
+
+### Line wrapping
+
+* For multiline function signatures, each new line should align with the
+  first parameter. Multiple parameters per line are permitted:
+
+``` rust
+fn frobnicate(a: Bar, b: Bar,
+              c: Bar, d: Bar)
+              -> Bar {
+    ...
+}
+
+fn foo<T: This,
+       U: That>(
+       a: Bar,
+       b: Bar)
+       -> Baz {
+    ...
+}
+```
+
+* Multiline function invocations generally follow the same rule as for
+  signatures. However, if the final argument begins a new block, the
+  contents of the block may begin on a new line, indented one level:
+
+``` rust
+fn foo_bar(a: Bar, b: Bar,
+           c: |Bar|) -> Bar {
+    ...
+}
+
+// Same line is fine:
+foo_bar(x, y, |z| { z.transpose(y) });
+
+// Indented body on new line is also fine:
+foo_bar(x, y, |z| {
+    z.quux();
+    z.rotate(x)
+})
+```
+
+> **[FIXME]** Do we also want to allow the following?
+>
+> ```rust
+> frobnicate(
+>     arg1,
+>     arg2,
+>     arg3)
+> ```
+>
+> This style could ease the conflict between line length and functions
+> with many parameters (or long method chains).
+
+### Matches
+
+> * **[Deprecated]** If you have multiple patterns in a single `match`
+>   arm, write each pattern on a separate line:
+>
+>     ``` rust
+>     match foo {
+>         bar(_)
+>         | baz => quux,
+>         x
+>         | y
+>         | z => {
+>             quuux
+>         }
+>     }
+>     ```
+
+### Alignment
+
+Idiomatic code should not use extra whitespace in the middle of a line
+to provide alignment.
+
+
+``` rust
+// Good
+struct Foo {
+    short: f64,
+    really_long: f64,
+}
+
+// Bad
+struct Bar {
+    short:       f64,
+    really_long: f64,
+}
+
+// Good
+let a = 0;
+let radius = 7;
+
+// Bad
+let b        = 0;
+let diameter = 7;
+```
diff --git a/src/doc/style/testing/README.md b/src/doc/style/testing/README.md
new file mode 100644 (file)
index 0000000..a21f694
--- /dev/null
@@ -0,0 +1,5 @@
+% Testing
+
+> **[FIXME]** Add some general remarks about when and how to unit
+> test, versus other kinds of testing. What are our expectations for
+> Rust's core libraries?
diff --git a/src/doc/style/testing/unit.md b/src/doc/style/testing/unit.md
new file mode 100644 (file)
index 0000000..813660d
--- /dev/null
@@ -0,0 +1,30 @@
+% Unit testing
+
+Unit tests should live in a `test` submodule at the bottom of the module they
+test. Mark the `test` submodule with `#[cfg(test)]` so it is only compiled when
+testing.
+
+The `test` module should contain:
+
+* Imports needed only for testing.
+* Functions marked with `#[test]` striving for full coverage of the parent module's
+  definitions.
+* Auxiliary functions needed for writing the tests.
+
+For example:
+
+``` rust
+// Excerpt from std::str
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn test_eq() {
+        assert!((eq(&"".to_owned(), &"".to_owned())));
+        assert!((eq(&"foo".to_owned(), &"foo".to_owned())));
+        assert!((!eq(&"foo".to_owned(), &"bar".to_owned())));
+    }
+}
+```
+
+> **[FIXME]** add details about useful macros for testing, e.g. `assert!`
diff --git a/src/doc/style/todo.md b/src/doc/style/todo.md
new file mode 100644 (file)
index 0000000..28ef2a1
--- /dev/null
@@ -0,0 +1,5 @@
+* [Containers and iteration]()
+* [The visitor pattern]()
+* [Concurrency]()
+* [Documentation]()
+* [Macros]()