From 00d4a43d84d5979332dbbbc4329211b007f7fe45 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 29 Jul 2016 18:56:09 -0400 Subject: [PATCH] Remove style guide. We originally imported this into the repository with the intent of fixing it up. Instead, nothing happened. Its appearance on rust-lang.org makes it seem semi-official, but it's not. The rustfmt strike team will end up producing something like this anyway, and leaving it around does nothing but mislead people. --- src/doc/style/README.md | 64 ------ src/doc/style/SUMMARY.md | 50 ----- src/doc/style/errors/README.md | 3 - src/doc/style/errors/ergonomics.md | 66 ------ src/doc/style/errors/handling.md | 7 - src/doc/style/errors/propagation.md | 8 - src/doc/style/errors/signaling.md | 125 ----------- src/doc/style/features/README.md | 9 - src/doc/style/features/crates.md | 6 - .../features/functions-and-methods/README.md | 44 ---- .../functions-and-methods/convenience.md | 43 ---- .../features/functions-and-methods/input.md | 203 ------------------ .../features/functions-and-methods/output.md | 56 ----- src/doc/style/features/let.md | 103 --------- src/doc/style/features/loops.md | 13 -- src/doc/style/features/match.md | 26 --- src/doc/style/features/modules.md | 133 ------------ src/doc/style/features/traits/README.md | 22 -- src/doc/style/features/traits/common.md | 71 ------ src/doc/style/features/traits/extensions.md | 7 - src/doc/style/features/traits/generics.md | 67 ------ src/doc/style/features/traits/objects.md | 49 ----- src/doc/style/features/traits/overloading.md | 7 - src/doc/style/features/traits/reuse.md | 30 --- src/doc/style/features/types/README.md | 68 ------ src/doc/style/features/types/conversions.md | 22 -- src/doc/style/features/types/newtype.md | 69 ------ src/doc/style/ownership/README.md | 3 - src/doc/style/ownership/builders.md | 176 --------------- src/doc/style/ownership/cell-smart.md | 4 - src/doc/style/ownership/constructors.md | 62 ------ src/doc/style/ownership/destructors.md | 22 -- src/doc/style/ownership/raii.md | 12 -- src/doc/style/platform.md | 7 - src/doc/style/safety/README.md | 19 -- src/doc/style/safety/lib-guarantees.md | 81 ------- src/doc/style/safety/unsafe.md | 22 -- src/doc/style/style/README.md | 5 - src/doc/style/style/braces.md | 77 ------- src/doc/style/style/comments.md | 122 ----------- src/doc/style/style/features.md | 13 -- src/doc/style/style/imports.md | 50 ----- src/doc/style/style/naming/README.md | 115 ---------- src/doc/style/style/naming/containers.md | 69 ------ src/doc/style/style/naming/conversions.md | 32 --- src/doc/style/style/naming/iterators.md | 32 --- src/doc/style/style/naming/ownership.md | 34 --- src/doc/style/style/optional.md | 3 - src/doc/style/style/organization.md | 14 -- src/doc/style/style/whitespace.md | 133 ------------ src/doc/style/testing/README.md | 5 - src/doc/style/testing/unit.md | 30 --- src/doc/style/todo.md | 5 - 53 files changed, 2518 deletions(-) delete mode 100644 src/doc/style/README.md delete mode 100644 src/doc/style/SUMMARY.md delete mode 100644 src/doc/style/errors/README.md delete mode 100644 src/doc/style/errors/ergonomics.md delete mode 100644 src/doc/style/errors/handling.md delete mode 100644 src/doc/style/errors/propagation.md delete mode 100644 src/doc/style/errors/signaling.md delete mode 100644 src/doc/style/features/README.md delete mode 100644 src/doc/style/features/crates.md delete mode 100644 src/doc/style/features/functions-and-methods/README.md delete mode 100644 src/doc/style/features/functions-and-methods/convenience.md delete mode 100644 src/doc/style/features/functions-and-methods/input.md delete mode 100644 src/doc/style/features/functions-and-methods/output.md delete mode 100644 src/doc/style/features/let.md delete mode 100644 src/doc/style/features/loops.md delete mode 100644 src/doc/style/features/match.md delete mode 100644 src/doc/style/features/modules.md delete mode 100644 src/doc/style/features/traits/README.md delete mode 100644 src/doc/style/features/traits/common.md delete mode 100644 src/doc/style/features/traits/extensions.md delete mode 100644 src/doc/style/features/traits/generics.md delete mode 100644 src/doc/style/features/traits/objects.md delete mode 100644 src/doc/style/features/traits/overloading.md delete mode 100644 src/doc/style/features/traits/reuse.md delete mode 100644 src/doc/style/features/types/README.md delete mode 100644 src/doc/style/features/types/conversions.md delete mode 100644 src/doc/style/features/types/newtype.md delete mode 100644 src/doc/style/ownership/README.md delete mode 100644 src/doc/style/ownership/builders.md delete mode 100644 src/doc/style/ownership/cell-smart.md delete mode 100644 src/doc/style/ownership/constructors.md delete mode 100644 src/doc/style/ownership/destructors.md delete mode 100644 src/doc/style/ownership/raii.md delete mode 100644 src/doc/style/platform.md delete mode 100644 src/doc/style/safety/README.md delete mode 100644 src/doc/style/safety/lib-guarantees.md delete mode 100644 src/doc/style/safety/unsafe.md delete mode 100644 src/doc/style/style/README.md delete mode 100644 src/doc/style/style/braces.md delete mode 100644 src/doc/style/style/comments.md delete mode 100644 src/doc/style/style/features.md delete mode 100644 src/doc/style/style/imports.md delete mode 100644 src/doc/style/style/naming/README.md delete mode 100644 src/doc/style/style/naming/containers.md delete mode 100644 src/doc/style/style/naming/conversions.md delete mode 100644 src/doc/style/style/naming/iterators.md delete mode 100644 src/doc/style/style/naming/ownership.md delete mode 100644 src/doc/style/style/optional.md delete mode 100644 src/doc/style/style/organization.md delete mode 100644 src/doc/style/style/whitespace.md delete mode 100644 src/doc/style/testing/README.md delete mode 100644 src/doc/style/testing/unit.md delete mode 100644 src/doc/style/todo.md diff --git a/src/doc/style/README.md b/src/doc/style/README.md deleted file mode 100644 index 8d837d1a1a916..0000000000000 --- a/src/doc/style/README.md +++ /dev/null @@ -1,64 +0,0 @@ -% Style Guidelines - -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. - -### 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 https://internals.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** - 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 deleted file mode 100644 index 508ede6c4a0ac..0000000000000 --- a/src/doc/style/SUMMARY.md +++ /dev/null @@ -1,50 +0,0 @@ -# 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) diff --git a/src/doc/style/errors/README.md b/src/doc/style/errors/README.md deleted file mode 100644 index 444da26ff8fed..0000000000000 --- a/src/doc/style/errors/README.md +++ /dev/null @@ -1,3 +0,0 @@ -% Errors - -> **[FIXME]** Add some general text here. diff --git a/src/doc/style/errors/ergonomics.md b/src/doc/style/errors/ergonomics.md deleted file mode 100644 index 269f2a289464a..0000000000000 --- a/src/doc/style/errors/ergonomics.md +++ /dev/null @@ -1,66 +0,0 @@ -% 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,ignore -use std::io::{File, Open, Write, IoError}; - -struct Info { - name: String, - age: i32, - rating: i32 -} - -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))); - try!(file.write_line(&format!("age: {}", info.age))); - try!(file.write_line(&format!("rating: {}", info.rating))); - return Ok(()); -} -``` - -over - -```rust,ignore -use std::io::{File, Open, Write, IoError}; - -struct Info { - name: String, - age: i32, - rating: i32 -} - -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)) { - Ok(_) => (), - Err(e) => return Err(e) - } - match file.write_line(&format!("age: {}", info.age)) { - Ok(_) => (), - Err(e) => return Err(e) - } - return file.write_line(&format!("rating: {}", info.rating)); -} -``` - -See -[the `result` module documentation](https://doc.rust-lang.org/stable/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 `std::io::Result` to painlessly propagate errors. diff --git a/src/doc/style/errors/handling.md b/src/doc/style/errors/handling.md deleted file mode 100644 index 9b8a00d73665b..0000000000000 --- a/src/doc/style/errors/handling.md +++ /dev/null @@ -1,7 +0,0 @@ -% Handling errors - -### Use thread isolation to cope with failure. [FIXME] - -> **[FIXME]** Explain how to isolate threads and detect thread failure for recovery. - -### Consuming `Result` [FIXME] diff --git a/src/doc/style/errors/propagation.md b/src/doc/style/errors/propagation.md deleted file mode 100644 index 0a347cd577b90..0000000000000 --- a/src/doc/style/errors/propagation.md +++ /dev/null @@ -1,8 +0,0 @@ -% 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 deleted file mode 100644 index 4038ec10b9ab5..0000000000000 --- a/src/doc/style/errors/signaling.md +++ /dev/null @@ -1,125 +0,0 @@ -% 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 thread 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 thread 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 thread. - -## 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 thread 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` type](https://doc.rust-lang.org/stable/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 deleted file mode 100644 index 09657503d20d1..0000000000000 --- a/src/doc/style/features/README.md +++ /dev/null @@ -1,9 +0,0 @@ -% 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 deleted file mode 100644 index 4748b05f17f74..0000000000000 --- a/src/doc/style/features/crates.md +++ /dev/null @@ -1,6 +0,0 @@ -% 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 deleted file mode 100644 index a3559ca3e7b6b..0000000000000 --- a/src/doc/style/features/functions-and-methods/README.md +++ /dev/null @@ -1,44 +0,0 @@ -% Functions and methods - -### Prefer methods to functions if there is a clear receiver. **[FIXME: needs RFC]** - -Prefer - -```rust,ignore -impl Foo { - pub fn frob(&self, w: widget) { ... } -} -``` - -over - -```rust,ignore -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 deleted file mode 100644 index 69fd3772a761f..0000000000000 --- a/src/doc/style/features/functions-and-methods/convenience.md +++ /dev/null @@ -1,43 +0,0 @@ -% 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 deleted file mode 100644 index 5b63a4514443c..0000000000000 --- a/src/doc/style/features/functions-and-methods/input.md +++ /dev/null @@ -1,203 +0,0 @@ -% Input to functions and methods - -### Let the client decide when to copy and where to place data. [FIXME: needs RFC] - -#### Copying: - -Prefer - -```rust,ignore -fn foo(b: Bar) { - // use b as owned, directly -} -``` - -over - -```rust,ignore -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,ignore -fn foo(b: Bar) -> Bar { ... } -``` - -over - -```rust,ignore -fn foo(b: Box) -> Box { ... } -``` - -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,ignore -fn foo>(c: T) { ... } -``` - -over any of - -```rust,ignore -fn foo(c: &[i32]) { ... } -fn foo(c: &Vec) { ... } -fn foo(c: &SomeOtherCollection) { ... } -``` - -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,ignore -fn foo(b: &Bar) { ... } -fn foo(b: &mut Bar) { ... } -``` - -over - -```rust,ignore -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,ignore -fn foo() -> (Bar, Bar) -``` - -over - -```rust,ignore -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,ignore -fn read(&mut self, buf: &mut [u8]) -> std::io::Result -``` - -(From the [Read trait](https://doc.rust-lang.org/stable/std/io/trait.Read.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](https://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,ignore -enum FooMode { - Mode1, - Mode2, - Mode3, -} -fn foo(mode: FooMode) { ... } -``` - -over - -```rust,ignore -fn foo(mode2: bool, mode3: bool) { - assert!(!mode2 || !mode3); - ... -} -``` - -Static enforcement usually comes at little run-time cost: it pushes the -costs to the boundaries. 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 `panic!` 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 deleted file mode 100644 index e26eee53367cf..0000000000000 --- a/src/doc/style/features/functions-and-methods/output.md +++ /dev/null @@ -1,56 +0,0 @@ -% 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,ignore -struct SearchResult { - found: bool, // item in container? - expected_index: usize // what would the item's index be? -} - -fn binary_search(&self, k: Key) -> SearchResult -``` -or - -```rust,ignore -fn binary_search(&self, k: Key) -> (bool, usize) -``` - -over - -```rust,ignore -fn binary_search(&self, k: Key) -> bool -``` - -#### Yield back ownership: - -Prefer - -```rust,ignore -fn from_utf8_owned(vv: Vec) -> Result> -``` - -over - -```rust,ignore -fn from_utf8_owned(vv: Vec) -> Option -``` - -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 deleted file mode 100644 index ba9787b45f13c..0000000000000 --- a/src/doc/style/features/let.md +++ /dev/null @@ -1,103 +0,0 @@ -% Let binding - -### Always separately bind RAII guards. [FIXME: needs RFC] - -Prefer - -```rust,ignore -fn use_mutex(m: sync::mutex::Mutex) { - let guard = m.lock(); - do_work(guard); - drop(guard); // unlock the lock - // do other work -} -``` - -over - -```rust,ignore -fn use_mutex(m: sync::mutex::Mutex) { - 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,ignore -let foo = match bar { - Baz => 0, - Quux => 1 -}; -``` - -over - -```rust,ignore -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,ignore -let v = s.iter().map(|x| x * 2) - .collect::>(); -``` - -over - -```rust,ignore -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,ignore -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 deleted file mode 100644 index b144825f98183..0000000000000 --- a/src/doc/style/features/loops.md +++ /dev/null @@ -1,13 +0,0 @@ -% 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 deleted file mode 100644 index 0d5a1184a0e87..0000000000000 --- a/src/doc/style/features/match.md +++ /dev/null @@ -1,26 +0,0 @@ -% Pattern matching - -### Dereference `match` targets when possible. [FIXME: needs RFC] - -Prefer - -~~~~ignore -match *foo { - X(...) => ... - Y(...) => ... -} -~~~~ - -over - -~~~~ignore -match foo { - box X(...) => ... - box Y(...) => ... -} -~~~~ - - - - - diff --git a/src/doc/style/features/modules.md b/src/doc/style/features/modules.md deleted file mode 100644 index 995c5fda8a0aa..0000000000000 --- a/src/doc/style/features/modules.md +++ /dev/null @@ -1,133 +0,0 @@ -% 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 hierarchy to organize APIs into coherent sections. [FIXME] - -> **[FIXME]** Flesh this out with examples; explain what a "coherent -> section" is with examples. -> -> The module hierarchy 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,ignore -pub mod foo; - -// in foo.rs or foo/mod.rs -pub fn bar() { println!("..."); } -/* ... */ -``` - -rather than declaring it inline: - -```rust,ignore -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`](https://doc.rust-lang.org/std/io/). Many of the submodules lack -children, like -[`io::fs`](https://doc.rust-lang.org/std/io/fs/) -and -[`io::stdio`](https://doc.rust-lang.org/std/io/stdio/). -On the other hand, -[`io::net`](https://doc.rust-lang.org/std/io/net/) -contains submodules, so it lives in a separate directory: - -```text -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 hierarchy 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](https://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`](https://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`](https://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 hierarchies for organization. [FIXME: needs RFC] - -> **[FIXME]** -> - Referencing internal modules from the standard library is subject to -> becoming outdated. - -Internal module hierarchies (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`](https://doc.rust-lang.org/std/io/), `mod mem` -provides implementations for -[`BufReader`](https://doc.rust-lang.org/std/io/struct.BufReader.html) -and -[`BufWriter`](https://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,ignore -// 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 deleted file mode 100644 index 1893db24466fa..0000000000000 --- a/src/doc/style/features/traits/README.md +++ /dev/null @@ -1,22 +0,0 @@ -% 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 deleted file mode 100644 index e8699c75229d3..0000000000000 --- a/src/doc/style/features/traits/common.md +++ /dev/null @@ -1,71 +0,0 @@ -% 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 `Debug`. -* Crate `url` defines type `Url`, without implementing `Debug`. -* Crate `webapp` imports from both `std` and `url`, - -There is no way for `webapp` to add `Debug` 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: - -```text -Clone, Debug, 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 deleted file mode 100644 index fc3a03c01f5a1..0000000000000 --- a/src/doc/style/features/traits/extensions.md +++ /dev/null @@ -1,7 +0,0 @@ -% 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 deleted file mode 100644 index f9dac1272c334..0000000000000 --- a/src/doc/style/features/traits/generics.md +++ /dev/null @@ -1,67 +0,0 @@ -% 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,ignore -fn from_iter>(iterator: T) -> SomeCollection -``` - -Here, the `Iterator` trait 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 below. -* _Precise types_. Because generics 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,ignore - fn binary(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` 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 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 deleted file mode 100644 index 34712ed1ae7f1..0000000000000 --- a/src/doc/style/features/traits/objects.md +++ /dev/null @@ -1,49 +0,0 @@ -% 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,ignore -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]) -> Frame { - ... - } -} - -fn make_gui() -> Box { - let b: Box = box Button::new(...); - let l: Box = box Label::new(...); - - box Frame::new([b, l]) as Box -} -``` - -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 deleted file mode 100644 index d7482c9619072..0000000000000 --- a/src/doc/style/features/traits/overloading.md +++ /dev/null @@ -1,7 +0,0 @@ -% 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 deleted file mode 100644 index feedd3937fc9d..0000000000000 --- a/src/doc/style/features/traits/reuse.md +++ /dev/null @@ -1,30 +0,0 @@ -% 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 implementations 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 i32 {} - -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 deleted file mode 100644 index d3b95d8a6e719..0000000000000 --- a/src/doc/style/features/types/README.md +++ /dev/null @@ -1,68 +0,0 @@ -% Data types - -### Use custom types to imbue meaning; do not abuse `bool`, `Option` or other core types. **[FIXME: needs RFC]** - -Prefer - -```rust,ignore -let w = Widget::new(Small, Round) -``` - -over - -```rust,ignore -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 deleted file mode 100644 index f0f230f57e557..0000000000000 --- a/src/doc/style/features/types/conversions.md +++ /dev/null @@ -1,22 +0,0 @@ -% 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 deleted file mode 100644 index 9646e3e82aa53..0000000000000 --- a/src/doc/style/features/types/newtype.md +++ /dev/null @@ -1,69 +0,0 @@ -% 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,ignore -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,ignore -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>>`. We wish to hide this type from the -client, so that the client's view of the return type is roughly `Iterator<(usize, -T)>`. We can do so using the newtype pattern: - -```rust,ignore -struct MyTransformResult(Enumerate>>); -impl Iterator<(usize, T)> for MyTransformResult { ... } - -fn my_transform>(iter: Iter) -> MyTransformResult { - ... -} -``` - -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 deleted file mode 100644 index 11bdb03a3a818..0000000000000 --- a/src/doc/style/ownership/README.md +++ /dev/null @@ -1,3 +0,0 @@ -% 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 deleted file mode 100644 index 3422591233275..0000000000000 --- a/src/doc/style/ownership/builders.md +++ /dev/null @@ -1,176 +0,0 @@ -% 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 - 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 thread 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::process::Command`](https://doc.rust-lang.org/stable/std/process/struct.Command.html) -is one example: - -```rust,ignore -// NOTE: the actual Command API does not use owned Strings; -// this is a simplified version. - -pub struct Command { - program: String, - args: Vec, - cwd: Option, - // 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) -> std::io::Result { - ... - } -} -``` - -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,ignore -// 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,ignore -// A simplified excerpt from std::thread::Builder - -impl ThreadBuilder { - /// Name the thread-to-be. Currently the name is used for identification - /// only in failure messages. - pub fn named(mut self, name: String) -> ThreadBuilder { - self.name = Some(name); - self - } - - /// Redirect thread-local stdout. - pub fn stdout(mut self, stdout: Box) -> ThreadBuilder { - self.stdout = Some(stdout); - // ^~~~~~ this is owned and cannot be cloned/re-used - self - } - - /// Creates and executes a new child thread. - 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 thread 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,ignore -// One-liners -ThreadBuilder::new().named("my_thread").spawn(proc() { ... }); - -// Complex configuration -let mut thread = ThreadBuilder::new(); -thread = thread.named("my_thread_2"); // must re-assign to retain ownership - -if reroute { - thread = thread.stdout(mywriter); -} - -thread.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 deleted file mode 100644 index cd027cc4aaffc..0000000000000 --- a/src/doc/style/ownership/cell-smart.md +++ /dev/null @@ -1,4 +0,0 @@ -% 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 deleted file mode 100644 index 51fc74ac1158a..0000000000000 --- a/src/doc/style/ownership/constructors.md +++ /dev/null @@ -1,62 +0,0 @@ -% Constructors - -### Define constructors as static, inherent methods. [FIXME: needs RFC] - -In Rust, "constructors" are just a convention: - -```rust,ignore -impl Vec { - pub fn new() -> Vec { ... } -} -``` - -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,ignore -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,ignore -pub struct Config { - pub color: Color, - pub size: Size, - pub shape: Shape, -} -``` - -provide a constructor if there are sensible defaults: - -```rust,ignore -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,ignore -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 deleted file mode 100644 index 1cfcd78d20da8..0000000000000 --- a/src/doc/style/ownership/destructors.md +++ /dev/null @@ -1,22 +0,0 @@ -% 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 thread 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 deleted file mode 100644 index 244e8096a1a2f..0000000000000 --- a/src/doc/style/ownership/raii.md +++ /dev/null @@ -1,12 +0,0 @@ -% 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 deleted file mode 100644 index d29d060b69461..0000000000000 --- a/src/doc/style/platform.md +++ /dev/null @@ -1,7 +0,0 @@ -% 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 deleted file mode 100644 index 1ac6e704d23eb..0000000000000 --- a/src/doc/style/safety/README.md +++ /dev/null @@ -1,19 +0,0 @@ -% 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 deleted file mode 100644 index 8ee64f1806a69..0000000000000 --- a/src/doc/style/safety/lib-guarantees.md +++ /dev/null @@ -1,81 +0,0 @@ -% 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` 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 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 deleted file mode 100644 index a8a50af044c29..0000000000000 --- a/src/doc/style/safety/unsafe.md +++ /dev/null @@ -1,22 +0,0 @@ -% 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 deleted file mode 100644 index 87449710543c0..0000000000000 --- a/src/doc/style/style/README.md +++ /dev/null @@ -1,5 +0,0 @@ -% 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 deleted file mode 100644 index 80323dba1d4c2..0000000000000 --- a/src/doc/style/style/braces.md +++ /dev/null @@ -1,77 +0,0 @@ -% Braces, semicolons, and commas [FIXME: needs RFC] - -### Opening braces always go on the same line. - -```rust,ignore -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,ignore -match foo { - bar => baz, - quux => { - do_something(); - do_something_else() - } -} -``` - -### `return` statements get semicolons. - -```rust,ignore -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,ignore -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 deleted file mode 100644 index af02d87cc8da8..0000000000000 --- a/src/doc/style/style/comments.md +++ /dev/null @@ -1,122 +0,0 @@ -% Comments [RFC #505] - -### Avoid block comments. - -Use line comments: - -```rust -// Wait for the main thread to return, and set the process error code -// appropriately. -``` - -Instead of: - -``` rust -/* - * Wait for the main thread 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,ignore -/// 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 thread 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 threads have finished executing. -/// -/// # Return value -/// -/// The return value is used as the process return code. 0 on success, 101 on -/// error. -``` - -### Code snippets - -Only use inner doc comments `//!` to write crate and module-level documentation, -nothing else. When using `mod` blocks, prefer `///` outside of the block: - -```rust -/// This module contains tests -mod test { - // ... -} -``` - -over - -```rust -mod test { - //! This module contains tests - - // ... -} -``` - -### Avoid inner doc comments. - -Use inner doc comments _only_ to document crates and file-level modules: - -```rust,ignore -//! The core library. -//! -//! The core library is a something something... -``` - -### Explain context. - -Rust doesn't have special constructors, only functions that return new -instances. These aren't visible in the automatically generated documentation -for a type, so you should specifically link to them: - -```rust,ignore -/// An iterator that yields `None` forever after the underlying iterator -/// yields `None` once. -/// -/// These can be created through -/// [`iter.fuse()`](trait.Iterator.html#method.fuse). -pub struct Fuse { - // ... -} -``` diff --git a/src/doc/style/style/features.md b/src/doc/style/style/features.md deleted file mode 100644 index 13cc37fc236ca..0000000000000 --- a/src/doc/style/style/features.md +++ /dev/null @@ -1,13 +0,0 @@ -## `return` [RFC #968] - -Terminate `return` statements with semicolons: - -``` rust,ignore -fn foo(bar: i32) -> Option { - if some_condition() { - return None; - } - - ... -} -``` diff --git a/src/doc/style/style/imports.md b/src/doc/style/style/imports.md deleted file mode 100644 index c958875ddb926..0000000000000 --- a/src/doc/style/style/imports.md +++ /dev/null @@ -1,50 +0,0 @@ -% 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,ignore -// 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,ignore -use option::Option; -use mem; - -let i: isize = 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 deleted file mode 100644 index 6d88a838f5f53..0000000000000 --- a/src/doc/style/style/naming/README.md +++ /dev/null @@ -1,115 +0,0 @@ -% 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` | - -

-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` | `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,ignore -mod foo { - pub struct Error { ... } -} -``` - -over - -```rust,ignore -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 deleted file mode 100644 index c352a5b1bf191..0000000000000 --- a/src/doc/style/style/naming/containers.md +++ /dev/null @@ -1,69 +0,0 @@ -% 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 thread 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,ignore -// 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 - -// Lookup element, failing if it is not found: -impl Index for Container { ... } -impl IndexMut for Container { ... } -``` - -#### Wrappers/Cells - -Prefer specific conversion functions like `as_bytes` or `into_vec` whenever -possible. Otherwise, use: - -```rust,ignore -// 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,ignore -// 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`: - -```rust,ignore -// Extract contents or fail if not available -fn assert(self) -> V -fn expect(self, &str) -> V -``` - -For `Result`: - -```rust,ignore -// 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 deleted file mode 100644 index 0287919c78aae..0000000000000 --- a/src/doc/style/style/naming/conversions.md +++ /dev/null @@ -1,32 +0,0 @@ -% 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 | - -

-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`, 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 deleted file mode 100644 index 945cbe4800cb0..0000000000000 --- a/src/doc/style/style/naming/iterators.md +++ /dev/null @@ -1,32 +0,0 @@ -% 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,ignore -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 -``` - -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 deleted file mode 100644 index 32cd8a1595afb..0000000000000 --- a/src/doc/style/style/naming/ownership.md +++ /dev/null @@ -1,34 +0,0 @@ -% 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 deleted file mode 100644 index d3c2178cc993f..0000000000000 --- a/src/doc/style/style/optional.md +++ /dev/null @@ -1,3 +0,0 @@ -* - -* diff --git a/src/doc/style/style/organization.md b/src/doc/style/style/organization.md deleted file mode 100644 index 85065406d761c..0000000000000 --- a/src/doc/style/style/organization.md +++ /dev/null @@ -1,14 +0,0 @@ -% 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 deleted file mode 100644 index c33c17c8e42a2..0000000000000 --- a/src/doc/style/style/whitespace.md +++ /dev/null @@ -1,133 +0,0 @@ -% 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,ignore -#[deprecated = "Use `bar` instead."] -fn foo(a: usize, b: usize) -> usize { - a + b -} -``` - -* Use a space after colons and commas: - -```rust,ignore -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,ignore -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,ignore -fn frobnicate(a: Bar, b: Bar, - c: Bar, d: Bar) - -> Bar { - ... -} - -fn foo( - 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,ignore -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,ignore -> 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,ignore -> 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,ignore -// 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 deleted file mode 100644 index a21f69414d326..0000000000000 --- a/src/doc/style/testing/README.md +++ /dev/null @@ -1,5 +0,0 @@ -% 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 deleted file mode 100644 index dbbe9fc3ac6da..0000000000000 --- a/src/doc/style/testing/unit.md +++ /dev/null @@ -1,30 +0,0 @@ -% Unit testing - -Unit tests should live in a `tests` submodule at the bottom of the module they -test. Mark the `tests` submodule with `#[cfg(test)]` so it is only compiled when -testing. - -The `tests` 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 tests { - #[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 deleted file mode 100644 index 28ef2a1832d8b..0000000000000 --- a/src/doc/style/todo.md +++ /dev/null @@ -1,5 +0,0 @@ -* [Containers and iteration]() -* [The visitor pattern]() -* [Concurrency]() -* [Documentation]() -* [Macros]()