-
Notifications
You must be signed in to change notification settings - Fork 0
Note style guide
Here are some rough guidelines to Rust style. They are followed unevenly and there's not necessarily consensus about everything here. More work is required.
- Lines should not be longer than 100 characters.
- Use spaces for indentation, not tabs.
- Type names and enumeration variants should be in
CamelCase
. - Acronyms should be camel case, too:
Uuid
, notUUID
. - Functions, methods, and variables should be
lowercase_with_underscores
where it helps readability. - Static variables should be in
ALL_CAPS
. - Constructors are methods called
new
ornew_with_more_details
. - Constructors that simply convert from another type are methods called
from_foo
. - When writing a binding to an external library, put the raw C bindings in a module called
ffi
(rather thanll
). Do not create high-level bindings calledhl
.
- trait examples: Copy, Owned, Const, Add, Sub, Num, Shr, Index, Encode, Decode, Reader, Writer, GenericPath
- extension traits: FooUtil. However, prefer default methods to extension traits.
- avoid words with suffixes (able, etc). try to use transitive verbs, nouns, and then adjectives in that order
Functions for converting between types should attempt to follow this:
-
as
: cheap conversions that are normally just converting a reference to a different type, but not changing the in-memory representation, e.g.string.as_bytes()
gives a&[u8]
view into a&str
. These don't consume the convertee. -
to
: expensive conversions that may allocate and copy data, e.g.string.to_owned()
copies a&str
to a new~str
. These also don't consume the convertee. -
into
: conversions that consume the convertee and almost always don't allocate new memory (they may change the in-memory representation, but will normally do so in-place), these are cheaper thanto
conversions, e.g.string.into_bytes()
converts a~str
to a~[u8]
without copying.
These are not hard rules, since generically implemented functions mean that an into
conversion that doesn't copy/allocate is impossible for some types, e.g. string.into_owned()
(from the Str
trait) doesn't copy when string
is ~str
, but it is forced to when string
is &str
or @str
.
Wrapped functions:
fn frobnicate(a: Bar,
b: Bar)
-> Bar {
code;
}
fn foo<T:This,
U:That>(
a: Bar,
b: Bar)
-> Baz {
code;
}
(Note: We need to adjust editors to do this automatically. This is not the current convention.)
The downside of this is, that the indendation level of many lines of code may change when the length of the function name changes.
- When writing cross-platform code, try to group platform-specific code into a module called
platform
. - Try to avoid
#[cfg]
directives outside thisplatform
module.
- Write
extern mod
directives first, then a blank line. - Put local imports first, then external imports, then
pub use
. - Avoid use of
use *
, except in tests.
Prefer to fully import types while module-qualifying functions, e.g.
use option::Option;
use cast;
let i: int = cast::transmute(Option(0));
-
It's OK to use
foo = bar;
-
Avoid importing functions, unless they're very common. Instead import up to the module you're going to use and then call
mod::func()
.
- Put tests in a test module at the bottom of the modules they test.
- Use
#[cfg(test)]
to only compile when testing. Example:
#[cfg(test)]
mod test {
}
deref the match target if you can. prefer
match *foo {
X(...) => ...
Y(...) => ...
}
instead of
match foo {
@X(...) => ...
@Y(...) => ...
}
multiple patterns in a single arm:
match foo {
bar(*)
| baz => quux,
x
| y
| z => {
quuux
}
}
only omit braces for single expressions
match foo {
bar => baz,
quux => {
do_something();
do_something_else();
}
}
Prefer line comments and avoid block comments. Reason: it avoids the debate about whether to put stars on every line, etc.
In doc comments, write sentences that begin with capital letters and end in a period, even in the short summary description.
Favor outer doc comments
/// Function documentation.
fn foo() {
...
}
Only use inner doc comments to document crates and file-level modules.
//! The core library.
//!
//! The core library is a something something...
Use full sentences that start with capitals and end with a period. See Doc-using-rustdoc.
Put types first, then implementations
TODO
TODO
Rust code in error messages should be enclosed in backquotes.
Examples:
found `true` in restricted position
Error messages should use the pattern "expected `X`, found `Y`".
mismatched types: expected `u16`, found `u8`
Trait names should be capitalized and should follow the pattern of Verb
or Verber
, except in cases where no verb seems sensible.
Examples:
Iterate
- Avoid
pub impl Type { ... }
. Instead putpub
modifiers on the method names. This allows a reader to immediately tell which methods are public at a glance.
The names of simple boolean predicates should start with "is_" or similarly be expressed using a "small question word".
The notable exception are generally established predicate names like "lt", "ge", etc.
Examples:
is_not_empty
A for
loop is always preferable to a while
loop unless the loop counts in a non-uniform way (making it difficult to express as a for
).
- Do we want to prefer 'top-down' organization?
- Prefer unsafe pointers to unsafely transmuting borrowed pointers