From 9d80dad9d8e5a3cda408a40e8b1809e6c1302dc6 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Mon, 31 Aug 2015 20:45:04 -0400 Subject: [PATCH 01/41] Added FAQ --- _config.yml | 2 + _layouts/faq.html | 98 +++++ css/style.css | 208 ++++++++++ faq.md | 963 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1271 insertions(+) create mode 100644 _layouts/faq.html create mode 100644 faq.md diff --git a/_config.yml b/_config.yml index d4bacfa14..116722f6b 100644 --- a/_config.yml +++ b/_config.yml @@ -1,2 +1,4 @@ name: The Rust Programming Language markdown: redcarpet +redcarpet: + extensions: ["tables"] diff --git a/_layouts/faq.html b/_layouts/faq.html new file mode 100644 index 000000000..51c232db8 --- /dev/null +++ b/_layouts/faq.html @@ -0,0 +1,98 @@ +--- +layout: default +--- + + + +
+ {{ content }} + +
+ + + + + diff --git a/css/style.css b/css/style.css index ace966057..d5f0772c7 100644 --- a/css/style.css +++ b/css/style.css @@ -383,3 +383,211 @@ ul.laundry-list { text-align: right; margin: 5px 10px 0 0; } + +.faq { + font-size: 16px; + line-height: 1.5em; + border-top: 1px solid #dedede; + margin-top: 2rem; + margin-bottom: 8rem; + padding-top: 4rem; + padding-right: 4rem; +} + + .faq p, + .faq ul, + .faq ol, + .faq blockquote, + .faq pre { + margin: 0 0 1rem 6rem; + font-family: "Source Serif Pro"; + } + + .faq ul, + .faq ol { + padding: 0; + } + + .faq ul { + counter-reset: uli; + } + + .faq ul > li { + list-style: none; + position: relative; + } + + .faq ul > li:before { + content: counter(uli); + counter-increment: uli; + color: #999; + position: absolute; + top: 0; + left: -1.5em; + width: 1em; + font-family: "Fira Sans"; + text-align: right; + } + + .faq ol { + counter-reset: oli; + } + + .faq ol > li { + list-style: none; + position: relative; + } + + .faq ol > li:before { + content: counter(oli); + counter-increment: oli; + color: #999; + position: absolute; + top: 0; + left: -1.5em; + width: 1em; + font-family: "Fira Sans"; + text-align: right; + } + + .faq blockquote { + border-left: .25em solid #dedede; + padding-left: 2rem; + } + + .faq blockquote p { + margin: 0; + } + + .faq h1 { + font-size: 2.5em; + line-height: 1.5em; + margin: 0 0 1rem 6rem; + font-weight: 400; + position: relative; + } + + .faq h1::before { + content: "Draft"; + position: absolute; + top: 1.25rem; + left: -6rem; + font-size: 1.5rem; + line-height: 1em; + display: inline-block; + font-weight: 400; + color: hsla(50, 90%, 30%, 1); + text-align: center; + background-color: hsla(50, 90%, 80%, 1); + border-bottom: 3px solid hsla(50, 90%, 50%, 1); + padding: .55em .5em .2em; + border-radius: .25em; + } + + .faq h2 { + font-size: 2em; + line-height: 1.5em; + margin: 3rem 0 1rem; + font-weight: 400; + border-top: 4px solid #dedede; + padding-top: 1rem; + } + + .faq h2 a { + color: #333; + text-decoration: none; + } + + .faq h3 { + font-size: 1.5em; + line-height: 1.3em; + font-weight: 500; + margin: 3rem 0 1rem; + } + + .faq h2 + h3 { + margin-top: 2rem; + } + + .faq h4 { + font-size: 1em; + line-height: 1.5em; + font-weight: 500; + margin: 2rem 0 .25rem; + } + + .faq li { + margin: 0; + padding: 0; + } + + .faq pre { + margin-top: 2rem; + margin-bottom: 2rem; + } + + .faq code { + display: inline-block; + padding: .1em .2em 0; + line-height: 1em; + background-color: #f7f7f7; + border-radius: .15em; + font-weight: 400; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + } + + .faq pre code { + font-size: 1em; + line-height: 1.5em; + } + + .faq .copyright { + font-size: .8em; + color: #999; + border-top: 1px solid #dedede; + margin-top: 6rem; + padding-top: 2rem; + } + +#toc { + margin-top: 2rem; + padding: 2rem; + background-color: #f7f7f7; + border-radius: .25em; + border: 1px solid #ccc; +} + + #toc h2 { + font-family: "Fira Sans"; + border: 0; + margin: 0 -2rem 2rem; + padding: 0 2rem 1rem; + font-size: 2rem; + line-height: 1.5em; + border-bottom: 1px solid #ccc; + } + + #toc ol { + counter-reset: tos; + margin: 0; + padding: 0; + -webkit-columns: 150px 3; + -moz-columns: 150px 3; + columns: 150px 3; + } + + #toc li { + margin-left: 1em; + } + + #toc li::before { + content: counter(tos); + counter-increment: tos; + } + +.todo { + background-color: #FFCC00; + padding: 1em 1em .75em; + border-radius: .25em; + font-family: "Fira Sans"; +} diff --git a/faq.md b/faq.md new file mode 100644 index 000000000..01914ab5e --- /dev/null +++ b/faq.md @@ -0,0 +1,963 @@ +--- +layout: faq +title: Frequently Asked Questions · The Rust Programming Language +--- + +# Frequently Asked Questions + +This document exists to answer some common questions about the Rust programming language. It is not a complete guide to the language, nor is it a tool for teaching the language. Rather, it exists as a reference to answer oft-repeated questions people in the Rust community encounter, and to clarify some of the design and history of the language. + +If there is some common or important question you feel is wrongly left unanswered here, feel free to [help us fix it](https://github.com/rust-lang/rust-www/blob/master/CONTRIBUTING.md). + +
+ +## Performance + +#### How fast is Rust? + +As always, this question is difficult to answer. There's still a lot of work to do on speed, and depending on what you're benchmarking, Rust has variable performance. + +That said, it is an explicit goal of Rust to be as fast as C++ for most things. Language decisions are made with performance in mind, and we want Rust to be as fast as possible. Given that Rust is built on top of LLVM, any performance improvements in it also help Rust become faster. + +#### Is Rust garbage collected? + +No. A language that requires a GC is a language that opts into a larger, more complex runtime than Rust cares for. Rust is usable on bare metal with no extra runtime. Additionally, garbage collection is frequently a source of non-deterministic behavior. Rust provides the tools to make using a GC possible and even pleasant, but it should not be a requirement for implementing the language. + +#### Why is my program compiled with `cargo build` slow? + +Did you compile with the `--release` flag? The Rust language uses a lot of optimizations in release mode that make the language competitive with C and C++, but you need to explicitly ask for them, as they also result in longer compilation times that may be undesirable during development. + +#### Why is Rust compilation slow? + +It's a combination of factors. Both the type inference and safety-related checks are fairly complex. They make life easier for the programmer, but they require some time to run. Add in the optimizations, and Rust's compilation is slower than a simpler language that doesn't provide Rust's safety guarantees. + +But all is not lost. The Rust compiler has evolved significantly over a number of years, and a lot of good work is being done to make it work faster. So expect improvements in compilation speed over time. + +#### Why is Rust's HashMap so slow? + +Rust's default hashing algorithm is cryptographically secure, which means it's great if you need something that can't be easily guessed at, but you pay for that with slower performance relative to a non-cryptographically secure algorithm. + +Even so, it's [actually not](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6) too bad. As you can see from [these benchmark comparisons](http://cglab.ca/~abeinges/blah/hash-rs/) of different hashing implementations in Rust, Rust's SipHash implementation (the default) is a solid choice for a wide variety of purposes. + +#### Can I run benchmarks using test::Bencher on the beta or stable channel? + +Sadly, no. The `test` feature, which is necessary for testing and benchmarking in Rust, is restricted to the nightly channel. + +#### Does Rust do tail-call optimization? + +In general, tail-call optimization is not guaranteed: see [here](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html) for a detailed explanation with references. There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. The compiler is still free to optimize tail-calls [when it pleases](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), however. + +#### Does Rust have a runtime? + +Rust has a [very small and limited runtime](https://github.com/Kimundi/lazy-static.rs) providing a heap, unwinding and backtrace support, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup. + +## Concurrency + +#### Can I use globals across threads without `unsafe`? + +No, even if the type implements `Sync`. + +Types which are `Sync` are thread-safe when multiple shared references to them are used concurrently. Types which are not `Sync` are not thread-safe, and thus when used in a global require `unsafe` to use. + +That being said, having multiple aliasing `&mut T`s is never allowed. Due to the nature of globals the borrow checker cannot possibly ensure that a `static` obeys the borrowing rules, so taking a mutable reference to a `static` is always unsafe. + +## Error Handling + +#### Why doesn't Rust have exceptions? + +The design issues of exception handling in programming language have been covered at length elsewhere. Exceptions complicate understanding of control-flow, they express validity/invalidity with a system outside of the type system, they interoperate poorly with multithreaded code (a major focus of Rust), the list goes on. + +Rust instead opted for a type-based approach to error handling, which is [covered at length in the book](https://doc.rust-lang.org/nightly/book/error-handling.html#the-limits-of-combinators) (the improved chapter is only on nightly at the moment, but will be on stable soon. Everything it covers works on stable). This fits more nicely with Rust's control flow, concurrency, and everything else. + +#### What's the deal with `unwrap()` everywhere? + +`unwrap()` is a function that gets the value out of an `Option` or `Result` and panics if its not there. It is useful both for causing catastrophic failure in certain cases, but it more useful for quick prototypes where you don't want to handle an error yet, or blog posts where error handling would distract from the main point. `unwrap()` shouldn't be your default way to handle errors, but it is a useful tool to have when you need it. + +#### Why do I get an error when I try to run example code that uses the `try!` macro? + +It's probably an issue with return types. The [`try!` macro](https://doc.rust-lang.org/stable/std/macro.try!.html) either extracts the value from a `Result`, or returns early with the error `Result` is carrying. This means that try only works for functions that return `Result` themselves, where the second type implements `From::from(err)`. + +#### Is there an easier way to do error handling than having `Result`s everywhere? + +If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you actually want. `Result` is an indicator that some computation may or may not complete. The fact that some languages allow you to ignore failure cases is an anti-feature. Forcing you to handle them is one of the ways that Rust encourages safety. So, if you really don't want to handle error, use `unwrap()`, but you should probably just handle the error for real. + +## Numerics + +#### Should I default to using `f32` or `f64`? + +The choice of which to use is dependent on the focus of the program. + +If you're interested in the greatest degree of precision with your floating point numbers, then `f64` is the preferred choice. If you're more interested in keeping the size of the value small, then `f32` is better. + +All things being equal, `f64` is likely a better default. + +#### Why can't I compare floats? + +You can! Floats implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) there is no total ordering for floating point numbers. + +So you can do all the normal comparison operations you would expect, but you can't use the `cmp` function. + +#### Why can't I use `f32` or `f64` as `HashMap` keys? + +In order to be used as a key in a `HashMap`, a type must implement the `Eq` and `Hash` traits. `f32` and `f64` implement `PartialEq`, but not `Eq`, because both types include `NaN` (stands for "not a number"). `NaN` values are not equal to any float, and are not equal to each other, so there is no total ordering over floating point types in Rust. This means that `f32` and `f64` can't be used as keys in a HashMap. + +#### How can I convert between numeric types? + +There are three ways: the `as` keyword, which does simple casting for primitive types, the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types), and `transmute`, which is an unsafe function that tells the compiler to treat the bits of one type as those of another type. + +## Syntax + +#### Why curly braces? Why can't everything be like Haskell/Python? + +Flexibility, simplicity, and correctness. Curly braces allow for more flexible syntax for the programmer, a simpler parser in the compiler, and help reduce the possibility of logic mistakes caused by incorrect indentation, like Apple's classic [goto fail](https://gotofail.com/) bug. + +#### I can leave out parentheses on if conditions, why do I have to put brackets around single line blocks? Why is the C style not allowed? + +A single line block may not always be a single line block. Forgetting to add in the brackets when you add a line to an `if` block can be the cause of some serious programming errors (just look at Apple's ["goto fail"](https://gotofail.com/) bug). In the interest of safety, Rust makes you use the blocks every time. + +#### Why is there no literal syntax for dictionaries? + +Dictionaries (or `HashMap`s in Rust parlance) aren't a primitive data type, and so they don't get literal syntax. If you want to make a `HashMap`, use `HashMap::new()`. + +#### When should I use an implicit return? + +You should use an implicit return everywhere it can be used. Unless you're writing an early return (before the end of a function, where typing `return` is mandatory), it should be implicit. + +#### Why aren't function signatures inferred? + +- Mechanically, it simplifies the inference algorithm; inference only requires looking at one function at a time. +- The same simplification goes double for human readers. A reader does not need an IDE running an inference algorithm across an entire crate to be able to guess at a function's argument types; it's always explicit and nearby. + +#### Why does `match` have to be exhaustive? + +`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to the `enum` in the future will prompt a compilation failure, rather than runtime panic. Second, it makes cost explicit. In general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched, though it could fall through if the type of the `match` expression is `()`. This sort of hidden cost and special casing is against the language's philosophy. It's easy to ignore all unspecified cases by using the `_` wildcard: + +```rust +match val.do_something() { + Cat(a) => { /* ... */ } + _ => { /* ... */ } +} +``` + +## Lifetimes + +#### Why lifetimes? + +Lifetimes are Rust's answer to garbage collection. They are a way of ensuring memory safety without paying hefty performance costs. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). + +#### Why is the lifetime syntax the way it is? + +The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticable, and fit nicely in a type right alonside traits and references. Alternative syntaxes have been discussed, but this seemed to work just fine. + +#### When is `Rc` useful? + +This is covered in the [official documentation for `Rc`](https://doc.rust-lang.org/stable/std/rc/). In short, `Rc` and its thread-safe cousin `Arc` are useful to express shared ownership of an immutable value, and have the system automatically deallocate the associated memory when no one has access to it. + +#### How do I return a borrow to something I created from a function? + +You need to ensure that the borrowed-to item will outlive the function. This can be done in two ways: by binding the output lifetime to some input lifetime, or by declaring the output lifetime as static. The first option is significantly better than the second. + +Here is an example of the each: + +```rust +// The first method +fn example1<'a>(s: &'a str) -> &'a str { + // Do something... +} + +// The second method +fn example2<'a>(s: &'a str) -> &'static str { + // Do something else... +} +``` + +The problem with declaring the lifetime as `static` is that it's rarely what you actually mean, and is instead a way of escaping the lifetime system. References with a `static` lifetime outlive everything else, and this means that they can be used in ways that would otherwise be invalid with the first method. + +#### How do I return a closure from a function? + +To return a closure from a function, it must be what's called a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own stack frame, so it is not dependent on its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer defined (put another way, it would allow reading potentially invalid memory). + +#### When are lifetimes required to be defined? + +Lifetimes can often be elided, as explained in the ["Lifetime elision" section](https://doc.rust-lang.org/book/lifetimes.html#lifetime-elision) of the Rust book. "Elided lifetimes" are those lifetimes with are implicit in any code containing references. They are automatically inserted by the compiler with the three following rules: + +- Each elided lifetime in a function’s arguments becomes a distinct lifetime parameter. +- If there is exactly one input lifetime, elided or not, that lifetime is assigned to all elided lifetimes in the return values of that function. +- If there are multiple input lifetimes, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes. + +If these rules would result in incorrect code elsewhere, then the Rust compiler will provide errors, and you will need to define the relevant lifetimes to correct that error. + +#### How can Rust guarantee "no null pointers"? + +Data values in the language can only be constructed through a fixed set of initializer forms. Each of those forms requires that its inputs already be initialized. A liveness analysis ensures that local variables are initialized before use. + +## Ownership + +#### How can I implement a graph or other data structure that contains cycles? + +There are two major options: + +- You can implement it using `Weak` or `Rc` to allow shared ownership of nodes, +although this approach pays the cost of memory management. +- You can implement it using `unsafe` code using raw pointers. This will be +more efficient, but bypasses Rust's safety guarantees. + +#### How can I define a struct that contains a pointer to one of its own fields? + +At the moment, you can't without `unsafe`. If you have a struct with a pointer to one of its own fields, the Rust compiler has no way to know if the pointed-to field will be destroyed before or after the containing struct, and so it can't guarantee that the pointer into the field won't potentially point to invalid memory. + +#### What does it mean to "consume a value"? + +"Consuming a value" means taking ownership of a value and then dropping it. When this is done, the value can't be used elsewhere. + +#### What is the difference between consuming and moving/taking ownership? + +Consuming means that the value has been dropped, and is no longer defined. With just a move, the value is still alive, but ownership has been transferred to a new owner, meaning the old owner can no longer modify it or lend out references. + +#### Why when I pass a struct to a function the compiler says it's been moved and I can't use it anymore, when the same doesn't happen for integers? + +If a type implements the `Copy` trait, then it will be copied when passed to a function. All numeric types in Rust implement `Copy`, but function types do not, so they are moved instead. This means that the function can no longer be used elsewhere, unless it is moved back out of the function via the return. + +#### How do you deal with a "Use of moved value" error? + +This error means that the value you're trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary. If it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. It may also be possible to implement `Copy` (for implicit copying, rather than moving) or `Clone` (explicit copying) for the type in question. If none of these are possible, you may want to return ownership of the value when the function is done, thus eliminating this error. + +#### What are the rules for using `self`, `&self`, or `&mut self` in a method declaration? + +If a method needs to consume the struct, declare it with `self` as the first parameter, if it only needs a reference use `&self`, and if it needs to mutate the struct without consuming it use `&mut self`. + +#### How can I understand the borrow checker? + +There is a certain desire to act as if the borrow checker is some mysterious zen master, doling out knocks on the head whenever its koans are misunderstood. The reality is a little different. In fact, the borrow checker is simply applying a couple simple rules, which can be found in the Rust book's [section on borrowing](https://doc.rust-lang.org/stable/book/references-and-borrowing.html#the-rules): + +> First, any borrow must last for a scope no greater than that of the owner. Second, you may have one or the other of these two kinds of borrows, but not both at the same time: +> +> - one or more references (&T) to a resource. +> - exactly one mutable reference (&mut T) + +Understanding these rules and understanding [lifetimes](https://doc.rust-lang.org/stable/book/lifetimes.html) is all you need to do to understand the borrow checker. + +#### How do deref coercions work? + +[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait, which looks like this: + +```rust +pub trait Deref { + type Target: ?Sized; + fn deref(&'a self) -> &'a Self::Target; +} +``` + +A Deref implementation indicates that the implementing type may be converted into `Target` by a call to the `deref` function, which takes an immutable reference of a certain lifetime to the calling struct, and returns a reference of the same lifetime to the target. + +You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html#implementors) for the standard library in the documentation. + +## Stability + +#### Can I use unstable features in the beta or stable channel? + +No, you cannot. Rust works hard to provide strong guarantees about the stability of the APIs provided on the beta and stable channels. When something is unstable, it means that we can't provide those guarantees for it yet, and don't want people relying on it staying the same. This gives us the opportunity to try changes in the wild on the nightly channel, while still maintaining strong guarantees for people seeking stability. + +Things stabilize all the time, and the beta and stable channels update every six weeks, so if you're waiting for a feature to be available without using the nightly channel, it should hopefully happen quickly. + +## Strings + +#### How can I convert a `String` or `Vec` to a slice (`&str` and `&[T]`)? + +Using Deref coercions! `Strings` and `Vec`s will automatically coerce to their respective slices when referenced. + +#### How can I convert from `&str` to `String` or the other way around? + +`String`s are automatically converted into `&str` when you take a reference of them. For example, the following code works: + +```rust +fn say_hello(name: &str) { + println!("Hello {}!", name); +} + +fn main() { + let s = "Jane Doe".to_owned(); + say_hello(&s); +} +``` + +The `to_owned()` is how you convert from a `&str` into a `String`. This is necessary because string literals in Rust are of type `&str`. In this particular example, making `s` into a `String` isn't actually necessary, and the code could be rewritten as: + +```rust +fn say_hello(name: &str) { + println!("Hello {}!", name); +} + +fn main() { + let s = "Jane Doe"; + say_hello(s); +} +``` + +#### How do I split a `String` into lines? + +The [`lines()`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.lines) function for `String`s provides an iterator over the lines of a string, which can then be `collect()`ed into a container of lines like so: + +```rust +let s = "This\nis\na\ntest"; +let v: Vec<&str> = s.lines().collect(); +``` + +#### What are the differences between the different string types? + +`String` is an owned string type, while `&str` is a string slice. For a more detailed explanation, [check out the Rust book](https://doc.rust-lang.org/stable/book/). + +#### How do I do O(1) character access in a `String`? + +You don't, not without converting the `String` into something else. If you do that, it comes with some serious caveats. Strings in Rust are all UTF-8 encoded, and O(1) access to characters is impossible in UTF-8. If you index by bytes as you normally would in ASCII strings you'll get a UTF-8 codepoint, which may or may not be an actual character. + +If you are absolutely certain your string is in fact ASCII, you can get O(1) access by indexing the underlying buffer like so: + +```rust +let s = "This is a test."; +let bytes = s.into_bytes(); +let c = bytes[2]; // 'i' character +``` + +But remember that this operation is almost certainly wrong most of the time. + +#### Why are strings UTF-8 by default? + +The `str` type is UTF-8 because we observe more text in the wild in this encoding – particularly in network transmissions, which are endian-agnostic – and we think it's best that the default treatment of I/O not involve having to recode codepoints in each direction. + +This does mean that indexed access to a Unicode codepoint inside a `str` value is an O(n) operation. On the one hand, this is clearly undesirable; on the other hand, this problem is full of trade-offs and we'd like to point a few important qualifications: + +Scanning a `str` for ASCII-range codepoints can still be done safely octet-at-a-time. If you use `.as_bytes()`, pulling out a `u8` costs only `O(1)` and produces a value that can be cast and compared to an ASCII-range `char`. So if you're (say) line-breaking on `'\n'`, octet-based treatment still works. UTF8 was well-designed this way. + +Most "character oriented" operations on text only work under very restricted language assumptions sets such as "ASCII-range codepoints only". Outside ASCII-range, you tend to have to use a complex (non-constant-time) algorithm for determining linguistic-unit (glyph, word, paragraph) boundaries anyways. We recommend using an "honest" linguistically-aware, Unicode-approved algorithm. + +The `char` type is UCS4. If you honestly need to do a codepoint-at-a-time algorithm, it's trivial to write a `type wstr = [char]`, and unpack a `str` into it in a single pass, then work with the `wstr`. In other words: the fact that the language is not "decoding to UCS4 by default" shouldn't stop you from decoding (or re-encoding any other way) if you need to work with that encoding. + +## Collections + +#### Can I implement data structures like vectors and linked lists efficiently in Rust? + +If your reason for implementing these data structures is to use them for other programs, there's no need, as all the common data structures are provided with the standard library. + +If, however, your reason is simply to learn, then you will likely need to dip into unsafe code. While these data structures _can_ be implemented entirely in safe Rust, the performance is likely to be worse than they would be with the use of unsafe code. The simple reason for this is that data structures like vectors and link lists rely on pointer and memory operations that are disallowed by safe Rust. + +For example, a doubly-linked list requires that there be two mutable references to each node, but this violates Rust's mutable reference aliasing rules. You can solve this using `Weak`, but the performance will be poorer than you likely want. + +#### How can I join a `Vec` (or an array) of strings into a single string? + +Whether the strings are owned strings (`String`) or string slices (`&str`), you can accomplish this with a fold, like so: + +```rust +fn main() { + // For vector of `&str` + let v1 = vec!["This ", "is ", "a ", "sentence."]; + let s1 = v1.iter.fold(String::new(), |acc, s| acc.push_str(s)); + println!("{}", s1); // >> This is a sentence. + + // For vector of `String` + let v2 = vec![ + "This ".to_owned(), + "is ".to_owned(), + "another ".to_owned(), + "sentence.".to_owned() + ]; + let s2 = v2.iter.fold(String::new(), |acc, &s| acc.push_str(s)); + println!("{}", s2); // >> This is another sentence. +} +``` + +#### How can I iterate over a `Vec` without moving/consuming it? + +The easiest way is by using `Vec`'s `IntoIterator` implementation, like so: + +```rust +let v = vec![1,2,3,4,5]; +for item in &v { + print!("{} ", item); +} +println!("\nLength: {}", v.len()); +``` + +The way Rust `for` loops work, they actually call `into_iter()` (which is defined in the `IntoIterator` trait) for whatever you are trying to iterate over. `IntoIterator` is implemented for `&'a Vec` and `&'a mut Vec`, meaning you can iterate over a vector without consuming it just be using `&v` or `&mut v` (for some vector `v`). + +#### How do you write a linked list in Rust? + +You probably don't need to. The Rust standard library provides a doubly-linked list for free. But if you're looking to do it just for personal edification, there are three ways of doing it: + +- Write it as a classic algebraic data-type (also called a "cons list"). This is easiest, but the performance characteristics aren't good at all +- Write it using `Weak` or `Rc` to allow shared ownership of nodes. This can work, but is also a pain. If you're using `Rc`, you need some way to break cycles, otherwise no memory will ever be freed. +- Use `unsafe`. This is the most performant, but also the toughest, because you can't rely on Rust's safety guarantees. + +#### Why do I need to type the array size in the array declaration? + +You don't necessarily have to. If you're declaring an array directly, the size is inferred based on the number of elements. But if you're declaring a function that takes an array, the compiler has to know how big that array will be. + +One thing to note is that currently Rust doesn't offer generics over arrays of different size. This is being worked on, but isn't available currently. If you'd like to accept a contiguous container of a variable number of values, use a Vec or slice (depending on whether you need ownership). + +## Documentation + +#### Where do I report issues in the Rust documentation? + +You can report issues in the Rust documentation on the Rust compiler [issue tracker](https://github.com/rust-lang/rust/issues). Make sure to read the [contributing guidelines](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md) first. + +#### How do I view rustdoc documentation for a library my project depends on? + +When you use `cargo doc` to generate documentation for your own project, it also generates docs for the active dependency versions. These are put into the `target/doc` directory of your project. Use `cargo doc --open` to open the docs after building them, or just open up `target/doc/index.html` yourself after building the docs. + +## Input / Output + +#### How do I read a file into a `String`? + +Using the `read_to_string()` method, which is defined on the `Read` trait in `std::io`. + +```rust +fn main() { + let mut f = try!(File::open("foo.txt")); + let mut s = String::new(); + try!(f.read_to_string(&mut s)); // `s` contains the contents of "foo.txt" +} +``` + +#### How do I read file input efficiently? + +The [`File` type](https://doc.rust-lang.org/stable/std/fs/struct.File.html) implements the `Read` trait, which has a variety of functions for reading and writing data, including `read()`, `read_to_end()`, `bytes()`, `chars()`, and `take()`. Each of these functions reads in a certain amount of input from a given file. `read()` reads input until the provided buffer is full. `read_to_end()` reads the entire buffer into a vector, allocating as much space as is needed. `bytes()` and `chars()` allow you to iterate over the bytes and characters of the file, respectively. Finally, `take()` allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need. + +#### How do I get command line arguments in Rust? + +The easiest way is to use `std::env::Args`, which provides an iterator over the input arguments. + +If you're looking for something more powerful, the [getopt](https://doc.rust-lang.org/getopts/getopts/index.html) and [docopt](https://github.com/docopt/docopt.rs) crates are both solid options. + +## Libraries + +#### How can I make an HTTP request? + +[Hyper](https://github.com/hyperium/hyper) is the most popular, but there are [a number of others as well](https://crates.io/search?q=http). + +#### How can I write a GUI application in Rust? + +There are a variety of ways to write GUI applications in Rust. Just check out [this list of GUI frameworks](https://github.com/kud1ing/awesome-rust#gui). + +#### How can I parse JSON/XML? + +[Serde](https://github.com/serde-rs/serde) is the recommended library for serialization and deserialization of Rust data to and from a number of different formats. + +#### Is there a standard 2D+ dimensional vector and shape crate? + +Not yet! Want to write one? + +#### How do I write an OpenGL app in Rust? + +[Glium](https://github.com/tomaka/glium) is the major library for OpenGL programming in Rust. [GLFW](https://github.com/bjz/glfw-rs) is also a solid option. + +#### Can I write a video game in Rust? + +Yes you can! The major game programming library for Rust is [Piston](http://www.piston.rs/), and there's a whole [community for game programming in Rust](https://www.reddit.com/r/rust_gamedev/) as well. + +## Project + +#### What is this project's goal? + +To design and implement a safe, concurrent, practical, static systems language. + +Rust exists because other languages at this level of abstraction and efficiency are unsatisfactory. In particular: + +1. There is too little attention paid to safety. +2. They have poor concurrency support. +3. There is a lack of practical affordances. + +Rust exists as alternative language that provides both efficient code and a comfortable level of abstraction, while improving on all three of these points. + +#### Is this project controlled by Mozilla? + +No. Rust started as Graydon Hoare's part-time side project in 2006 and remained so for over 3 years. Mozilla got involved in 2009 once the language was mature enough to run basic tests and demonstrate its core concepts. Though it remains sponsored by Mozilla, Rust is developed by a diverse community of enthusiasts from many different places around the world. + +#### What are explicit non-goals of Rust? + +1. To employ any particularly cutting-edge technologies. Old, established techniques are better. +2. To prize expressiveness, minimalism or elegance above other goals. These are desirable but subordinate goals. +3. To cover the complete feature-set of C++, or any other language. It should provide majority-case features. +4. To be 100% static, 100% safe, 100% reflective, or too dogmatic in any other sense. Trade-offs exist. +5. To run on "every possible platform". It must eventually work without unnecessary compromises on widely-used hardware and software platforms. + +#### Who is using Rust? + +There are a number of companies using Rust, including: + +- [OpenDNS](https://labs.opendns.com/2013/10/04/zeromq-helping-us-block-malicious-domains/) +- [Skylight](https://www.skylight.io/) +- [Wit.ai](https://github.com/wit-ai/witd) +- [Codius](https://codius.org/blog/codius-rust/) +- [MaidSafe](http://maidsafe.net/) +- [Terminal.com](https://www.terminal.com/) + +#### In which projects is Mozilla using Rust? + +The main project is [Servo](https://github.com/servo/servo), an experimental browser engine Mozilla is working on. They are also working to integrate Rust components into Firefox. + +#### What examples are there of large Rust projects? + +The two biggest open source Rust projects right now are [Servo](https://github.com/servo/servo) and the [Rust compiler](https://github.com/rust-lang/rust) itself. + +#### What projects are good examples of idiomatic Rust code? + +TODO: Write this answer. + +#### How can I try Rust easily? + +The easiest way to try Rust is through the [Playground](https://play.rust-lang.org/), an online app for writing and running Rust code. If you want to try it on your system, [install it](https://www.rust-lang.org/install.html) and go through the ["Learn Rust"](https://doc.rust-lang.org/stable/book/learn-rust.html) section of the book. + +#### How do I get help with Rust issues? + +There are several ways. You can: + +- Post in [/r/rust](https://www.reddit.com/r/rust), the official Rust subreddit +- Post in [users.rust-lang.org](https://users.rust-lang.org/), the official Rust forum +- Ask in the official [Rust IRC channel](https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) (#rust on irc.mozilla.org) + +#### Why has Rust changed so much over time? + +Rust started with a goal of creating a safe but usable systems programming language. In pursuit of this goal it explored a lot of ideas, some of which it kept (lifetimes, traits) others which it discarded (the typestate system). Also, in the run up to 1.0 a lot of the standard library was rewritten. Some of this was out of a desire to improve the old versions of the APIs. Some of it was out of a desire for improved Windows support. + +#### What IDE should I use? + +There are a couple developing options: [RustDT](https://github.com/RustDT/RustDT) is a Rust plugin for Eclipse, while [SolidOak](https://github.com/oakes/SolidOak) is a from-scratch Rust IDE. Both are solid options for a Rust IDE. + +## Modules and Crates + +#### What is the relationship between a module and a crate? + +- A crate is a top-level compilation unit that corresponds to a single loadable object. +- A module is a (possibly nested) unit of name-management inside a crate. +- A crate contains an implicit, un-named top-level module. +- Recursive definitions can span modules, but not crates. +- Crates do not have global names, only a set of non-unique metadata tags. +- There is no global inter-crate namespace; all name management occurs within a crate. +- Using another crate binds the root of its namespace into the user's namespace. + +#### Why do I have to declare module files with mod at the top level of the crate, instead of just `use`ing them? + +There are two ways to declare modules in Rust, inline or in another file. Here is an example of each: + +```rust +// In main.rs +mod hello { + pub fn f() { + println!("hello!"); + } +} + +fn main() { + hello::f(); +} +``` + +```rust +// In main.rs +mod hello; + +fn main() { + hello::f(); +} + +// In hello.rs +pub fn f() { + println!("hello!"); +} +``` + +In the first example, the module is defined in the same file it's used. In the second example, the module declaration in the main file tells the compiler to look for either `hello.rs` or `hello/mod.rs`, and to load that file. + +A `use`ing declaration just tells the compiler to bring everything from a particular module into the current module. Without a `mod` declaration first, the compiler doesn't know if the `use`d module exists, and so can't import its contents into the current module. + +#### How do I configure Cargo to use a proxy? + +As explained on the Cargo [configuration documentation](http://doc.crates.io/config.html), you can set Cargo to use a proxy by setting the "proxy" variable under `[http]` in the configuration file. + +#### Why can't the compiler find the method implementation even through I'm already `use`ing the crate? + +For methods defined on a trait, you have to explicitly import the trait declaration. This means it's not enough to import a module where a struct implements the trait, you must also important the module containing the trait itself. + +#### Why can't the compiler infer `use` declarations for me? + +It probably could, but you also don't want it to. While in many cases it is likely that the compiler could determine the correct module to import by simply looking for where a given identifier is defined, this may not be the case in general. Any decision rule in `rustc` for choosing between competing options would likely cause surprise and confusion, and not solve much of a problem. + +For example, the compiler could say that in the case of competing identifier definitions the definition from the earliest imported module is chosen. So if both module `foo` and module `bar` define the identifier `baz`, but `foo` is the first registered module, the compiler would insert `use foo::baz;`. + +```rust +mod foo; +mod bar; + +// use foo::baz // to be inserted by the compiler. + +fn main() { + baz(); +} +``` + +If you know this is going to happen, perhaps it saves a small number of keystrokes, but it also greatly increases the possibility for surprising error messages when you actually meant for `baz()` to be `bar::baz()`, and it decreases the readability of the code by making the meaning of a function call dependent on module declaration. These are not tradeoffs we are willing to make. + +#### How do I package and archive crates from [http://crates.io](http://crates.io)? + +TODO: Write this answer. + +#### How do I do dynamic Rust library loading? + +Importing dynamic libraries in Rust is done using [`std::dynamic_lib`](https://doc.rust-lang.org/std/dynamic_lib/index.html). Note that this entire module is currently marked unstable, and that a number of things may change in the current implementation. + +#### Why doesn't [http://crates.io](http://crates.io) have namespaces? + +Quoting the [official explanation](https://internals.rust-lang.org/t/crates-io-package-policies/1041) of [http://crates.io](http://crates.io)'s design: + +> In the first month with crates.io, a number of people have asked us about the possibility of introducing [namespaced packages](https://github.com/rust-lang/crates.io/issues/58).

+> +> While namespaced packages allow multiple authors to use a single, generic name, they add complexity to how packages are referenced in Rust code and in human communication about packages. At first glance, they allow multiple authors to claim names like `http`, but that simply means that people will need to refer to those packages as `wycats' http` or `reem's http`, offering little benefit over package names like `wycats-http` or `reem-http`.

+> +> When we looked at package ecosystems without namespacing, we found that people tended to go with more creative names (like `nokogiri` instead of "tenderlove's libxml2"). These creative names tend to be short and memorable, in part because of the lack of any hierarchy. They make it easier to communicate concisely and unambiguously about packages. They create exciting brands. And we've seen the success of several 10,000+ package ecosystems like NPM and RubyGems whose communities are prospering within a single namespace.

+> +> In short, we don't think the Cargo ecosystem would be better off if Piston chose a name like `bvssvni/game-engine` (allowing other users to choose `wycats/game-engine`) instead of simply `piston`.

+> +> Because namespaces are strictly more complicated in a number of ways,and because they can be added compatibly in the future should they become necessary, we're going to stick with a single shared namespace. + +#### Why are so many Rust answers on StackOverflow wrong? + +The Rust language has been around for a number of years, and only reached version 1.0 in May of 2015. In the time before then the language changed significantly, and a number of StackOverflow answers were given at the time of older versions of the language. + +Over time more and more answers will be offered for the current version, this improving this issue as the proportion of out-of-date answers is reduced. + +## Generics + +#### What is "monomorphisation"? + +Monomorphisation is the process by which Rust generates specific instances of a generic function based on the types of the various calls to that function. This is used to provide static dispatch for generic functions. For functions using trait objects for generics, dynamic dispatch is used instead, with calls to the function going through a vtable to identify specific function calls for the provided type implementing the given trait. + +#### What's the different between a function and a closure that doesn't capture any variables? + +Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the the struct can be called as a function. + +The big difference between these traits is how they take the `self` parameter. `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. + +#### What are higher-kinded types, why should I want them, and why doesn't Rust have them? + +Let's go through these one by one: + +First, higher-kinded types are types that take other types as parameters. Type constructors, like `Vec` are examples. What support for higher-kinded types means is that you can use these type constructors wherever you can use types, such as in a trait `impl`. + +Next, the lack of higher-kinded types makes expression of certain ideas far more tedious than it would otherwise be. For example, implementing a `Functor` trait (a math-y term for something which can be mapped over, obeying certain rules) without higher-kinded types is a pain. With higher-kinded types, it's as simple as (note: theoretical syntax, this does not actually work, and has no guarantee to be how higher-kinded types look when and if they're implemented): + +```rust +trait Functor { + fn fmap B>(&self, f: F) -> Self; +} +``` + +The part that Rust currently can't do is that `Self` above is a type constructor parameterized by another type constructor. This is what support for higher-kinded types lets you express. + +Finally, Rust doesn't currently have them simply because they haven't been a priority. There is nothing inherent to the language that stops us from implementing higher-kinded types, it just hasn't been done yet. There is an open RFC for implementing them, but no real proposal exists yet. If one comes around, it will definitely be considered. + +(Credit to anasaziwochi for his [useful explanation](https://www.reddit.com/r/rust/comments/2av5tv/why_does_rust_not_have_a_functor_trait/ciz6iwm) of higher-kinded types in Rust.) + +#### What do named type parameters in generic types mean? + +These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a simple `where` clause. In essence, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. + +#### Does Rust have type reflection? + +Rust does have limited type reflection through the `Reflect` and `Any` traits. `Reflect` is a marker trait (meaning it has no functions associated with it) that indicates a function expects a type which can be reflected over. It is implemented for all types. `Any` is automatically implemented for any type that is both `Reflect` and `'static`, and is used for basic dynamic typing, as in the following example: + +```rust +use std::any::Any; +fn foo(x: &T) { + let any: &Any = x; + if any.is::() { println!("u32"); } +} +``` + +Note that the above could be equivalently written as: + +```rust +#![feature(reflect_marker)] +use std::marker::Reflect; +use std::any::Any; +fn foo(x: &T) { + let any: &Any = x; + if any.is::() { println!("u32"); } +} +``` + +#### Can I override operators? Which ones and how? + +You can provide custom implementations for a variety of operators using their associated traits: `Add` for `+`, `Mult` for `*`. It looks like this: + +```rust +struct Foo; + +impl Add for Foo { + type Output = Foo; + fn add(self, rhs: Foo) -> Self::Output { + println!("Adding!"); + self + } +} +``` + +The following operators can be overloaded: + +| Operation | Trait | +|:--------------------|:-----------| +| `+` | `Add` | +| `binary -` | `Sub` | +| `*` | `Mul` | +| `/` | `Div` | +| `unary -` | `Neg` | +| `%` | `Rem` | +| `&` | `BitAnd` | +| | | `BitOr` | +| `^` | `BitXor` | +| `!` | `Not` | +| `<<` | `Shl` | +| `>>` | `Shr` | +| `*` | `Deref` | +| `mut *` | `DerefMut` | +| `[]` | `Index` | +| `mut []` | `IndexMut` | + +#### Why the split between `Eq`/`PartialEq` and `Ord`/`PartialOrd`? + +There are some types in Rust that have a partial ordering, or partial equality, but no total ordering or total equality. The floating point types `f32` and `f64` are examples of this. Because a floating point value may be `NaN`, and because `NaN`s aren't equal to any other floating point type, nor less than or greater to any other floating point type, nor equal to each other, these types _can't_ implement `Eq` and `Ord`, although they _can_ implement `PartialEq` and `PartialOrd`. + +## Debugging + +#### How do I debug Rust programs? + +Rust programs can be debugged using gdb or lldb, same as C and C++. In fact, every Rust installation comes with rust-gdb and rust-lldb, wrappers over gdb and lldb with Rust pretty-printing enabled. + +#### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? + +This error is usually caused by `unwrap()`ing a `None` or `Err`. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build` is also helpful). Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful. + +## Low-Level + +#### How do I `memcpy` bytes? + +To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapping bytes, use `std::ptr::cpy_nonoverlapping`. Both of these functions are `unsafe`, as both can be used to subvert the language's safety guarantees. Use caution when using them. + +#### Can Rust reasonably function without the standard library? + +Absolutely. Rust programs can be set to not load the standard library using the `#![no_std]` attribute. With this attribute set, you can continue to use the Rust core, which is nothing but the platform-agnostic primitives. As such, it doesn't include IO, concurrency, heap allocation, etc. Note however that `libcore` has not been stabilized. + +#### Can I write an operating system in Rust? + +Yes! In fact there are several projects underway doing just that, including [reenix](https://github.com/scialex/reenix) and [RustOS](https://github.com/ryanra/RustOS). + +#### How can I read or write numeric types like `i32` or `f64` in big-endian or little-endian format in a file or other byte stream? + +You should check out the [byteorder crate](http://burntsushi.net/rustdoc/byteorder/), which provides utilities for exactly that. + +#### Does Rust specify data layout? + +No. In the general case, `enum` and `struct` layout is undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested `enum`s, reordering fields to remove padding, etc. `enums` which carry no data ("C-like") are eligible to have a defined representation. Such `enums` are easily distinguished in that they are simply a list of names that carry no data: + +```rust +enum CLike { + A, + B = 32, + C = 34, + D +} +``` + +The `repr` attribute can be applied to such `enums` to give them the same representation as a primitive. This allows using Rust `enum`s in FFI where C `enum`s are also used, for most use cases. The attribute can also be applied to `struct`s to get the same layout as a C `struct` would. + +## Cross-Platform + +#### How do I build a Windows binary that doesn't display the console window? + +TODO: Write this answer. + +#### How I make the console-less binary not crash on panic!? + +TODO: Write this answer. + +#### What's the idiomatic way to express platform-specific behavior in Rust? + +Platform-specific behavior can be expressed using [conditional compilation attributes](https://doc.rust-lang.org/reference.html#conditional-compilation) such as `target_os`, `target_family`, `target_endian`, etc. + +#### Can Rust be used for Android/iOS programming? + +Yes it can! There are already examples of using Rust for both [Android](https://github.com/tomaka/android-rs-glue) and [iOS](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/). It does require a bit of work to set up, but Rust functions fine on both platforms. + +#### Can I run my Rust program in a web browser? + +There [are efforts](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/) to make Rust run in the web browser using Emscripten. Given that Rust is implemented on top of LLVM, this should be possible, but Rust currently runs on a special patched version of LLVM, and so it is tougher than it would otherwise be. This will likely improve over time. + +#### How do I cross-compile in Rust? + +Cross compilation is possible in Rust, but it requires a bit of work to set up, which is covered here: https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md + +## Design Patterns + +#### Is Rust object oriented? + +It is multi-paradigm. Not everything is shoe-horned into a single abstraction. Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you're accustomed to. + +#### How do I handle configuration of a struct with optional parameters? + +The easiest way is to use the `Option` type in whatever function you're using to construct instances of the struct (usually `new()`). Another way is to use the builder pattern, where only certain functions instantiating member variables must be called before the construction of the built type. + +#### How do I do global variables in Rust? + +Globals in Rust can be done using `const` declarations for compile-time computed global constants, while `static` can be used for mutable globals. Note that modifying a `static` variable requires the use of `unsafe`, as it allows for data races, one of the things guaranteed not to happen in safe Rust. + +#### How can I set compile-time constants that are defined procedurally (equivalent to constexpr in C++)? + +Rust currently has limited support for compile time constants. You can define primitives using `const` declarations (similar to `static`, but immutable). You can also define some compile-time constants using compiler plugins. The closest thing you have to full Compile-Time Function Evaluation (CTFE) is the [`lazy-static`](https://github.com/rust-lang-nursery/lazy-static.rs) crate, which lazily evaluates constants (guaranteed to be evaluated once) at runtime, rather than evaluating them at compile time. CTFE is open for consideration in the future, it simply hasn't been a priority thus far. + +#### Can I run initialization code that happens before main? + +Rust has no concept of "life before `main`". The closest you'll see can be done through the ["lazy_static"](https://github.com/Kimundi/lazy-static.rs) crate, which simulates a "before main" by lazily initializing static variables at their first usage. + +#### How do I map OO concepts to Rust? + +Trying to directly map object oriented programming concepts to Rust is unlikely to be fruitful. Rust has its own features and its own way of doing things, and you are better off learning how to use them than you are trying to simulate another style the language wasn't designed for. + +#### Why doesn't Rust have inheritance? + +There are two meanings for the word "inheritance": _subtyping_, and _interface sharing_. Both purposes are already handled by traits. + +For the first, subtyping exists for polymorphism, which traits already provide. + +For the second, interface sharing is handled via trait methods, which define a collection of related functions that must be implemented for any implementation of the trait. + +Rust has consistently worked to avoid having features with overlapping purposes, preferring to keep features orthogonal. For this reason, and given that the two major purposes are already handled by traits, Rust has opted not to include inheritance. + +#### Does Rust allow non-constant-expression values for globals? + +No. Globals can not have a non-constant-expression constructor and cannot have a destructor at all. This is an opinion of the language. Static constructors are undesirable because they can slow down program startup. Life before main is often considered a misfeature, never to be used. Rust helps this along by just not having the feature. + +See the [C++ FQA](http://yosefk.com/c++fqa/ctors.html#fqa-10.12) about the "static initialization order fiasco", and [Eric Lippert's blog](http://ericlippert.com/2013/02/06/static-constructors-part-one/) for the challenges in C#, which also has this feature. + +A nice replacement is the [lazy-static](https://github.com/rust-lang-nursery/lazy-static.rs) library by Marvin Löbel. + +## Macros + +#### Can I write a macro to generate identifiers? + +Not currently. Rust macros are so-called hygienic macros, not the unlimited compile-time syntax editing you see in C. Macro invocations can only appear in places where they are explicitly supported: items, methods declarations, statements, expressions, and patterns. Here, "method declarations" means a blank space where a method can be put. They can't be used to complete a partial method declaration. By the same logic, they can't be used to complete a partial variable declaration. + +## Other Languages + +### C + +#### How can I implement something like `struct X { static int X; };` in Rust? + +Rust does not have `static` fields as shown in the code snippet above. Instead, you can declare a `static` variable in a given module, which is kept private to that module. + +#### How can I convert a C-style enum to an integer, or vice-versa? + +Converting a C-style enum to an integer to an integer can be done with a simple `as` expression, like `e as i64` (where `e` is some enum). + +Converting in the other direction is a little tougher, as Rust can't statically ensure that the conversion is valid. As such, it requires `unsafe` via `unsafe::reinterpret_cast()`. + +#### Why does Rust not have an ABI like C does, and why do I have to annotate things with extern? + +Committing to an ABI is a big thing, and can limit potentially advantageous language changes in the future. Given that Rust only hit 1.0 in May of 2015, it is still too early to make a commitment as big as a stable ABI. This does not mean that one won't happen in the future, though. + +#### Can Rust code call C code? + +Yes. Calling C code from Rust is simple and exactly as efficient as calling C code from C. + +#### Can C code call Rust code? + +Yes. The Rust code has to be exposed via an `extern` declaration, which makes it C-ABI compatible. Such a function can be passed to C code as a function pointer or, if given the `#[no_mangle]` attribute to disable symbol mangling, can be called directly from C code. + +### C++ + +#### I already write perfect C++. What does Rust give me? + +Modern C++ has made a lot of strides to being a safe and comfortable programming language, but it's not perfect, and it's still very easy to do things unsafely. This is something the C++ core developers are working to overcome, but C++ is limited by a long history that predates a lot of the ideas they are now trying to implement. + +Rust was designed from day one to be a safe systems programming language, which means it's not limited by historic design decisions that make getting safety right in C++ so complicated. In C++, safety is achieved by careful personal discipline, and is very easy to get wrong. In Rust, safety is the default. + +#### How do I do the equivalent of C++ template specialization in Rust? + +Rust doesn't currently have an equivalent to template specialization, but it is [being worked on](https://github.com/rust-lang/rfcs/pull/1210) and will hopefully be added soon. + +#### How does Rust's ownership system related to move semantics in C++? + +In C++, moving vs copying was added on late with C++11. With Rust the concept of moving vs copying has been around from the beginning. In C++ something can be moved into a function or out of a function using r-value references and either `std::move` or `std::forward`. In Rust, moves happen for anything that does not implement the `Copy` trait (which will cause the value of the type to be copied, rather than moved). This means that moves are the default operation, and that copies must be opted into explicitly. + +One thing to note, however is that moves are often not necessary or desirable in Rust. If the function you're writing does not require ownership of the value being passed in, it should probably be borrowed (mutably or immutable, as necessary) rather than moved or copied. + +It's also useful to note that functions can explicitly require that an input parameter be copied like so: + +```rust +fn must_copy(t: T) { + // Do something in here... +} +``` + +#### How can I interoperate with C++ from Rust, or with Rust from C++? + +The simplest way is to interoperate through C. Both Rust and C++ provide a [foreign function interface](https://doc.rust-lang.org/book/ffi.html) for C, and can use that to communicate between each other. If writing C bindings is too tedious, you can always use [rust-bindgen](https://github.com/crabtw/rust-bindgen) to help automatically generate workable C bindings. + +#### Does Rust have C++-style constructors? + +No. Functions can serve the same purpose as constructors without adding any language complexity. + +#### Does Rust have copy constructors? + +Not exactly. Types which implement `Copy` will do a standard C-like "shallow copy" with no extra work (similar to "plain old data" in C++). It is impossible to implement `Copy` types that require custom copy behavior. Instead, in Rust "copy constructors" are created by implementing the `Clone` trait, and explicitly calling the `clone` method. Making user-defined copy operators explicit surfaces the underlying complexity, forcing the developer to opt-in to potentially expensive operations. + +#### Does Rust have move constructors? + +No. Values of all types are moved via `memcpy`. This makes writing generic unsafe code much simpler since assignment, passing and returning are known to never have a side effect like unwinding. + +### Swift + +#### Why does Rust not have the ? and ! like in Swift? + +In Swift, `?` is used to indicate an optional value. This is already done by `Option` in Rust, and so `?` is not needed. Similarly, `!` is used to "unwrap" an optional value in Swift, which is done by the `unwrap()` function in Rust. In both cases, Rust opted for slightly longer names which more clearly indicate intent. Also, in Rust the `!` symbol already indicates logical negation and macro calls, and does not need a third meaning. + +### Go + +#### How are Go and Rust similar, and how are they different? + +Rust and Go have substantially different design goals, and so differ substantially. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones: + +- Rust is lower level than Go, comparable with C, C++, D, and Nim. It provides access to memory management primitives that do not exist in Go (which has a garbage collector) +- Rust's focus is on ensuring safety and efficiency while also providing high-level affordances, while Go's is on being a small, simple language which compiles quickly and can work nicely with a variety of tools. +- Rust has strong support for generics, which Go does not +- Rust has strong influences from the world of functional programming, including a type system which draws from Haskell's typeclasses. Go has a simpler type system, using interfaces for basic generic programming + +Rust is probably not the best choice in every situation. If you're considering using either Rust or Go for a project it's probably best to try out both languages a bit and make an informed decision rather than base your decision on a small comparison of the two. + +#### `gofmt` is great. Where's `rustfmt`? + +`rustfmt` is [right here](https://github.com/nrc/rustfmt/), and is being actively developed to make reading Rust code as easy and predictable as possible. + +### Haskell + +#### How do Rust traits compare to Haskell typeclasses? + +Rust traits are similar to Haskell typeclasses, but are currently not as powerful. Rust traits cannot express functional dependencies or type families, nor does Rust have full support for higher-kinded types. Some of these may be added in the future, but are not provided currently. + +## Licensing + +#### Why a dual MIT/ASL2 License? + +The Apache license includes important protection against patent aggression, but it is not compatible with the GPL, version 2. To avoid problems using Rust with GPL2, it is alternately MIT licensed. + +#### Why a BSD-style permissive license rather than MPL or tri-license? + +This is partly due to preference of the original developer (Graydon), and partly due to the fact that languages tend to have a wider audience and more diverse set of possible embeddings and end-uses than products such as web browsers. We'd like to appeal to as many of those potential contributors as possible. + +## Naming + +#### Why is the language called Rust? + +As [stated by Graydon Hoare](https://www.reddit.com/r/rust/comments/27jvdt/internet_archaeology_the_definitive_endall_source/), original developer of the Rust language, the name "Rust" comes from his personal interest in fungi, and because it evoked the feeling he was looking for in a programming language name. But truly, as Graydon himself put it: + +> <graydon> IOW I don't have a really good explanation. it seemed like a good name. (also a substring of "trust", "frustrating", "rustic" and ... "thrust"?)
+> <graydon> I think I named it after fungi. rusts are amazing creatures. + From bea69ad6a469bcede7534fab2c02f7df42dfe3c6 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Thu, 22 Oct 2015 19:42:44 -0400 Subject: [PATCH 02/41] Updated FAQ --- faq.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/faq.md b/faq.md index 01914ab5e..983850fca 100644 --- a/faq.md +++ b/faq.md @@ -39,7 +39,7 @@ Rust's default hashing algorithm is cryptographically secure, which means it's g Even so, it's [actually not](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6) too bad. As you can see from [these benchmark comparisons](http://cglab.ca/~abeinges/blah/hash-rs/) of different hashing implementations in Rust, Rust's SipHash implementation (the default) is a solid choice for a wide variety of purposes. -#### Can I run benchmarks using test::Bencher on the beta or stable channel? +#### Can I run benchmarks using `test::Bencher` on the beta or stable channel? Sadly, no. The `test` feature, which is necessary for testing and benchmarking in Rust, is restricted to the nightly channel. @@ -65,17 +65,17 @@ That being said, having multiple aliasing `&mut T`s is never allowed. Due to the #### Why doesn't Rust have exceptions? -The design issues of exception handling in programming language have been covered at length elsewhere. Exceptions complicate understanding of control-flow, they express validity/invalidity with a system outside of the type system, they interoperate poorly with multithreaded code (a major focus of Rust), the list goes on. +The design issues for exception handling in programming language have been covered at length elsewhere. Exceptions complicate understanding of control-flow, they express validity/invalidity outside of the type system, they interoperate poorly with multithreaded code (a major focus of Rust), the list goes on. -Rust instead opted for a type-based approach to error handling, which is [covered at length in the book](https://doc.rust-lang.org/nightly/book/error-handling.html#the-limits-of-combinators) (the improved chapter is only on nightly at the moment, but will be on stable soon. Everything it covers works on stable). This fits more nicely with Rust's control flow, concurrency, and everything else. +Rust opted instead for a type-based approach to error handling, which is [covered at length in the book](https://doc.rust-lang.org/nightly/book/error-handling.html#the-limits-of-combinators) (the improved chapter is only on nightly at the moment, but will be on stable soon. Everything it covers works on stable). This fits more nicely with Rust's control flow, concurrency, and everything else. #### What's the deal with `unwrap()` everywhere? -`unwrap()` is a function that gets the value out of an `Option` or `Result` and panics if its not there. It is useful both for causing catastrophic failure in certain cases, but it more useful for quick prototypes where you don't want to handle an error yet, or blog posts where error handling would distract from the main point. `unwrap()` shouldn't be your default way to handle errors, but it is a useful tool to have when you need it. +`unwrap()` is a function that extracts the value inside an `Option` or `Result` and panics if its not there. It is useful both for causing catastrophic failure in certain cases, but it more useful for quick prototypes where you don't want to handle an error yet, or blog posts where error handling would distract from the main point. `unwrap()` shouldn't be your default way to handle errors, but it is a useful tool to have when you need it. #### Why do I get an error when I try to run example code that uses the `try!` macro? -It's probably an issue with return types. The [`try!` macro](https://doc.rust-lang.org/stable/std/macro.try!.html) either extracts the value from a `Result`, or returns early with the error `Result` is carrying. This means that try only works for functions that return `Result` themselves, where the second type implements `From::from(err)`. +It's probably an issue with the function's return type. The [`try!` macro](https://doc.rust-lang.org/stable/std/macro.try!.html) either extracts the value from a `Result`, or returns early with the error `Result` is carrying. This means that try only works for functions that return `Result` themselves, where the `Err`-constructed type implements `From::from(err)`. #### Is there an easier way to do error handling than having `Result`s everywhere? @@ -113,7 +113,7 @@ Flexibility, simplicity, and correctness. Curly braces allow for more flexible s #### I can leave out parentheses on if conditions, why do I have to put brackets around single line blocks? Why is the C style not allowed? -A single line block may not always be a single line block. Forgetting to add in the brackets when you add a line to an `if` block can be the cause of some serious programming errors (just look at Apple's ["goto fail"](https://gotofail.com/) bug). In the interest of safety, Rust makes you use the blocks every time. +A single line block may not always be a single line block. Forgetting to add in the brackets when you add a line to an `if` block can be the cause of some serious programming errors (just look at Apple's [“goto fail”](https://gotofail.com/) bug). In the interest of safety, Rust makes you use the blocks every time. #### Why is there no literal syntax for dictionaries? @@ -130,7 +130,7 @@ You should use an implicit return everywhere it can be used. Unless you're writi #### Why does `match` have to be exhaustive? -`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to the `enum` in the future will prompt a compilation failure, rather than runtime panic. Second, it makes cost explicit. In general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched, though it could fall through if the type of the `match` expression is `()`. This sort of hidden cost and special casing is against the language's philosophy. It's easy to ignore all unspecified cases by using the `_` wildcard: +`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to the `enum` in the future will cause a compilation failure, rather than an error at runtime. Second, it makes cost explicit. In general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched, though it could fall through if the type of the `match` expression is `()`. This sort of hidden cost and special casing is against the language's philosophy. It's easy to ignore all unspecified cases by using the `_` wildcard: ```rust match val.do_something() { @@ -147,7 +147,7 @@ Lifetimes are Rust's answer to garbage collection. They are a way of ensuring me #### Why is the lifetime syntax the way it is? -The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticable, and fit nicely in a type right alonside traits and references. Alternative syntaxes have been discussed, but this seemed to work just fine. +The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticable, and fit nicely in a type declaration right alonside traits and references. Alternative syntaxes have been discussed, but this seems to work just fine. #### When is `Rc` useful? @@ -155,7 +155,7 @@ This is covered in the [official documentation for `Rc`](https://doc.rust-lang.o #### How do I return a borrow to something I created from a function? -You need to ensure that the borrowed-to item will outlive the function. This can be done in two ways: by binding the output lifetime to some input lifetime, or by declaring the output lifetime as static. The first option is significantly better than the second. +You need to ensure that the borrowed item will outlive the function. This can be done in two ways: by binding the output lifetime to some input lifetime, or by declaring the output lifetime as static. The first option is significantly better than the second. Here is an example of the each: @@ -175,7 +175,7 @@ The problem with declaring the lifetime as `static` is that it's rarely what you #### How do I return a closure from a function? -To return a closure from a function, it must be what's called a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own stack frame, so it is not dependent on its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer defined (put another way, it would allow reading potentially invalid memory). +To return a closure from a function, it must be what's called a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own stack frame, so it is not dependent on its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer defined (put another way, it would allow reading potentially invalid memory). The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). #### When are lifetimes required to be defined? From 596d92cd3d6b70bb2ccf08e380f24af5ee439730 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Thu, 22 Oct 2015 19:50:35 -0400 Subject: [PATCH 03/41] Cleanup --- _layouts/faq.html | 95 +++-------------------------------------------- css/style.css | 24 ------------ faq.md | 38 ++++++++++++++++++- 3 files changed, 43 insertions(+), 114 deletions(-) diff --git a/_layouts/faq.html b/_layouts/faq.html index 51c232db8..cb2b21011 100644 --- a/_layouts/faq.html +++ b/_layouts/faq.html @@ -5,94 +5,11 @@
- {{ content }} - + {{ content }} +
- - - - diff --git a/css/style.css b/css/style.css index d5f0772c7..0bc60669d 100644 --- a/css/style.css +++ b/css/style.css @@ -467,23 +467,6 @@ ul.laundry-list { position: relative; } - .faq h1::before { - content: "Draft"; - position: absolute; - top: 1.25rem; - left: -6rem; - font-size: 1.5rem; - line-height: 1em; - display: inline-block; - font-weight: 400; - color: hsla(50, 90%, 30%, 1); - text-align: center; - background-color: hsla(50, 90%, 80%, 1); - border-bottom: 3px solid hsla(50, 90%, 50%, 1); - padding: .55em .5em .2em; - border-radius: .25em; - } - .faq h2 { font-size: 2em; line-height: 1.5em; @@ -584,10 +567,3 @@ ul.laundry-list { content: counter(tos); counter-increment: tos; } - -.todo { - background-color: #FFCC00; - padding: 1em 1em .75em; - border-radius: .25em; - font-family: "Fira Sans"; -} diff --git a/faq.md b/faq.md index 983850fca..18fa02eda 100644 --- a/faq.md +++ b/faq.md @@ -9,7 +9,35 @@ This document exists to answer some common questions about the Rust programming If there is some common or important question you feel is wrongly left unanswered here, feel free to [help us fix it](https://github.com/rust-lang/rust-www/blob/master/CONTRIBUTING.md). -
+ ## Performance @@ -499,9 +527,11 @@ The main project is [Servo](https://github.com/servo/servo), an experimental bro The two biggest open source Rust projects right now are [Servo](https://github.com/servo/servo) and the [Rust compiler](https://github.com/rust-lang/rust) itself. + #### How can I try Rust easily? @@ -597,9 +627,11 @@ fn main() { If you know this is going to happen, perhaps it saves a small number of keystrokes, but it also greatly increases the possibility for surprising error messages when you actually meant for `baz()` to be `bar::baz()`, and it decreases the readability of the code by making the meaning of a function call dependent on module declaration. These are not tradeoffs we are willing to make. + #### How do I do dynamic Rust library loading? @@ -771,13 +803,17 @@ The `repr` attribute can be applied to such `enums` to give them the same repres ## Cross-Platform + + #### What's the idiomatic way to express platform-specific behavior in Rust? From a5329311227a403b82bffab7e4208e71e228b1b6 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Thu, 22 Oct 2015 21:31:10 -0400 Subject: [PATCH 04/41] Corrections --- faq.md | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/faq.md b/faq.md index 18fa02eda..e1b478cf7 100644 --- a/faq.md +++ b/faq.md @@ -77,17 +77,13 @@ In general, tail-call optimization is not guaranteed: see [here](https://mail.mo #### Does Rust have a runtime? -Rust has a [very small and limited runtime](https://github.com/Kimundi/lazy-static.rs) providing a heap, unwinding and backtrace support, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup. +Rust has a [very small and limited runtime]() providing a heap, unwinding and backtrace support, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup. ## Concurrency #### Can I use globals across threads without `unsafe`? -No, even if the type implements `Sync`. - -Types which are `Sync` are thread-safe when multiple shared references to them are used concurrently. Types which are not `Sync` are not thread-safe, and thus when used in a global require `unsafe` to use. - -That being said, having multiple aliasing `&mut T`s is never allowed. Due to the nature of globals the borrow checker cannot possibly ensure that a `static` obeys the borrowing rules, so taking a mutable reference to a `static` is always unsafe. +Yes, if the type implements `Sync`, doesn't implement `Drop`, and you don't try to mutate the global value. ## Error Handling @@ -201,6 +197,10 @@ fn example2<'a>(s: &'a str) -> &'static str { The problem with declaring the lifetime as `static` is that it's rarely what you actually mean, and is instead a way of escaping the lifetime system. References with a `static` lifetime outlive everything else, and this means that they can be used in ways that would otherwise be invalid with the first method. +An alternative is to return an owning type like `String`. This eliminates the reference issues entirely, at the cost of possibly unnecessary allocations. + +There is also the `Cow` ("copy on write") type, which will only do the extra allocation if you attempt to mutate the contained value. + #### How do I return a closure from a function? To return a closure from a function, it must be what's called a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own stack frame, so it is not dependent on its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer defined (put another way, it would allow reading potentially invalid memory). The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). @@ -240,7 +240,7 @@ At the moment, you can't without `unsafe`. If you have a struct with a pointer t #### What is the difference between consuming and moving/taking ownership? -Consuming means that the value has been dropped, and is no longer defined. With just a move, the value is still alive, but ownership has been transferred to a new owner, meaning the old owner can no longer modify it or lend out references. +These are different terms for the same thing. In both cases, it means the value has been moved into a function, and moved out of the calling owner. #### Why when I pass a struct to a function the compiler says it's been moved and I can't use it anymore, when the same doesn't happen for integers? @@ -292,7 +292,7 @@ Things stabilize all the time, and the beta and stable channels update every six #### How can I convert a `String` or `Vec` to a slice (`&str` and `&[T]`)? -Using Deref coercions! `Strings` and `Vec`s will automatically coerce to their respective slices when referenced. +Using Deref coercions `Strings` and `Vec`s will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. #### How can I convert from `&str` to `String` or the other way around? @@ -337,7 +337,7 @@ let v: Vec<&str> = s.lines().collect(); #### How do I do O(1) character access in a `String`? -You don't, not without converting the `String` into something else. If you do that, it comes with some serious caveats. Strings in Rust are all UTF-8 encoded, and O(1) access to characters is impossible in UTF-8. If you index by bytes as you normally would in ASCII strings you'll get a UTF-8 codepoint, which may or may not be an actual character. +`str` implements both the `Index` and `IndexMut` traits, but because Rust strings are all UTF-8, and so it can be indexed exactly as you would expect. But if you do that, it comes with some serious caveats. Strings in Rust are all UTF-8 encoded, and O(1) access to characters is impossible in UTF-8. If you index by bytes as you normally would in ASCII strings you'll get a UTF-8 codepoint, which may or may not be an actual character. If you try to index a location that is not a valid UTF-8 boundary, the operation with panic, which makes it doubly unlikely that indexing is what you're looking for. If you are absolutely certain your string is in fact ASCII, you can get O(1) access by indexing the underlying buffer like so: @@ -359,7 +359,7 @@ Scanning a `str` for ASCII-range codepoints can still be done safely octet-at-a- Most "character oriented" operations on text only work under very restricted language assumptions sets such as "ASCII-range codepoints only". Outside ASCII-range, you tend to have to use a complex (non-constant-time) algorithm for determining linguistic-unit (glyph, word, paragraph) boundaries anyways. We recommend using an "honest" linguistically-aware, Unicode-approved algorithm. -The `char` type is UCS4. If you honestly need to do a codepoint-at-a-time algorithm, it's trivial to write a `type wstr = [char]`, and unpack a `str` into it in a single pass, then work with the `wstr`. In other words: the fact that the language is not "decoding to UCS4 by default" shouldn't stop you from decoding (or re-encoding any other way) if you need to work with that encoding. +The `char` type is UTF32. If you honestly need to do a codepoint-at-a-time algorithm, it's trivial to write a `type wstr = [char]`, and unpack a `str` into it in a single pass, then work with the `wstr`. In other words: the fact that the language is not "decoding to UTF32 by default" shouldn't stop you from decoding (or re-encoding any other way) if you need to work with that encoding. ## Collections @@ -565,6 +565,10 @@ There are a couple developing options: [RustDT](https://github.com/RustDT/RustDT - There is no global inter-crate namespace; all name management occurs within a crate. - Using another crate binds the root of its namespace into the user's namespace. +#### Why can't the Rust compiler find this library I'm `use`ing? + +There are a number of possible answers, but a common mistake is not realizing that `use` declarations are _always_ relative to the crate root. Try rewriting your declarations to use the paths they would use if defined in the root file of your project and see if that fixes the problem. + #### Why do I have to declare module files with mod at the top level of the crate, instead of just `use`ing them? There are two ways to declare modules in Rust, inline or in another file. Here is an example of each: @@ -663,6 +667,8 @@ Over time more and more answers will be offered for the current version, this im Monomorphisation is the process by which Rust generates specific instances of a generic function based on the types of the various calls to that function. This is used to provide static dispatch for generic functions. For functions using trait objects for generics, dynamic dispatch is used instead, with calls to the function going through a vtable to identify specific function calls for the provided type implementing the given trait. +In C++ people would likely know this as "template instantiation." But unlike C++, Rust's monomorphisation is an implementation detail, and not a language feature. + #### What's the different between a function and a closure that doesn't capture any variables? Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the the struct can be called as a function. @@ -921,9 +927,9 @@ Rust doesn't currently have an equivalent to template specialization, but it is #### How does Rust's ownership system related to move semantics in C++? -In C++, moving vs copying was added on late with C++11. With Rust the concept of moving vs copying has been around from the beginning. In C++ something can be moved into a function or out of a function using r-value references and either `std::move` or `std::forward`. In Rust, moves happen for anything that does not implement the `Copy` trait (which will cause the value of the type to be copied, rather than moved). This means that moves are the default operation, and that copies must be opted into explicitly. +In C++, moving vs copying was added on late with C++11. With Rust the concept of moving vs copying has been around from the beginning. In C++ something can be moved into a function or out of a function using r-value references and either `std::move` or `std::forward`. In Rust, moves happen for anything that does not implement the `Copy` trait (which will cause the value of the type to be copied, rather than moved). This means that moves are the default operation, and that copies must be opted into explicitly. It's also important to know that moves in Rust are destructive copies, which call `Drop` (equivalent to a C++ destructor) on the moved value. -One thing to note, however is that moves are often not necessary or desirable in Rust. If the function you're writing does not require ownership of the value being passed in, it should probably be borrowed (mutably or immutable, as necessary) rather than moved or copied. +Moves are often not necessary or desirable in Rust. If the function you're writing does not require ownership of the value being passed in, it should probably be borrowed (mutably or immutably, as necessary) rather than moved or copied. It's also useful to note that functions can explicitly require that an input parameter be copied like so: @@ -939,7 +945,25 @@ The simplest way is to interoperate through C. Both Rust and C++ provide a [fore #### Does Rust have C++-style constructors? -No. Functions can serve the same purpose as constructors without adding any language complexity. +No. Functions can serve the same purpose as constructors without adding any language complexity. The usual name for the constructor-equivalent function in Rust is `new()`, although this is just a social norm rather than a language rule. The `new()` function in fact is just like any other function. An example of it looks like so: + +```rust +struct Foo { + a: i32, + b: f64, + c: bool +} + +impl Foo { + fn new() -> Foo { + Foo { + a: 0, + b: 0.0, + c: false + } + } +} +``` #### Does Rust have copy constructors? From b7826590440e28520df61007b4d643326280ae4a Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 24 Oct 2015 11:16:51 -0400 Subject: [PATCH 05/41] Updated FAQ based on Diggsey's suggestions --- faq.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/faq.md b/faq.md index e1b478cf7..69bdbd27d 100644 --- a/faq.md +++ b/faq.md @@ -117,7 +117,7 @@ All things being equal, `f64` is likely a better default. #### Why can't I compare floats? -You can! Floats implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) there is no total ordering for floating point numbers. +You can! Floats implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) there is no total ordering for floating point numbers. There [is a crate](https://crates.io/crates/ordered-float) that provides a total ordering on floats by wrapping them, which may be desirable depending on your use-case. So you can do all the normal comparison operations you would expect, but you can't use the `cmp` function. @@ -232,7 +232,25 @@ more efficient, but bypasses Rust's safety guarantees. #### How can I define a struct that contains a pointer to one of its own fields? -At the moment, you can't without `unsafe`. If you have a struct with a pointer to one of its own fields, the Rust compiler has no way to know if the pointed-to field will be destroyed before or after the containing struct, and so it can't guarantee that the pointer into the field won't potentially point to invalid memory. +You can, but it's useless to do so. The struct becomes permanently borrowed by itself and therefore can't be moved. Here is some code illustrating this: + +```rust +use std::cell::Cell; + +#[derive(Debug)] +struct Unmovable<'a> { + x: u32, + y: Cell>, +} + + +fn main() { + let test = Unmovable { x: 42, y: Cell::new(None) }; + test.y.set(Some(&test.x)); + + println!("{:?}", test); +} +``` #### What does it mean to "consume a value"? From e94751d713d9a4d5158c50bc1403c2f4b564fa2a Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Fri, 6 Nov 2015 16:20:47 -0500 Subject: [PATCH 06/41] Addressing feedback --- faq.md | 205 +++++++++++++++++++++++++-------------------------------- 1 file changed, 91 insertions(+), 114 deletions(-) diff --git a/faq.md b/faq.md index 69bdbd27d..86a522fa1 100644 --- a/faq.md +++ b/faq.md @@ -5,7 +5,7 @@ title: Frequently Asked Questions · The Rust Programming Language # Frequently Asked Questions -This document exists to answer some common questions about the Rust programming language. It is not a complete guide to the language, nor is it a tool for teaching the language. Rather, it exists as a reference to answer oft-repeated questions people in the Rust community encounter, and to clarify some of the design and history of the language. +This page exists to answer common questions about the Rust programming language. It is not a complete guide to the language, nor is it a tool for teaching the language. It is a reference to answer oft-repeated questions people in the Rust community encounter, and to clarify the reasoning behind some of Rust's design decisions. If there is some common or important question you feel is wrongly left unanswered here, feel free to [help us fix it](https://github.com/rust-lang/rust-www/blob/master/CONTRIBUTING.md). @@ -39,63 +39,63 @@ If there is some common or important question you feel is wrongly left unanswere -## Performance +### Performance #### How fast is Rust? -As always, this question is difficult to answer. There's still a lot of work to do on speed, and depending on what you're benchmarking, Rust has variable performance. +Fast! Rust is already competitive with idiomatic C and C++ in a number of benchmarks. -That said, it is an explicit goal of Rust to be as fast as C++ for most things. Language decisions are made with performance in mind, and we want Rust to be as fast as possible. Given that Rust is built on top of LLVM, any performance improvements in it also help Rust become faster. +It is an explicit goal of Rust to be at least as fast as C++. Language decisions are made with performance in mind, and given that Rust is built on LLVM, any LLVM performance improvements also help Rust. #### Is Rust garbage collected? -No. A language that requires a GC is a language that opts into a larger, more complex runtime than Rust cares for. Rust is usable on bare metal with no extra runtime. Additionally, garbage collection is frequently a source of non-deterministic behavior. Rust provides the tools to make using a GC possible and even pleasant, but it should not be a requirement for implementing the language. +No. A language that requires a GC is a language that opts into a larger, more complex runtime than Rust cares for. Rust is usable on bare metal with no extra runtime. Additionally, garbage collection is frequently a source of non-deterministic behavior. Rust provides the tools to make using a GC [possible and even pleasant](http://manishearth.github.io/blog/2015/09/01/designing-a-gc-in-rust/), but it is not part of the language as provided. -#### Why is my program compiled with `cargo build` slow? +#### Why is my program slow? -Did you compile with the `--release` flag? The Rust language uses a lot of optimizations in release mode that make the language competitive with C and C++, but you need to explicitly ask for them, as they also result in longer compilation times that may be undesirable during development. +Did you compile with the `--release` flag? The Rust language uses a lot of optimizations in release mode, but you need to explicitly ask for them, as they also result in longer compilation times that may be undesirable during development. #### Why is Rust compilation slow? -It's a combination of factors. Both the type inference and safety-related checks are fairly complex. They make life easier for the programmer, but they require some time to run. Add in the optimizations, and Rust's compilation is slower than a simpler language that doesn't provide Rust's safety guarantees. +Most of the compilation time is spent in type checking and code translation, with some time also used for safety checks. All of these are required for the strong guarantees Rust makes, but they require some time to run. Add in optimizations, and Rust's compilation is slower than a simpler language that doesn't provide Rust's guarantees. -But all is not lost. The Rust compiler has evolved significantly over a number of years, and a lot of good work is being done to make it work faster. So expect improvements in compilation speed over time. +But all is not lost. The Rust compiler has evolved significantly over a number of years, and a lot of good work is being done to make it work faster, and to make it feel faster during development. #### Why is Rust's HashMap so slow? -Rust's default hashing algorithm is cryptographically secure, which means it's great if you need something that can't be easily guessed at, but you pay for that with slower performance relative to a non-cryptographically secure algorithm. +By default, Rust's `HashMap` uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). -Even so, it's [actually not](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6) too bad. As you can see from [these benchmark comparisons](http://cglab.ca/~abeinges/blah/hash-rs/) of different hashing implementations in Rust, Rust's SipHash implementation (the default) is a solid choice for a wide variety of purposes. +While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges/blah/hash-rs/) in many cases, one case where it is notably slower than other hashing algorithms is with short keys, such as integers. This is why Rust programmers often observe slow performance with `HashMap`. The [FNV hasher](https://crates.io/crates/fnv) is frequently recommended for these cases, but be aware that it does not have the same collision-resistence properties as SipHash. -#### Can I run benchmarks using `test::Bencher` on the beta or stable channel? +#### Why can't I run benchmarks? -Sadly, no. The `test` feature, which is necessary for testing and benchmarking in Rust, is restricted to the nightly channel. +You can run benchmarks, but only on the nightly channel. Rust's benchmarking mechanism is currently unstable, as the API has not been deemed ready for stabilization. This may change in the future, but until then benchmarking can only be used on nightly. #### Does Rust do tail-call optimization? -In general, tail-call optimization is not guaranteed: see [here](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html) for a detailed explanation with references. There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. The compiler is still free to optimize tail-calls [when it pleases](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), however. +In general, tail-call optimization is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html), but may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization). There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. The compiler is still free to optimize tail-calls [when it pleases](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), however, and the language has a word (`become`) reserved for future explicit tail calls. #### Does Rust have a runtime? -Rust has a [very small and limited runtime]() providing a heap, unwinding and backtrace support, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup. +Rust has a [very small and limited runtime](https://doc.rust-lang.org/std/rt/) providing a heap, unwinding and backtrace support, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup. -## Concurrency +### Concurrency #### Can I use globals across threads without `unsafe`? Yes, if the type implements `Sync`, doesn't implement `Drop`, and you don't try to mutate the global value. -## Error Handling +### Error Handling #### Why doesn't Rust have exceptions? -The design issues for exception handling in programming language have been covered at length elsewhere. Exceptions complicate understanding of control-flow, they express validity/invalidity outside of the type system, they interoperate poorly with multithreaded code (a major focus of Rust), the list goes on. +Exceptions complicate understanding of control-flow, they express validity/invalidity outside of the type system, and they interoperate poorly with multithreaded code (a major focus of Rust). -Rust opted instead for a type-based approach to error handling, which is [covered at length in the book](https://doc.rust-lang.org/nightly/book/error-handling.html#the-limits-of-combinators) (the improved chapter is only on nightly at the moment, but will be on stable soon. Everything it covers works on stable). This fits more nicely with Rust's control flow, concurrency, and everything else. +Rust prefers a type-based approach to error handling, which is [covered at length in the book](https://doc.rust-lang.org/stable/book/error-handling.html). This fits more nicely with Rust's control flow, concurrency, and everything else. #### What's the deal with `unwrap()` everywhere? -`unwrap()` is a function that extracts the value inside an `Option` or `Result` and panics if its not there. It is useful both for causing catastrophic failure in certain cases, but it more useful for quick prototypes where you don't want to handle an error yet, or blog posts where error handling would distract from the main point. `unwrap()` shouldn't be your default way to handle errors, but it is a useful tool to have when you need it. +`unwrap()` is a function that extracts the value inside an `Option` or `Result` and panics if no value is present. It is useful in the presence of truly unrecoverable errors, but is more useful for quick prototypes where you don't want to handle an error yet, or blog posts where error handling would distract from the main point. `unwrap()` shouldn't be your default way to handle errors, but it is a useful tool to have. #### Why do I get an error when I try to run example code that uses the `try!` macro? @@ -103,9 +103,9 @@ It's probably an issue with the function's return type. The [`try!` macro](https #### Is there an easier way to do error handling than having `Result`s everywhere? -If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you actually want. `Result` is an indicator that some computation may or may not complete. The fact that some languages allow you to ignore failure cases is an anti-feature. Forcing you to handle them is one of the ways that Rust encourages safety. So, if you really don't want to handle error, use `unwrap()`, but you should probably just handle the error for real. +If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you actually want. `Result` is an indicator that some computation may or may not complete successfully. The fact that some languages allow you to ignore failure cases is an anti-feature. Forcing you to handle them is one of the ways that Rust encourages safety. So, if you really don't want to handle error, use `unwrap()`, but you should probably just handle the error for real. -## Numerics +### Numerics #### Should I default to using `f32` or `f64`? @@ -117,44 +117,45 @@ All things being equal, `f64` is likely a better default. #### Why can't I compare floats? -You can! Floats implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) there is no total ordering for floating point numbers. There [is a crate](https://crates.io/crates/ordered-float) that provides a total ordering on floats by wrapping them, which may be desirable depending on your use-case. - -So you can do all the normal comparison operations you would expect, but you can't use the `cmp` function. +You can! Floats implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) there is no total ordering for floating point numbers. There [is a crate](https://crates.io/crates/ordered-float) that provides a total ordering on floats by wrapping them, which may be desirable depending on your use-case. You can still do all of the normal comparison operations you would expect, but you can't use the `cmp` function. #### Why can't I use `f32` or `f64` as `HashMap` keys? -In order to be used as a key in a `HashMap`, a type must implement the `Eq` and `Hash` traits. `f32` and `f64` implement `PartialEq`, but not `Eq`, because both types include `NaN` (stands for "not a number"). `NaN` values are not equal to any float, and are not equal to each other, so there is no total ordering over floating point types in Rust. This means that `f32` and `f64` can't be used as keys in a HashMap. +In order to be used as a key in a `HashMap`, a type must implement the `Eq` and `Hash` traits. `f32` and `f64` implement `PartialEq`, but not `Eq`, because both types include `NaN` (stands for "not a number"). `NaN` values are [not equal to any float, and are not equal to each other](https://en.wikipedia.org/wiki/NaN). This means that `f32` and `f64` can't be used as keys in a HashMap. #### How can I convert between numeric types? There are three ways: the `as` keyword, which does simple casting for primitive types, the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types), and `transmute`, which is an unsafe function that tells the compiler to treat the bits of one type as those of another type. -## Syntax +### Syntax #### Why curly braces? Why can't everything be like Haskell/Python? -Flexibility, simplicity, and correctness. Curly braces allow for more flexible syntax for the programmer, a simpler parser in the compiler, and help reduce the possibility of logic mistakes caused by incorrect indentation, like Apple's classic [goto fail](https://gotofail.com/) bug. +Use of curly braces to denote blocks is a common design choice in a variety of programming languages, and Rust's consistency is useful for people already familiar with the style. + +Curly braces also allow for more flexible syntax for the programmer, a simpler parser in the compiler, and help reduce the possibility of logic mistakes caused by incorrect indentation, like Apple's classic [goto fail](https://gotofail.com/) bug. #### I can leave out parentheses on if conditions, why do I have to put brackets around single line blocks? Why is the C style not allowed? -A single line block may not always be a single line block. Forgetting to add in the brackets when you add a line to an `if` block can be the cause of some serious programming errors (just look at Apple's [“goto fail”](https://gotofail.com/) bug). In the interest of safety, Rust makes you use the blocks every time. +Rust does not require parentheses around the conditional for `if`, `else if`, and the like. If C-style bracketless blocks were allowed, there would be no clear delineation between the condition and the body of the block. Requiring braces also eliminates the dangling-else problem, where nested if-else expressions can lead to ambiguity. #### Why is there no literal syntax for dictionaries? -Dictionaries (or `HashMap`s in Rust parlance) aren't a primitive data type, and so they don't get literal syntax. If you want to make a `HashMap`, use `HashMap::new()`. +Dictionaries (or `HashMap`s in Rust parlance) aren't a primitive data type, and so they don't get literal syntax. If you want more convenient syntax for `HashMap` creation, you can [create a macro](http://stackoverflow.com/questions/27582739/how-do-i-create-a-hashmap-literal/27582993#27582993) to provide it. #### When should I use an implicit return? -You should use an implicit return everywhere it can be used. Unless you're writing an early return (before the end of a function, where typing `return` is mandatory), it should be implicit. +Implicit returns are simply a coding style option, and can be used anywhere they make sense. While early returns require an explicit `return`, any other return can be made implicit according to your preferences or the preferences of your project. #### Why aren't function signatures inferred? -- Mechanically, it simplifies the inference algorithm; inference only requires looking at one function at a time. -- The same simplification goes double for human readers. A reader does not need an IDE running an inference algorithm across an entire crate to be able to guess at a function's argument types; it's always explicit and nearby. +- Mechanically, it simplifies the inference algorithm, as inference only requires looking at one function at a time. +- Mandatory function signatures help enforce interface stability at both the module and crate level. +- It improves code comprehension for programmer, eliminating the need for an IDE running an inference algorithm across an entire crate to be able to guess at a function's argument types; it's always explicit and nearby. #### Why does `match` have to be exhaustive? -`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to the `enum` in the future will cause a compilation failure, rather than an error at runtime. Second, it makes cost explicit. In general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched, though it could fall through if the type of the `match` expression is `()`. This sort of hidden cost and special casing is against the language's philosophy. It's easy to ignore all unspecified cases by using the `_` wildcard: +`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to an `enum` in the future will cause a compilation failure, rather than an error at runtime. Second, it makes cost explicit. In general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched, though it could fall through if the type of the `match` expression is `()`. This sort of hidden cost and special casing is against the language's philosophy. It is easy to ignore all unspecified cases by using the `_` wildcard: ```rust match val.do_something() { @@ -163,11 +164,11 @@ match val.do_something() { } ``` -## Lifetimes +### Lifetimes #### Why lifetimes? -Lifetimes are Rust's answer to garbage collection. They are a way of ensuring memory safety without paying hefty performance costs. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). +Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety without mechanisms like garbage collection which carry hefty performance costs. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). #### Why is the lifetime syntax the way it is? @@ -181,7 +182,7 @@ This is covered in the [official documentation for `Rc`](https://doc.rust-lang.o You need to ensure that the borrowed item will outlive the function. This can be done in two ways: by binding the output lifetime to some input lifetime, or by declaring the output lifetime as static. The first option is significantly better than the second. -Here is an example of the each: +Here is an example of each: ```rust // The first method @@ -203,11 +204,11 @@ There is also the `Cow` ("copy on write") type, which will only do the extra all #### How do I return a closure from a function? -To return a closure from a function, it must be what's called a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own stack frame, so it is not dependent on its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer defined (put another way, it would allow reading potentially invalid memory). The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). +To return a closure from a function, it must be a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own copy of the captured variables, independent of its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer valid (put another way, it would allow reading potentially invalid memory). The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). #### When are lifetimes required to be defined? -Lifetimes can often be elided, as explained in the ["Lifetime elision" section](https://doc.rust-lang.org/book/lifetimes.html#lifetime-elision) of the Rust book. "Elided lifetimes" are those lifetimes with are implicit in any code containing references. They are automatically inserted by the compiler with the three following rules: +Lifetimes can often be elided, as explained in the ["Lifetime elision" section](https://doc.rust-lang.org/book/lifetimes.html#lifetime-elision) of the Rust book. "Elided lifetimes" are those lifetimes which are implicit in any code containing references. They are automatically inserted by the compiler with the three following rules: - Each elided lifetime in a function’s arguments becomes a distinct lifetime parameter. - If there is exactly one input lifetime, elided or not, that lifetime is assigned to all elided lifetimes in the return values of that function. @@ -219,20 +220,21 @@ If these rules would result in incorrect code elsewhere, then the Rust compiler Data values in the language can only be constructed through a fixed set of initializer forms. Each of those forms requires that its inputs already be initialized. A liveness analysis ensures that local variables are initialized before use. -## Ownership +### Ownership #### How can I implement a graph or other data structure that contains cycles? -There are two major options: +There are three major options: - You can implement it using `Weak` or `Rc` to allow shared ownership of nodes, although this approach pays the cost of memory management. - You can implement it using `unsafe` code using raw pointers. This will be more efficient, but bypasses Rust's safety guarantees. +- Using vectors and indices into those vectors. There are [several](http://smallcultfollowing.com/babysteps/blog/2015/04/06/modeling-graphs-in-rust-using-vector-indices/) [available](http://featherweightmusings.blogspot.com/2015/04/graphs-in-rust.html) examples and explanations of this approach. #### How can I define a struct that contains a pointer to one of its own fields? -You can, but it's useless to do so. The struct becomes permanently borrowed by itself and therefore can't be moved. Here is some code illustrating this: +It's possible, but useless to do so. The struct becomes permanently borrowed by itself and therefore can't be moved. Here is some code illustrating this: ```rust use std::cell::Cell; @@ -254,15 +256,15 @@ fn main() { #### What does it mean to "consume a value"? -"Consuming a value" means taking ownership of a value and then dropping it. When this is done, the value can't be used elsewhere. +"Consuming a value" means taking ownership of a value. When this is done, the value can't be used elsewhere. #### What is the difference between consuming and moving/taking ownership? These are different terms for the same thing. In both cases, it means the value has been moved into a function, and moved out of the calling owner. -#### Why when I pass a struct to a function the compiler says it's been moved and I can't use it anymore, when the same doesn't happen for integers? +#### Why can I use integers after passing them to a function, but not structs? -If a type implements the `Copy` trait, then it will be copied when passed to a function. All numeric types in Rust implement `Copy`, but function types do not, so they are moved instead. This means that the function can no longer be used elsewhere, unless it is moved back out of the function via the return. +If a type implements the `Copy` trait, then it will be copied when passed to a function. All numeric types in Rust implement `Copy`, but struct types do not implement `Copy` by default, so they are moved instead. This means that the struct can no longer be used elsewhere, unless it is moved back out of the function via the return. #### How do you deal with a "Use of moved value" error? @@ -270,7 +272,9 @@ This error means that the value you're trying to use has been moved to a new own #### What are the rules for using `self`, `&self`, or `&mut self` in a method declaration? -If a method needs to consume the struct, declare it with `self` as the first parameter, if it only needs a reference use `&self`, and if it needs to mutate the struct without consuming it use `&mut self`. +- Use `self` when a function needs to consume the type +- Use `&self` when a function only needs a reference to the type +- Use `&mut self` when a function needs to mutate the type without consuming it #### How can I understand the borrow checker? @@ -281,7 +285,7 @@ There is a certain desire to act as if the borrow checker is some mysterious zen > - one or more references (&T) to a resource. > - exactly one mutable reference (&mut T) -Understanding these rules and understanding [lifetimes](https://doc.rust-lang.org/stable/book/lifetimes.html) is all you need to do to understand the borrow checker. +Understanding these rules and [lifetimes](https://doc.rust-lang.org/stable/book/lifetimes.html) is all you need to do to understand the borrow checker. #### How do deref coercions work? @@ -298,19 +302,19 @@ A Deref implementation indicates that the implementing type may be converted int You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html#implementors) for the standard library in the documentation. -## Stability +### Stability #### Can I use unstable features in the beta or stable channel? No, you cannot. Rust works hard to provide strong guarantees about the stability of the APIs provided on the beta and stable channels. When something is unstable, it means that we can't provide those guarantees for it yet, and don't want people relying on it staying the same. This gives us the opportunity to try changes in the wild on the nightly channel, while still maintaining strong guarantees for people seeking stability. -Things stabilize all the time, and the beta and stable channels update every six weeks, so if you're waiting for a feature to be available without using the nightly channel, it should hopefully happen quickly. +Things stabilize all the time, and the beta and stable channels update every six weeks. If you're waiting for a feature to be available without using the nightly channel, it should hopefully be available soon. -## Strings +### Strings #### How can I convert a `String` or `Vec` to a slice (`&str` and `&[T]`)? -Using Deref coercions `Strings` and `Vec`s will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. +Using Deref coercions, `Strings` and `Vec`s will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. #### How can I convert from `&str` to `String` or the other way around? @@ -351,13 +355,13 @@ let v: Vec<&str> = s.lines().collect(); #### What are the differences between the different string types? -`String` is an owned string type, while `&str` is a string slice. For a more detailed explanation, [check out the Rust book](https://doc.rust-lang.org/stable/book/). +`String` is an owned string type, while `&str` is a string slice. For a more detailed explanation, [check out the Rust book](https://doc.rust-lang.org/stable/book/strings.html). #### How do I do O(1) character access in a `String`? -`str` implements both the `Index` and `IndexMut` traits, but because Rust strings are all UTF-8, and so it can be indexed exactly as you would expect. But if you do that, it comes with some serious caveats. Strings in Rust are all UTF-8 encoded, and O(1) access to characters is impossible in UTF-8. If you index by bytes as you normally would in ASCII strings you'll get a UTF-8 codepoint, which may or may not be an actual character. If you try to index a location that is not a valid UTF-8 boundary, the operation with panic, which makes it doubly unlikely that indexing is what you're looking for. +Rust strings are UTF-8 encoded, and so one visual "character" may in fact be composed of multiple bytes of "code points." Rust provides several `String` methods which provide iterators over characters (`String::chars()`), bytes (`String::bytes()`), lines (`String::lines()`), and others which should perform as expected in O(n) time instead. -If you are absolutely certain your string is in fact ASCII, you can get O(1) access by indexing the underlying buffer like so: +If you are absolutely certain your string is in fact ASCII (and that each visual character is therefore one byte in size), you can get O(1) access by indexing the underlying buffer like so: ```rust let s = "This is a test."; @@ -365,8 +369,6 @@ let bytes = s.into_bytes(); let c = bytes[2]; // 'i' character ``` -But remember that this operation is almost certainly wrong most of the time. - #### Why are strings UTF-8 by default? The `str` type is UTF-8 because we observe more text in the wild in this encoding – particularly in network transmissions, which are endian-agnostic – and we think it's best that the default treatment of I/O not involve having to recode codepoints in each direction. @@ -375,15 +377,15 @@ This does mean that indexed access to a Unicode codepoint inside a `str` value i Scanning a `str` for ASCII-range codepoints can still be done safely octet-at-a-time. If you use `.as_bytes()`, pulling out a `u8` costs only `O(1)` and produces a value that can be cast and compared to an ASCII-range `char`. So if you're (say) line-breaking on `'\n'`, octet-based treatment still works. UTF8 was well-designed this way. -Most "character oriented" operations on text only work under very restricted language assumptions sets such as "ASCII-range codepoints only". Outside ASCII-range, you tend to have to use a complex (non-constant-time) algorithm for determining linguistic-unit (glyph, word, paragraph) boundaries anyways. We recommend using an "honest" linguistically-aware, Unicode-approved algorithm. +Most "character oriented" operations on text only work under very restricted language assumptions such as "ASCII-range codepoints only". Outside ASCII-range, you tend to have to use a complex (non-constant-time) algorithm for determining linguistic-unit (glyph, word, paragraph) boundaries anyway. We recommend using an "honest" linguistically-aware, Unicode-approved algorithm. -The `char` type is UTF32. If you honestly need to do a codepoint-at-a-time algorithm, it's trivial to write a `type wstr = [char]`, and unpack a `str` into it in a single pass, then work with the `wstr`. In other words: the fact that the language is not "decoding to UTF32 by default" shouldn't stop you from decoding (or re-encoding any other way) if you need to work with that encoding. +The `char` type is UTF32. If you are sure you need to do a codepoint-at-a-time algorithm, it's trivial to write a `type wstr = [char]`, and unpack a `str` into it in a single pass, then work with the `wstr`. In other words: the fact that the language is not "decoding to UTF32 by default" shouldn't stop you from decoding (or re-encoding any other way) if you need to work with that encoding. -## Collections +### Collections #### Can I implement data structures like vectors and linked lists efficiently in Rust? -If your reason for implementing these data structures is to use them for other programs, there's no need, as all the common data structures are provided with the standard library. +If your reason for implementing these data structures is to use them for other programs, there's no need, as efficient implementations of these data structures are provided by the standard library. If, however, your reason is simply to learn, then you will likely need to dip into unsafe code. While these data structures _can_ be implemented entirely in safe Rust, the performance is likely to be worse than they would be with the use of unsafe code. The simple reason for this is that data structures like vectors and link lists rely on pointer and memory operations that are disallowed by safe Rust. @@ -391,26 +393,7 @@ For example, a doubly-linked list requires that there be two mutable references #### How can I join a `Vec` (or an array) of strings into a single string? -Whether the strings are owned strings (`String`) or string slices (`&str`), you can accomplish this with a fold, like so: - -```rust -fn main() { - // For vector of `&str` - let v1 = vec!["This ", "is ", "a ", "sentence."]; - let s1 = v1.iter.fold(String::new(), |acc, s| acc.push_str(s)); - println!("{}", s1); // >> This is a sentence. - - // For vector of `String` - let v2 = vec![ - "This ".to_owned(), - "is ".to_owned(), - "another ".to_owned(), - "sentence.".to_owned() - ]; - let s2 = v2.iter.fold(String::new(), |acc, &s| acc.push_str(s)); - println!("{}", s2); // >> This is another sentence. -} -``` +You can do this using the [`join()`](http://doc.rust-lang.org/std/slice/trait.SliceConcatExt.html#tymethod.join) and [`concat()`](http://doc.rust-lang.org/std/slice/trait.SliceConcatExt.html#tymethod.concat) iterator methods. These allow the concatenation of items being iterated over, with `join()` inserting a separator of your choosing. #### How can I iterate over a `Vec` without moving/consuming it? @@ -426,21 +409,13 @@ println!("\nLength: {}", v.len()); The way Rust `for` loops work, they actually call `into_iter()` (which is defined in the `IntoIterator` trait) for whatever you are trying to iterate over. `IntoIterator` is implemented for `&'a Vec` and `&'a mut Vec`, meaning you can iterate over a vector without consuming it just be using `&v` or `&mut v` (for some vector `v`). -#### How do you write a linked list in Rust? - -You probably don't need to. The Rust standard library provides a doubly-linked list for free. But if you're looking to do it just for personal edification, there are three ways of doing it: - -- Write it as a classic algebraic data-type (also called a "cons list"). This is easiest, but the performance characteristics aren't good at all -- Write it using `Weak` or `Rc` to allow shared ownership of nodes. This can work, but is also a pain. If you're using `Rc`, you need some way to break cycles, otherwise no memory will ever be freed. -- Use `unsafe`. This is the most performant, but also the toughest, because you can't rely on Rust's safety guarantees. - #### Why do I need to type the array size in the array declaration? You don't necessarily have to. If you're declaring an array directly, the size is inferred based on the number of elements. But if you're declaring a function that takes an array, the compiler has to know how big that array will be. -One thing to note is that currently Rust doesn't offer generics over arrays of different size. This is being worked on, but isn't available currently. If you'd like to accept a contiguous container of a variable number of values, use a Vec or slice (depending on whether you need ownership). +One thing to note is that currently Rust doesn't offer generics over arrays of different size. This is a planned feature, but isn't available currently. If you'd like to accept a contiguous container of a variable number of values, use a Vec or slice (depending on whether you need ownership). -## Documentation +### Documentation #### Where do I report issues in the Rust documentation? @@ -450,23 +425,33 @@ You can report issues in the Rust documentation on the Rust compiler [issue trac When you use `cargo doc` to generate documentation for your own project, it also generates docs for the active dependency versions. These are put into the `target/doc` directory of your project. Use `cargo doc --open` to open the docs after building them, or just open up `target/doc/index.html` yourself after building the docs. -## Input / Output +### Input / Output #### How do I read a file into a `String`? Using the `read_to_string()` method, which is defined on the `Read` trait in `std::io`. ```rust -fn main() { - let mut f = try!(File::open("foo.txt")); +fn read_file(path: &str) -> Result { + let mut f = try!(File::open(path)); let mut s = String::new(); try!(f.read_to_string(&mut s)); // `s` contains the contents of "foo.txt" + s +} + +fn main() { + match read_file("foo.txt") { + Ok(_) => println!("Got file contents!"), + Err(err) => println!("Getting file contents failed with error: {}", err) + }; } ``` #### How do I read file input efficiently? -The [`File` type](https://doc.rust-lang.org/stable/std/fs/struct.File.html) implements the `Read` trait, which has a variety of functions for reading and writing data, including `read()`, `read_to_end()`, `bytes()`, `chars()`, and `take()`. Each of these functions reads in a certain amount of input from a given file. `read()` reads input until the provided buffer is full. `read_to_end()` reads the entire buffer into a vector, allocating as much space as is needed. `bytes()` and `chars()` allow you to iterate over the bytes and characters of the file, respectively. Finally, `take()` allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need. +The [`File` type](https://doc.rust-lang.org/stable/std/fs/struct.File.html) implements the `Read` trait, which has a variety of functions for reading and writing data, including `read()`, `read_to_end()`, `bytes()`, `chars()`, and `take()`. Each of these functions reads in a certain amount of input from a given file. `read()` reads as much input as the underlying system will provide in a single call. `read_to_end()` reads the entire buffer into a vector, allocating as much space as is needed. `bytes()` and `chars()` allow you to iterate over the bytes and characters of the file, respectively. Finally, `take()` allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need. + +For buffered reads, use the [`BufReader`](http://doc.rust-lang.org/stable/std/io/struct.BufReader.html) struct, which helps to reduce the number of system calls when reading. #### How do I get command line arguments in Rust? @@ -474,11 +459,13 @@ The easiest way is to use `std::env::Args`, which provides an iterator over the If you're looking for something more powerful, the [getopt](https://doc.rust-lang.org/getopts/getopts/index.html) and [docopt](https://github.com/docopt/docopt.rs) crates are both solid options. -## Libraries +If you're looking for something more powerful, there are a [number of options on crates.io](https://crates.io/keywords/argument). + +### Libraries #### How can I make an HTTP request? -[Hyper](https://github.com/hyperium/hyper) is the most popular, but there are [a number of others as well](https://crates.io/search?q=http). +[Hyper](https://github.com/hyperium/hyper) is the most popular, but there are [a number of others as well](https://crates.io/keywords/http). #### How can I write a GUI application in Rust? @@ -500,7 +487,7 @@ Not yet! Want to write one? Yes you can! The major game programming library for Rust is [Piston](http://www.piston.rs/), and there's a whole [community for game programming in Rust](https://www.reddit.com/r/rust_gamedev/) as well. -## Project +### Project #### What is this project's goal? @@ -782,7 +769,7 @@ The following operators can be overloaded: There are some types in Rust that have a partial ordering, or partial equality, but no total ordering or total equality. The floating point types `f32` and `f64` are examples of this. Because a floating point value may be `NaN`, and because `NaN`s aren't equal to any other floating point type, nor less than or greater to any other floating point type, nor equal to each other, these types _can't_ implement `Eq` and `Ord`, although they _can_ implement `PartialEq` and `PartialOrd`. -## Debugging +### Debugging #### How do I debug Rust programs? @@ -792,7 +779,7 @@ Rust programs can be debugged using gdb or lldb, same as C and C++. In fact, eve This error is usually caused by `unwrap()`ing a `None` or `Err`. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build` is also helpful). Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful. -## Low-Level +### Low-Level #### How do I `memcpy` bytes? @@ -825,7 +812,7 @@ enum CLike { The `repr` attribute can be applied to such `enums` to give them the same representation as a primitive. This allows using Rust `enum`s in FFI where C `enum`s are also used, for most use cases. The attribute can also be applied to `struct`s to get the same layout as a C `struct` would. -## Cross-Platform +### Cross-Platform +#### How can I read or write numeric types like `i32` or `f64` in big-endian or little-endian format in a file or other byte stream? -#### How can I try Rust easily? +You should check out the [byteorder crate](http://burntsushi.net/rustdoc/byteorder/), which provides utilities for exactly that. -The easiest way to try Rust is through the [Playground](https://play.rust-lang.org/), an online app for writing and running Rust code. If you want to try it on your system, [install it](https://www.rust-lang.org/install.html) and go through the ["Learn Rust"](https://doc.rust-lang.org/stable/book/learn-rust.html) section of the book. +#### Does Rust specify data layout? -#### How do I get help with Rust issues? +No. In the general case, `enum` and `struct` layout is undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested `enum`s, reordering fields to remove padding, etc. `enums` which carry no data ("C-like") are eligible to have a defined representation. Such `enums` are easily distinguished in that they are simply a list of names that carry no data: -There are several ways. You can: +```rust +enum CLike { + A, + B = 32, + C = 34, + D +} +``` -- Post in [users.rust-lang.org](https://users.rust-lang.org/), the official Rust forum -- Ask in the official [Rust IRC channel](https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) (#rust on irc.mozilla.org) -- Ask on [StackOverflow](http://stackoverflow.com/questions/tagged/rust) with the "rust" tag -- Post in [/r/rust](https://www.reddit.com/r/rust), the official Rust subreddit +The `repr` attribute can be applied to such `enums` to give them the same representation as a primitive. This allows using Rust `enum`s in FFI where C `enum`s are also used, for most use cases. The attribute can also be applied to `struct`s to get the same layout as a C `struct` would. -#### Why has Rust changed so much over time? +

Cross-Platform

-Rust started with a goal of creating a safe but usable systems programming language. In pursuit of this goal it explored a lot of ideas, some of which it kept (lifetimes, traits) while others were discarded (the typestate system). Also, in the run up to 1.0 a lot of the standard library was rewritten. Some of this was out of a desire to improve the old versions of the APIs. Some of it was out of a desire for improved Windows support. + -Rust maintains three "channels": stable, beta, and nightly. Stable and beta are updated every six weeks, with the current nightly becoming the new beta, and the current beta becoming the new stable. Language and standard library features marked unstable or hidden behind feature gates may only be used on the nightly channel. + -- Fixing compiler bugs -- Patching safety holes -- Changing type inference to require new annotations +#### What's the idiomatic way to express platform-specific behavior in Rust? -For details, read the Rust blog post ["Stability as a Deliverable."](http://blog.rust-lang.org/2014/10/30/Stability.html) +Platform-specific behavior can be expressed using [conditional compilation attributes](https://doc.rust-lang.org/reference.html#conditional-compilation) such as `target_os`, `target_family`, `target_endian`, etc. -#### What IDE should I use? +#### Can Rust be used for Android/iOS programming? -There are a couple developing options: [RustDT](https://github.com/RustDT/RustDT) is a Rust plugin for Eclipse, while [SolidOak](https://github.com/oakes/SolidOak) is a from-scratch Rust IDE. Both are solid options for a Rust IDE. Rust also integrates well with a variety of text editors. Detailed information about both text editor and IDE support can be found at [areweideyet.com](http://areweideyet.com/). +Yes it can! There are already examples of using Rust for both [Android](https://github.com/tomaka/android-rs-glue) and [iOS](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/). It does require a bit of work to set up, but Rust functions fine on both platforms. -## Modules and Crates +#### Can I run my Rust program in a web browser? + +There [are efforts](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/) to make Rust run in the web browser using Emscripten. Given that Rust is implemented on top of LLVM, this should be possible, but Rust currently runs on a special patched version of LLVM, and so it is tougher than it would otherwise be. This will likely improve over time. + +#### How do I cross-compile in Rust? + +Cross compilation is possible in Rust, but it requires [a bit of work](https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md) to set up. Rust does distribute [copies of the standard library](http://static.rust-lang.org/dist/) for each of the supported platforms, which are contained in the `rust-std-*` files for each of the build directories found on the distribution page. + +

Modules and Crates

#### What is the relationship between a module and a crate? @@ -668,196 +744,33 @@ The Rust language has been around for a number of years, and only reached versio Over time more and more answers will be offered for the current version, this improving this issue as the proportion of out-of-date answers is reduced. -## Generics - -#### What is "monomorphisation"? - -Monomorphisation is the process by which Rust generates specific instances of a generic function based on the types of the various calls to that function. This is used to provide static dispatch for generic functions. For functions using trait objects for generics, dynamic dispatch is used instead, with calls to the function going through a vtable to identify specific function calls for the provided type implementing the given trait. - -In C++ people would likely know this as "template instantiation." But unlike C++, Rust's monomorphisation is an implementation detail, and not a language feature. - -#### What's the difference between a function and a closure that doesn't capture any variables? - -Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the the struct can be called as a function. - -The big difference between these traits is how they take the `self` parameter. `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. - -#### What are higher-kinded types, why would I want them, and why doesn't Rust have them? - -Let's go through these one by one: - -First, higher-kinded types are types that take other types as parameters. Type constructors, like `Vec` are examples. What support for higher-kinded types means is that you can use these type constructors wherever you can use types, such as in a trait `impl`. - -Next, the lack of higher-kinded types makes expression of certain ideas far more tedious than it would otherwise be. For example, implementing a `Functor` trait (a math-y term for something which can be mapped over, obeying certain rules) without higher-kinded types is a pain. With higher-kinded types, it's as simple as (note: theoretical syntax, this does not actually work, and has no guarantee to be how higher-kinded types look when and if they're implemented): - -```rust -trait Functor { - fn fmap B>(&self, f: F) -> Self; -} -``` - -The part that Rust currently can't do is that `Self` above is a type constructor parameterized by another type constructor. This is what support for higher-kinded types lets you express. - -Finally, Rust doesn't currently have them simply because they haven't been a priority. There is nothing inherent to the language that stops us from implementing higher-kinded types, it just hasn't been done yet. There is an open RFC for implementing them, but no real proposal exists yet. If one comes around, it will definitely be considered. +

Libraries

-(Credit to anasaziwochi for his [useful explanation](https://www.reddit.com/r/rust/comments/2av5tv/why_does_rust_not_have_a_functor_trait/ciz6iwm) of higher-kinded types in Rust.) - -#### What do named type parameters in generic types mean? - -These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a simple `where` clause. In essence, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. - -#### Does Rust have type reflection? - -Rust does have limited type reflection through the `Reflect` and `Any` traits. `Reflect` is a marker trait (meaning it has no functions associated with it) that indicates a function expects a type which can be reflected over. It is implemented for all types. `Any` is automatically implemented for any type that is both `Reflect` and `'static`, and is used for basic dynamic typing, as in the following example, which implements a map indexed on the type of the mapped-to value: - -```rust -use std::any::{Any, TypeId}; -use std::collections::HashMap; - -type Entry = Box; - -#[derive(Debug)] -struct AnyMap(HashMap); - -impl AnyMap { - fn new() -> Self { - AnyMap(HashMap::new()) - } - - fn insert(&mut self, val: T) -> Option{ - self.0.insert(TypeId::of::(), Box::new(val) as Entry) - } - - fn get(&self) -> Option<&T> { - self.0.get(&TypeId::of::()).unwrap().downcast_ref() - } -} - -fn main() { - let mut map = AnyMap::new(); - map.insert(123i32); - map.insert(456i64); - - println!("{:?}", map); - println!("{:?}", map.get::()); -} -``` - -#### Can I override operators? Which ones and how? - -You can provide custom implementations for a variety of operators using their associated traits: `Add` for `+`, `Mult` for `*`. It looks like this: - -```rust -struct Foo; - -impl Add for Foo { - type Output = Foo; - fn add(self, rhs: Foo) -> Self::Output { - println!("Adding!"); - self - } -} -``` - -The following operators can be overloaded: - -| Operation | Trait | -|:--------------------|:-----------| -| `+` | `Add` | -| `binary -` | `Sub` | -| `*` | `Mul` | -| `/` | `Div` | -| `unary -` | `Neg` | -| `%` | `Rem` | -| `&` | `BitAnd` | -| | | `BitOr` | -| `^` | `BitXor` | -| `!` | `Not` | -| `<<` | `Shl` | -| `>>` | `Shr` | -| `*` | `Deref` | -| `mut *` | `DerefMut` | -| `[]` | `Index` | -| `mut []` | `IndexMut` | - -#### Why the split between `Eq`/`PartialEq` and `Ord`/`PartialOrd`? - -There are some types in Rust that have a partial ordering, or partial equality, but no total ordering or total equality. The floating point types `f32` and `f64` are examples of this. Because a floating point value may be `NaN`, and because `NaN`s aren't equal to any other floating point type, nor less than or greater to any other floating point type, nor equal to each other, these types _can't_ implement `Eq` and `Ord`, although they _can_ implement `PartialEq` and `PartialOrd`. - -### Debugging - -#### How do I debug Rust programs? - -Rust programs can be debugged using gdb or lldb, same as C and C++. In fact, every Rust installation comes with rust-gdb and rust-lldb, wrappers over gdb and lldb with Rust pretty-printing enabled. - -#### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? - -This error is usually caused by `unwrap()`ing a `None` or `Err`. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build` is also helpful). Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful. - -### Low-Level - -#### How do I `memcpy` bytes? - -To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapping bytes, use `std::ptr::cpy_nonoverlapping`. Both of these functions are `unsafe`, as both can be used to subvert the language's safety guarantees. Use caution when using them. - -#### Can Rust reasonably function without the standard library? - -Absolutely. Rust programs can be set to not load the standard library using the `#![no_std]` attribute. With this attribute set, you can continue to use the Rust core, which is nothing but the platform-agnostic primitives. As such, it doesn't include IO, concurrency, heap allocation, etc. Note however that `libcore` has not been stabilized. - -#### Can I write an operating system in Rust? - -Yes! In fact there are several projects underway doing just that, including [reenix](https://github.com/scialex/reenix), [RustOS](https://github.com/ryanra/RustOS), and [redox](http://www.redox-os.org/). - -#### How can I read or write numeric types like `i32` or `f64` in big-endian or little-endian format in a file or other byte stream? - -You should check out the [byteorder crate](http://burntsushi.net/rustdoc/byteorder/), which provides utilities for exactly that. - -#### Does Rust specify data layout? - -No. In the general case, `enum` and `struct` layout is undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested `enum`s, reordering fields to remove padding, etc. `enums` which carry no data ("C-like") are eligible to have a defined representation. Such `enums` are easily distinguished in that they are simply a list of names that carry no data: - -```rust -enum CLike { - A, - B = 32, - C = 34, - D -} -``` - -The `repr` attribute can be applied to such `enums` to give them the same representation as a primitive. This allows using Rust `enum`s in FFI where C `enum`s are also used, for most use cases. The attribute can also be applied to `struct`s to get the same layout as a C `struct` would. - -### Cross-Platform - - +[Hyper](https://github.com/hyperium/hyper) is the most popular, but there are [a number of others as well](https://crates.io/keywords/http). - +There are a variety of ways to write GUI applications in Rust. Just check out [this list of GUI frameworks](https://github.com/kud1ing/awesome-rust#gui). -#### What's the idiomatic way to express platform-specific behavior in Rust? +#### How can I parse JSON/XML? -Platform-specific behavior can be expressed using [conditional compilation attributes](https://doc.rust-lang.org/reference.html#conditional-compilation) such as `target_os`, `target_family`, `target_endian`, etc. +[Serde](https://github.com/serde-rs/serde) is the recommended library for serialization and deserialization of Rust data to and from a number of different formats. -#### Can Rust be used for Android/iOS programming? +#### Is there a standard 2D+ dimensional vector and shape crate? -Yes it can! There are already examples of using Rust for both [Android](https://github.com/tomaka/android-rs-glue) and [iOS](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/). It does require a bit of work to set up, but Rust functions fine on both platforms. +Not yet! Want to write one? -#### Can I run my Rust program in a web browser? +#### How do I write an OpenGL app in Rust? -There [are efforts](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/) to make Rust run in the web browser using Emscripten. Given that Rust is implemented on top of LLVM, this should be possible, but Rust currently runs on a special patched version of LLVM, and so it is tougher than it would otherwise be. This will likely improve over time. +[Glium](https://github.com/tomaka/glium) is the major library for OpenGL programming in Rust. [GLFW](https://github.com/bjz/glfw-rs) is also a solid option. -#### How do I cross-compile in Rust? +#### Can I write a video game in Rust? -Cross compilation is possible in Rust, but it requires [a bit of work](https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md) to set up. Rust does distribute [copies of the standard library](http://static.rust-lang.org/dist/) for each of the supported platforms, which are contained in the `rust-std-*` files for each of the build directories found on the distribution page. +Yes you can! The major game programming library for Rust is [Piston](http://www.piston.rs/), and there's both a [subreddit for game programming in Rust](https://www.reddit.com/r/rust_gamedev/) and an IRC channel (`#rust-gamedev` on [Mozilla IRC](https://wiki.mozilla.org/IRC)) as well. -### Design Patterns +

Design Patterns

#### Is Rust object oriented? @@ -905,13 +818,7 @@ See the [C++ FQA](http://yosefk.com/c++fqa/ctors.html#fqa-10.12) about the "stat However, `thread_local!` variables (which are restricted to a single thread) are effectively global for the thread in which they are defined, and may have a non-constant constructor and destructor. -## Macros - -#### Can I write a macro to generate identifiers? - -Not currently. Rust macros are so-called hygienic macros, not the unlimited compile-time syntax editing you see in C. Macro invocations can only appear in places where they are explicitly supported: items, methods declarations, statements, expressions, and patterns. Here, "method declarations" means a blank space where a method can be put. They can't be used to complete a partial method declaration. By the same logic, they can't be used to complete a partial variable declaration. - -### Other Languages +

Other Languages

#### How can I implement something like `struct X { static int X; };` in Rust? @@ -1016,7 +923,94 @@ Rust is probably not the best choice in every situation. If you're considering u Rust traits are similar to Haskell typeclasses, but are currently not as powerful. Rust traits cannot express functional dependencies or type families, nor does Rust have full support for higher-kinded types. Some of these may be added in the future, but are not provided currently. -### Licensing +

Documentation

+ +#### Where do I report issues in the Rust documentation? + +You can report issues in the Rust documentation on the Rust compiler [issue tracker](https://github.com/rust-lang/rust/issues). Make sure to read the [contributing guidelines](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md) first. + +#### How do I view rustdoc documentation for a library my project depends on? + +When you use `cargo doc` to generate documentation for your own project, it also generates docs for the active dependency versions. These are put into the `target/doc` directory of your project. Use `cargo doc --open` to open the docs after building them, or just open up `target/doc/index.html` yourself after building the docs. + +

Project

+ +#### What is this project's goal? + +To design and implement a safe, concurrent, practical, static systems language. + +Rust exists because other languages at this level of abstraction and efficiency are unsatisfactory. In particular: + +1. There is too little attention paid to safety. +2. They have poor concurrency support. +3. There is a lack of practical affordances. + +Rust exists as alternative language that provides both efficient code and a comfortable level of abstraction, while improving on all three of these points. + +#### Is this project controlled by Mozilla? + +No. Rust started as Graydon Hoare's part-time side project in 2006 and remained so for over 3 years. Mozilla got involved in 2009 once the language was mature enough to run basic tests and demonstrate its core concepts. Though it remains sponsored by Mozilla, Rust is developed by a diverse community of enthusiasts from many different places around the world. The [Rust Team](https://www.rust-lang.org/team.html) is composed of both Mozilla and non-Mozilla members. + +#### What are explicit non-goals of Rust? + +1. To employ any particularly cutting-edge technologies. Old, established techniques are better. +2. To prize expressiveness, minimalism or elegance above other goals. These are desirable but subordinate goals. +3. To cover the complete feature-set of C++, or any other language. It should provide majority-case features. +4. To be 100% static, 100% safe, 100% reflective, or too dogmatic in any other sense. Trade-offs exist. +5. To run on "every possible platform". It must eventually work without unnecessary compromises on widely-used hardware and software platforms. + +#### In which projects is Mozilla using Rust? + +The main project is [Servo](https://github.com/servo/servo), an experimental browser engine Mozilla is working on. They are also working to integrate Rust components into Firefox. + +#### What examples are there of large Rust projects? + +The two biggest open source Rust projects right now are [Servo](https://github.com/servo/servo) and the [Rust compiler](https://github.com/rust-lang/rust) itself. + + + +#### How can I try Rust easily? + +The easiest way to try Rust is through the [Playground](https://play.rust-lang.org/), an online app for writing and running Rust code. If you want to try it on your system, [install it](https://www.rust-lang.org/install.html) and go through the ["Learn Rust"](https://doc.rust-lang.org/stable/book/learn-rust.html) section of the book. + +#### How do I get help with Rust issues? + +There are several ways. You can: + +- Post in [users.rust-lang.org](https://users.rust-lang.org/), the official Rust forum +- Ask in the official [Rust IRC channel](https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) (#rust on irc.mozilla.org) +- Ask on [StackOverflow](http://stackoverflow.com/questions/tagged/rust) with the "rust" tag +- Post in [/r/rust](https://www.reddit.com/r/rust), the official Rust subreddit + +#### Why has Rust changed so much over time? + +Rust started with a goal of creating a safe but usable systems programming language. In pursuit of this goal it explored a lot of ideas, some of which it kept (lifetimes, traits) while others were discarded (the typestate system). Also, in the run up to 1.0 a lot of the standard library was rewritten. Some of this was out of a desire to improve the old versions of the APIs. Some of it was out of a desire for improved Windows support. + +#### How does Rust language versioning work? + +Rust maintains three "channels": stable, beta, and nightly. Stable and beta are updated every six weeks, with the current nightly becoming the new beta, and the current beta becoming the new stable. Language and standard library features marked unstable or hidden behind feature gates may only be used on the nightly channel. + +Anything marked stable will not change without a major version update with three exceptions: + +- Fixing compiler bugs +- Patching safety holes +- Changing type inference to require new annotations + +For details, read the Rust blog post ["Stability as a Deliverable."](http://blog.rust-lang.org/2014/10/30/Stability.html) + +#### Can I use unstable features in the beta or stable channel? + +No, you cannot. Rust works hard to provide strong guarantees about the stability of the APIs provided on the beta and stable channels. When something is unstable, it means that we can't provide those guarantees for it yet, and don't want people relying on it staying the same. This gives us the opportunity to try changes in the wild on the nightly channel, while still maintaining strong guarantees for people seeking stability. + +Things stabilize all the time, and the beta and stable channels update every six weeks. If you're waiting for a feature to be available without using the nightly channel, it should hopefully be available soon. + +#### What IDE should I use? + +There are a couple developing options: [RustDT](https://github.com/RustDT/RustDT) is a Rust plugin for Eclipse, while [SolidOak](https://github.com/oakes/SolidOak) is a from-scratch Rust IDE. Both are solid options for a Rust IDE. Rust also integrates well with a variety of text editors. Detailed information about both text editor and IDE support can be found at [areweideyet.com](http://areweideyet.com/). #### Why a dual MIT/ASL2 License? @@ -1026,12 +1020,9 @@ The Apache license includes important protection against patent aggression, but This is partly due to preference of the original developer (Graydon), and partly due to the fact that languages tend to have a wider audience and more diverse set of possible embeddings and end-uses than products such as web browsers. We'd like to appeal to as many of those potential contributors as possible. -### Naming - #### Why is the language called Rust? As [stated by Graydon Hoare](https://www.reddit.com/r/rust/comments/27jvdt/internet_archaeology_the_definitive_endall_source/), original developer of the Rust language, the name "Rust" comes from his personal interest in fungi, and because it evoked the feeling he was looking for in a programming language name. But truly, as Graydon himself put it: > <graydon> IOW I don't have a really good explanation. it seemed like a good name. (also a substring of "trust", "frustrating", "rustic" and ... "thrust"?)
> <graydon> I think I named it after fungi. rusts are amazing creatures. - From 57f72c57d290de64fb6b20913aeabd7b00fa4583 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Wed, 18 Nov 2015 18:07:52 -0500 Subject: [PATCH 15/41] Simplified CSS --- css/style.css | 138 ++++----------------------- faq.md | 260 +++++++++++++++++++++++++------------------------- 2 files changed, 146 insertions(+), 252 deletions(-) diff --git a/css/style.css b/css/style.css index f24379ef8..bfa665f92 100644 --- a/css/style.css +++ b/css/style.css @@ -385,20 +385,12 @@ ul.laundry-list { } .faq { - font-size: 16px; - line-height: 1.5em; border-top: 1px solid #dedede; - margin-top: 2rem; - margin-bottom: 8rem; - padding-top: 4rem; + margin-top: 2em; + margin-bottom: 8em; + padding-top: 4em; } - @media screen and (min-width: 820px) { - .faq { - padding-right: 4rem; - } - } - .faq p, .faq ul, .faq ol, @@ -409,63 +401,21 @@ ul.laundry-list { } @media screen and (min-width: 820px) { + .faq { + padding-right: 6em; + } + .faq p, .faq ul, .faq ol, .faq blockquote, - .faq pre { - margin-left: 6rem; - } - - .faq ul, - .faq ol { - padding: 0; - } - - .faq ul { - counter-reset: uli; - } - - .faq ul > li { - list-style: none; - position: relative; + .faq pre, + .faq h1, + #toc { + margin-left: 8rem; } - - .faq ul > li:before { - content: counter(uli); - counter-increment: uli; - color: #999; - position: absolute; - top: 0; - left: -1.5em; - width: 1em; - font-family: "Fira Sans"; - text-align: right; - } - - .faq ol { - counter-reset: oli; } - .faq ol > li { - list-style: none; - position: relative; - } - - .faq ol > li:before { - content: counter(oli); - counter-increment: oli; - color: #999; - position: absolute; - top: 0; - left: -1.5em; - width: 1em; - font-family: "Fira Sans"; - text-align: right; - } - - } - .faq blockquote { border-left: .25em solid #dedede; padding-left: 2rem; @@ -478,17 +428,12 @@ ul.laundry-list { .faq h1 { font-size: 2.5em; line-height: 1.5em; - margin: 0 0 1rem; + margin-top: 0; + margin-bottom: 1rem; font-weight: 400; position: relative; } - @media screen and (min-width: 820px) { - .faq h1 { - margin-left: 6rem; - } - } - .faq h2 { font-size: 2em; line-height: 1.5em; @@ -498,34 +443,13 @@ ul.laundry-list { padding-top: 1rem; } - .faq h2 a { - color: #333; - text-decoration: none; - } - .faq h3 { - font-size: 1.5em; - line-height: 1.3em; - font-weight: 500; - margin: 3rem 0 1rem; - } - - .faq h2 + h3 { - margin-top: 2rem; - } - - .faq h4 { font-size: 1em; line-height: 1.5em; font-weight: 500; margin: 2rem 0 .25rem; } - .faq li { - margin: 0; - padding: 0; - } - .faq pre { margin-top: 2rem; margin-bottom: 2rem; @@ -534,9 +458,10 @@ ul.laundry-list { .faq code { display: inline-block; padding: .1em .2em 0; - font-size: 0.9em; + font-size: 0.95em; line-height: 1em; background-color: #f7f7f7; + border-radius: 2px; font-weight: 400; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; } @@ -546,47 +471,16 @@ ul.laundry-list { line-height: 1.5em; } - .faq .copyright { - font-size: .8em; - color: #999; - border-top: 1px solid #dedede; - margin-top: 6rem; - padding-top: 2rem; - } - -#toc { - margin-top: 2rem; - padding: 2rem; - background-color: #f7f7f7; - border-radius: .25em; - border: 1px solid #ccc; -} - #toc h2 { - font-family: "Fira Sans"; border: 0; - margin: 0 -2rem 2rem; - padding: 0 2rem 1rem; font-size: 2rem; line-height: 1.5em; - border-bottom: 1px solid #ccc; } #toc ol { - counter-reset: tos; - margin: 0; + margin: 0 0 0 2rem; padding: 0; -webkit-columns: 150px 3; -moz-columns: 150px 3; columns: 150px 3; } - - #toc li { - margin-left: 1em; - } - - #toc li::before { - content: counter(tos); - counter-increment: tos; - } - diff --git a/faq.md b/faq.md index 81ff3fc4c..01e5cde08 100644 --- a/faq.md +++ b/faq.md @@ -39,75 +39,75 @@ If there is some common or important question you feel is wrongly left unanswere

Performance

-#### How fast is Rust? +### How fast is Rust? Fast! Rust is already competitive with idiomatic C and C++ in a number of benchmarks. It is an explicit goal of Rust to be at least as fast as C++. Language decisions are made with performance in mind, and given that Rust is built on LLVM, any LLVM performance improvements also help Rust. -#### Is Rust garbage collected? +### Is Rust garbage collected? No. A language that requires a GC is a language that opts into a larger, more complex runtime than Rust cares for. Rust is usable on bare metal with no extra runtime. Additionally, garbage collection is frequently a source of non-deterministic behavior. Rust provides the tools to make using a GC [possible and even pleasant](http://manishearth.github.io/blog/2015/09/01/designing-a-gc-in-rust/), but it is not part of the language as provided. -#### Why is my program slow? +### Why is my program slow? If you compiled with Cargo, did you use the `--release` flag? If you compiled with `rustc` directly, did you use the `-O` flag? Either of these will compile with optimizations turned on. The Rust languages uses a lot of optimizations to create efficient machine code, but you need to explicitly ask for them, as they also result in longer compilation times that may be undesirable during development. -#### Why is Rust compilation slow? +### Why is Rust compilation slow? Most of the compilation time is spent in type checking and code translation, with some time also used for safety checks. All of these are required for the strong guarantees Rust makes, but they require some time to run. Add in optimizations, and Rust's compilation is slower than a simpler language that doesn't provide Rust's guarantees. But all is not lost. The Rust compiler has evolved significantly over a number of years, and a lot of good work is being done to make it work faster, and to make it feel faster during development. -#### Why is Rust's HashMap so slow? +### Why is Rust's HashMap so slow? By default, Rust's `HashMap` uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges/blah/hash-rs/) in many cases, one case where it is notably slower than other hashing algorithms is with short keys, such as integers. This is why Rust programmers often observe slow performance with `HashMap`. The [FNV hasher](https://crates.io/crates/fnv) is frequently recommended for these cases, but be aware that it does not have the same collision-resistence properties as SipHash. -#### Why can't I run benchmarks? +### Why can't I run benchmarks? You can run benchmarks, but only on the nightly channel. Rust's benchmarking mechanism is currently unstable, as the API has not been deemed ready for stabilization. This may change in the future, but until then benchmarking can only be used on nightly. -#### Does Rust do tail-call optimization? +### Does Rust do tail-call optimization? In general, tail-call optimization is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html), but may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization). There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. The compiler is still free to optimize tail-calls [when it pleases](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), however, and the language has a word (`become`) reserved for future explicit tail calls. -#### Does Rust have a runtime? +### Does Rust have a runtime? Rust has a [very small and limited runtime](https://doc.rust-lang.org/std/rt/) providing a heap, backtraces, unwinding, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup.

Syntax

-#### Why curly braces? Why can't everything be like Haskell/Python? +### Why curly braces? Why can't everything be like Haskell/Python? Use of curly braces to denote blocks is a common design choice in a variety of programming languages, and Rust's consistency is useful for people already familiar with the style. Curly braces also allow for more flexible syntax for the programmer, a simpler parser in the compiler, and help reduce the possibility of logic mistakes caused by incorrect indentation, like Apple's [goto fail](https://gotofail.com/) bug. -#### I can leave out parentheses on `if` conditions, why do I have to put brackets around single line blocks? Why is the C style not allowed? +### I can leave out parentheses on `if` conditions, why do I have to put brackets around single line blocks? Why is the C style not allowed? Rust does not require parentheses around the conditional for `if`, `else if`, and the like. If C-style bracketless blocks were allowed, there would be no clear delineation between the condition and the body of the block. Requiring braces also eliminates the dangling-else problem, where nested if-else expressions can be to ambiguous. -#### Why is there no literal syntax for dictionaries? +### Why is there no literal syntax for dictionaries? There are two data types in the Rust standard library that fit the definition of a "dictionary": `BTreeMap` and `HashMap`, but they have different performance characteristics, and it's not clear which one should be the default for any potential dictionary literal syntax. Rust prefers to make performance costs explicit, and any selection of a default from these two choices may lead to performance surprises that undermine this intention. If you want a more convenient syntax for `BTreeMap` or `HashMap` creation, you can [create a macro](http://stackoverflow.com/questions/27562739/how-do-i-create-a-hashmap-literal/27582993#27582993) to provide it. -#### When should I use an implicit return? +### When should I use an implicit return? Implicit returns are simply a coding style option, and can be used anywhere they make sense. While early returns require an explicit `return`, any other return can be made implicit according to your preferences or the preferences of your project. -#### Why aren't function signatures inferred? +### Why aren't function signatures inferred? - Mechanically, it simplifies the inference algorithm, as inference only requires looking at one function at a time. - Mandatory function signatures help enforce interface stability at both the module and crate level. - It improves code comprehension for programmer, eliminating the need for an IDE running an inference algorithm across an entire crate to be able to guess at a function's argument types; it's always explicit and nearby. -#### Why does `match` have to be exhaustive? +### Why does `match` have to be exhaustive? `match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to an `enum` in the future will cause a compilation failure, rather than an error at runtime. Second, it makes cost explicit. In general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched, though it could fall through if the type of the `match` expression is `()`. This sort of hidden cost and special casing is against the language's philosophy. It is easy to ignore all unspecified cases by using the `_` wildcard: @@ -120,7 +120,7 @@ match val.do_something() {

Numerics

-#### Should I default to using `f32` or `f64`? +### Should I default to using `f32` or `f64`? The choice of which to use is dependent on the focus of the program. @@ -128,25 +128,25 @@ If you're interested in the greatest degree of precision with your floating poin All things being equal, `f64` is likely a better default. -#### Why can't I compare floats? +### Why can't I compare floats? You can! Floats implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) there is no total ordering for floating point numbers. There [is a crate](https://crates.io/crates/ordered-float) that provides a total ordering on floats by wrapping them, which may be desirable depending on your use-case. You can still do all of the normal comparison operations you would expect, but you can't use the `cmp` function. -#### Why can't I use `f32` or `f64` as `HashMap` keys? +### Why can't I use `f32` or `f64` as `HashMap` keys? In order to be used as a key in a `HashMap`, a type must implement the `Eq` and `Hash` traits. `f32` and `f64` implement `PartialEq`, but not `Eq`, because both types include `NaN` (stands for "not a number"). `NaN` values are [not equal to any float, and are not equal to each other](https://en.wikipedia.org/wiki/NaN). This means that `f32` and `f64` can't be used as keys in a HashMap. -#### How can I convert between numeric types? +### How can I convert between numeric types? There are three ways: the `as` keyword, which does simple casting for primitive types, the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types), and `transmute`, which is an unsafe function that tells the compiler to treat the bits of one type as those of another type.

Strings

-#### How can I convert a `String` or `Vec` to a slice (`&str` and `&[T]`)? +### How can I convert a `String` or `Vec` to a slice (`&str` and `&[T]`)? Using Deref coercions, `Strings` and `Vec`s will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. -#### How can I convert from `&str` to `String` or the other way around? +### How can I convert from `&str` to `String` or the other way around? `String`s are automatically converted into `&str` when you take a reference of them. For example, the following code works: @@ -174,7 +174,7 @@ fn main() { } ``` -#### How do I split a `String` into lines? +### How do I split a `String` into lines? The [`lines()`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.lines) function for `String`s provides an iterator over the lines of a string, which can then be `collect()`ed into a container of lines like so: @@ -183,17 +183,17 @@ let s = "This\nis\na\ntest"; let v: Vec<&str> = s.lines().collect(); ``` -#### What are the differences between the different string types? +### What are the differences between the different string types? `String` is an owned string type, while `&str` is a string slice. For a more detailed explanation, [check out the Rust book](https://doc.rust-lang.org/stable/book/strings.html). -#### How do I do O(1) character access in a `String`? +### How do I do O(1) character access in a `String`? Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a "code unit" (In UTF-16, code units 2 bytes instead. In UTF-32 they are 4 bytes). "Code points" are composed of one or more code units, and combine in "grapheme clusters" which most closely approximate characters. Thus, even though you may index on bytes in a UTF-8 string, you can't access the `i`th code point or grapheme cluster in constant time. However, if you know at which byte that desired code point or grapheme cluster begins, then you _can_ access it in constant time. Functions including `str::find()` and regex matches return byte indices, facilitating this sort of access. -#### Why are strings UTF-8 by default? +### Why are strings UTF-8 by default? The `str` type is UTF-8 because we observe more text in the wild in this encoding – particularly in network transmissions, which are endian-agnostic – and we think it's best that the default treatment of I/O not involve having to recode codepoints in each direction. @@ -209,7 +209,7 @@ For a more in-depth explanation of why UTF-8 is usually preferable over UTF-16 o

Collections

-#### Can I implement data structures like vectors and linked lists efficiently in Rust? +### Can I implement data structures like vectors and linked lists efficiently in Rust? If your reason for implementing these data structures is to use them for other programs, there's no need, as efficient implementations of these data structures are provided by the standard library. @@ -217,11 +217,11 @@ If, however, your reason is simply to learn, then you will likely need to dip in For example, a doubly-linked list requires that there be two mutable references to each node, but this violates Rust's mutable reference aliasing rules. You can solve this using `Weak`, but the performance will be poorer than you likely want. -#### How can I join a `Vec` (or an array) of strings into a single string? +### How can I join a `Vec` (or an array) of strings into a single string? You can do this using the [`join()`](http://doc.rust-lang.org/std/slice/trait.SliceConcatExt.html#tymethod.join) and [`concat()`](http://doc.rust-lang.org/std/slice/trait.SliceConcatExt.html#tymethod.concat) iterator methods. These allow the concatenation of items being iterated over, with `join()` inserting a separator of your choosing. -#### How can I iterate over a `Vec` without moving/consuming it? +### How can I iterate over a `Vec` without moving/consuming it? The easiest way is by using `Vec`'s `IntoIterator` implementation, like so: @@ -235,7 +235,7 @@ println!("\nLength: {}", v.len()); The way Rust `for` loops work, they actually call `into_iter()` (which is defined in the `IntoIterator` trait) for whatever you are trying to iterate over. `IntoIterator` is implemented for `&'a Vec` and `&'a mut Vec`, meaning you can iterate over a vector without consuming it just be using `&v` or `&mut v` (for some vector `v`). -#### Why do I need to type the array size in the array declaration? +### Why do I need to type the array size in the array declaration? You don't necessarily have to. If you're declaring an array directly, the size is inferred based on the number of elements. But if you're declaring a function that takes an array, the compiler has to know how big that array will be. @@ -243,7 +243,7 @@ One thing to note is that currently Rust doesn't offer generics over arrays of d

Ownership

-#### How can I implement a graph or other data structure that contains cycles? +### How can I implement a graph or other data structure that contains cycles? There are three major options: @@ -253,7 +253,7 @@ although this approach pays the cost of memory management. more efficient, but bypasses Rust's safety guarantees. - Using vectors and indices into those vectors. There are [several](http://smallcultfollowing.com/babysteps/blog/2015/04/06/modeling-graphs-in-rust-using-vector-indices/) [available](http://featherweightmusings.blogspot.com/2015/04/graphs-in-rust.html) examples and explanations of this approach. -#### How can I define a struct that contains a pointer to one of its own fields? +### How can I define a struct that contains a pointer to one of its own fields? It's possible, but useless to do so. The struct becomes permanently borrowed by itself and therefore can't be moved. Here is some code illustrating this: @@ -275,29 +275,29 @@ fn main() { } ``` -#### What does it mean to "consume a value"? +### What does it mean to "consume a value"? "Consuming a value" means taking ownership of a value. When this is done, the value can't be used elsewhere. -#### What is the difference between consuming and moving/taking ownership? +### What is the difference between consuming and moving/taking ownership? These are different terms for the same thing. In both cases, it means the value has been moved into a function, and moved out of the calling owner. -#### Why can I use integers after passing them to a function, but not structs? +### Why can I use integers after passing them to a function, but not structs? If a type implements the `Copy` trait, then it will be copied when passed to a function. All numeric types in Rust implement `Copy`, but struct types do not implement `Copy` by default, so they are moved instead. This means that the struct can no longer be used elsewhere, unless it is moved back out of the function via the return. -#### How do you deal with a "Use of moved value" error? +### How do you deal with a "Use of moved value" error? This error means that the value you're trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary. If it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. It may also be possible to implement `Copy` (for implicit copying, rather than moving) or `Clone` (explicit copying) for the type in question. If none of these are possible, you may want to return ownership of the value when the function is done, thus eliminating this error. -#### What are the rules for using `self`, `&self`, or `&mut self` in a method declaration? +### What are the rules for using `self`, `&self`, or `&mut self` in a method declaration? - Use `self` when a function needs to consume the type - Use `&self` when a function only needs a reference to the type - Use `&mut self` when a function needs to mutate the type without consuming it -#### How can I understand the borrow checker? +### How can I understand the borrow checker? There is a certain desire to act as if the borrow checker is some mysterious zen master, doling out knocks on the head whenever its koans are misunderstood. The reality is a little different. In fact, the borrow checker is simply applying a couple simple rules, which can be found in the Rust book's [section on borrowing](https://doc.rust-lang.org/stable/book/references-and-borrowing.html#the-rules): @@ -308,7 +308,7 @@ There is a certain desire to act as if the borrow checker is some mysterious zen Understanding these rules and [lifetimes](https://doc.rust-lang.org/stable/book/lifetimes.html) is all you need to do to understand the borrow checker. -#### How do deref coercions work? +### How do deref coercions work? [Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait, which looks like this: @@ -325,19 +325,19 @@ You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/s

Lifetimes

-#### Why lifetimes? +### Why lifetimes? Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety without mechanisms like garbage collection which carry hefty performance costs. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). -#### Why is the lifetime syntax the way it is? +### Why is the lifetime syntax the way it is? The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticable, and fit nicely in a type declaration right alonside traits and references. Alternative syntaxes have been discussed, but this seems to work just fine. -#### When is `Rc` useful? +### When is `Rc` useful? This is covered in the [official documentation for `Rc`](https://doc.rust-lang.org/stable/std/rc/), Rust's non-atomically reference-counted pointer type. In short, `Rc` and its thread-safe cousin `Arc` are useful to express shared ownership of an immutable value, and have the system automatically deallocate the associated memory when no one has access to it. -#### How do I return a borrow to something I created from a function? +### How do I return a borrow to something I created from a function? You need to ensure that the borrowed item will outlive the function. This can be done in two ways: by binding the output lifetime to some input lifetime, or by declaring the output lifetime as static. The first option is significantly better than the second. @@ -361,11 +361,11 @@ An alternative is to return an owning type like `String`. This eliminates the re There is also the `Cow` ("copy on write") type, which will only do the extra allocation if you attempt to mutate the contained value. -#### How do I return a closure from a function? +### How do I return a closure from a function? To return a closure from a function, it must be a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own copy of the captured variables, independent of its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer valid (put another way, it would allow reading potentially invalid memory). The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). -#### When are lifetimes required to be defined? +### When are lifetimes required to be defined? Lifetimes can often be elided, as explained in the ["Lifetime elision" section](https://doc.rust-lang.org/book/lifetimes.html#lifetime-elision) of the Rust book. "Elided lifetimes" are those lifetimes which are implicit in any code containing references. They are automatically inserted by the compiler with the three following rules: @@ -375,25 +375,25 @@ Lifetimes can often be elided, as explained in the ["Lifetime elision" section]( If these rules would result in incorrect code elsewhere, then the Rust compiler will provide errors, and you will need to define the relevant lifetimes to correct that error. -#### How can Rust guarantee "no null pointers"? +### How can Rust guarantee "no null pointers"? Data values in the language can only be constructed through a fixed set of initializer forms. Each of those forms requires that its inputs already be initialized. A liveness analysis ensures that local variables are initialized before use.

Generics

-#### What is "monomorphisation"? +### What is "monomorphisation"? Monomorphisation is the process by which Rust generates specific instances of a generic function based on the types of the various calls to that function. This is used to provide static dispatch for generic functions. For functions using trait objects for generics, dynamic dispatch is used instead, with calls to the function going through a vtable to identify specific function calls for the provided type implementing the given trait. In C++ people would likely know this as "template instantiation." But unlike C++, Rust's monomorphisation is an implementation detail, and not a language feature. -#### What's the difference between a function and a closure that doesn't capture any variables? +### What's the difference between a function and a closure that doesn't capture any variables? Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the the struct can be called as a function. The big difference between these traits is how they take the `self` parameter. `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. -#### What are higher-kinded types, why would I want them, and why doesn't Rust have them? +### What are higher-kinded types, why would I want them, and why doesn't Rust have them? Let's go through these one by one: @@ -413,11 +413,11 @@ Finally, Rust doesn't currently have them simply because they haven't been a pri (Credit to anasaziwochi for his [useful explanation](https://www.reddit.com/r/rust/comments/2av5tv/why_does_rust_not_have_a_functor_trait/ciz6iwm) of higher-kinded types in Rust.) -#### What do named type parameters in generic types mean? +### What do named type parameters in generic types mean? These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a simple `where` clause. In essence, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. -#### Does Rust have type reflection? +### Does Rust have type reflection? Rust does have limited type reflection through the `Reflect` and `Any` traits. `Reflect` is a marker trait (meaning it has no functions associated with it) that indicates a function expects a type which can be reflected over. It is implemented for all types. `Any` is automatically implemented for any type that is both `Reflect` and `'static`, and is used for basic dynamic typing, as in the following example, which implements a map indexed on the type of the mapped-to value: @@ -454,7 +454,7 @@ fn main() { } ``` -#### Can I override operators? Which ones and how? +### Can I override operators? Which ones and how? You can provide custom implementations for a variety of operators using their associated traits: `Add` for `+`, `Mult` for `*`. It looks like this: @@ -491,13 +491,13 @@ The following operators can be overloaded: | `[]` | `Index` | | `mut []` | `IndexMut` | -#### Why the split between `Eq`/`PartialEq` and `Ord`/`PartialOrd`? +### Why the split between `Eq`/`PartialEq` and `Ord`/`PartialOrd`? There are some types in Rust that have a partial ordering, or partial equality, but no total ordering or total equality. The floating point types `f32` and `f64` are examples of this. Because a floating point value may be `NaN`, and because `NaN`s aren't equal to any other floating point type, nor less than or greater to any other floating point type, nor equal to each other, these types _can't_ implement `Eq` and `Ord`, although they _can_ implement `PartialEq` and `PartialOrd`.

Input / Output

-#### How do I read a file into a `String`? +### How do I read a file into a `String`? Using the `read_to_string()` method, which is defined on the `Read` trait in `std::io`. @@ -517,13 +517,13 @@ fn main() { } ``` -#### How do I read file input efficiently? +### How do I read file input efficiently? The [`File` type](https://doc.rust-lang.org/stable/std/fs/struct.File.html) implements the `Read` trait, which has a variety of functions for reading and writing data, including `read()`, `read_to_end()`, `bytes()`, `chars()`, and `take()`. Each of these functions reads in a certain amount of input from a given file. `read()` reads as much input as the underlying system will provide in a single call. `read_to_end()` reads the entire buffer into a vector, allocating as much space as is needed. `bytes()` and `chars()` allow you to iterate over the bytes and characters of the file, respectively. Finally, `take()` allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need. For buffered reads, use the [`BufReader`](http://doc.rust-lang.org/stable/std/io/struct.BufReader.html) struct, which helps to reduce the number of system calls when reading. -#### How do I get command line arguments in Rust? +### How do I get command line arguments in Rust? The easiest way is to use `std::env::Args`, which provides an iterator over the input arguments. @@ -531,65 +531,65 @@ If you're looking for something more powerful, there are a [number of options on

Error Handling

-#### Why doesn't Rust have exceptions? +### Why doesn't Rust have exceptions? Exceptions complicate understanding of control-flow, they express validity/invalidity outside of the type system, and they interoperate poorly with multithreaded code (a major focus of Rust). Rust prefers a type-based approach to error handling, which is [covered at length in the book](https://doc.rust-lang.org/stable/book/error-handling.html). This fits more nicely with Rust's control flow, concurrency, and everything else. -#### What's the deal with `unwrap()` everywhere? +### What's the deal with `unwrap()` everywhere? `unwrap()` is a function that extracts the value inside an `Option` or `Result` and panics if no value is present. It is useful in the presence of truly unrecoverable errors, but is more useful for quick prototypes where you don't want to handle an error yet, or blog posts where error handling would distract from the main point. `unwrap()` shouldn't be your default way to handle errors, but it is a useful tool to have. -#### Why do I get an error when I try to run example code that uses the `try!` macro? +### Why do I get an error when I try to run example code that uses the `try!` macro? It's probably an issue with the function's return type. The [`try!` macro](https://doc.rust-lang.org/stable/std/macro.try!.html) either extracts the value from a `Result`, or returns early with the error `Result` is carrying. This means that `try` only works for functions that return `Result` themselves, where the `Err`-constructed type implements `From::from(err)`. -#### Is there an easier way to do error handling than having `Result`s everywhere? +### Is there an easier way to do error handling than having `Result`s everywhere? If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you want. `Result` is an indicator that some computation may or may not complete successfully. The fact that some languages allow you to ignore failure cases is an anti-feature. Forcing you to handle them is one of the ways that Rust encourages safety. So, if you really don't want to handle an error, use `unwrap()`, but you should probably just handle the error for real.

Concurrency

-#### Can I use globals across threads without `unsafe`? +### Can I use globals across threads without `unsafe`? Yes, if the type implements `Sync`, doesn't implement `Drop`, and you don't try to mutate the global value.

Macros

-#### Can I write a macro to generate identifiers? +### Can I write a macro to generate identifiers? Not currently. Rust macros are so-called hygienic macros, not the unlimited compile-time syntax editing you see in C. Macro invocations can only appear in places where they are explicitly supported: items, methods declarations, statements, expressions, and patterns. Here, "method declarations" means a blank space where a method can be put. They can't be used to complete a partial method declaration. By the same logic, they can't be used to complete a partial variable declaration.

Debugging

-#### How do I debug Rust programs? +### How do I debug Rust programs? Rust programs can be debugged using gdb or lldb, same as C and C++. In fact, every Rust installation comes with rust-gdb and rust-lldb, wrappers over gdb and lldb with Rust pretty-printing enabled. -#### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? +### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? This error is usually caused by `unwrap()`ing a `None` or `Err`. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build` is also helpful). Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful.

Low-Level

-#### How do I `memcpy` bytes? +### How do I `memcpy` bytes? To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapping bytes, use `std::ptr::cpy_nonoverlapping`. Both of these functions are `unsafe`, as both can be used to subvert the language's safety guarantees. Use caution when using them. -#### Can Rust reasonably function without the standard library? +### Can Rust reasonably function without the standard library? Absolutely. Rust programs can be set to not load the standard library using the `#![no_std]` attribute. With this attribute set, you can continue to use the Rust core, which is nothing but the platform-agnostic primitives. As such, it doesn't include IO, concurrency, heap allocation, etc. Note however that `libcore` has not been stabilized. -#### Can I write an operating system in Rust? +### Can I write an operating system in Rust? Yes! In fact there are several projects underway doing just that, including [reenix](https://github.com/scialex/reenix), [RustOS](https://github.com/ryanra/RustOS), and [redox](http://www.redox-os.org/). -#### How can I read or write numeric types like `i32` or `f64` in big-endian or little-endian format in a file or other byte stream? +### How can I read or write numeric types like `i32` or `f64` in big-endian or little-endian format in a file or other byte stream? You should check out the [byteorder crate](http://burntsushi.net/rustdoc/byteorder/), which provides utilities for exactly that. -#### Does Rust specify data layout? +### Does Rust specify data layout? No. In the general case, `enum` and `struct` layout is undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested `enum`s, reordering fields to remove padding, etc. `enums` which carry no data ("C-like") are eligible to have a defined representation. Such `enums` are easily distinguished in that they are simply a list of names that carry no data: @@ -607,36 +607,36 @@ The `repr` attribute can be applied to such `enums` to give them the same repres

Cross-Platform

-#### What's the idiomatic way to express platform-specific behavior in Rust? +### What's the idiomatic way to express platform-specific behavior in Rust? Platform-specific behavior can be expressed using [conditional compilation attributes](https://doc.rust-lang.org/reference.html#conditional-compilation) such as `target_os`, `target_family`, `target_endian`, etc. -#### Can Rust be used for Android/iOS programming? +### Can Rust be used for Android/iOS programming? Yes it can! There are already examples of using Rust for both [Android](https://github.com/tomaka/android-rs-glue) and [iOS](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/). It does require a bit of work to set up, but Rust functions fine on both platforms. -#### Can I run my Rust program in a web browser? +### Can I run my Rust program in a web browser? There [are efforts](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/) to make Rust run in the web browser using Emscripten. Given that Rust is implemented on top of LLVM, this should be possible, but Rust currently runs on a special patched version of LLVM, and so it is tougher than it would otherwise be. This will likely improve over time. -#### How do I cross-compile in Rust? +### How do I cross-compile in Rust? Cross compilation is possible in Rust, but it requires [a bit of work](https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md) to set up. Rust does distribute [copies of the standard library](http://static.rust-lang.org/dist/) for each of the supported platforms, which are contained in the `rust-std-*` files for each of the build directories found on the distribution page.

Modules and Crates

-#### What is the relationship between a module and a crate? +### What is the relationship between a module and a crate? - A crate is a top-level compilation unit that corresponds to a single loadable object. - A module is a (possibly nested) unit of name-management inside a crate. @@ -646,13 +646,13 @@ Cross compilation is possible in Rust, but it requires [a bit of work](https://g - There is no global inter-crate namespace; all name management occurs within a crate. - Using another crate binds the root of its namespace into the user's namespace. -#### Why can't the Rust compiler find this library I'm `use`ing? +### Why can't the Rust compiler find this library I'm `use`ing? There are a number of possible answers, but a common mistake is not realizing that `use` declarations are _always_ relative to the crate root. Try rewriting your declarations to use the paths they would use if defined in the root file of your project and see if that fixes the problem. There are also `self` and `super`, which disambiguate `use` paths as being relative to the current module or parent module, respectively. -#### Why do I have to declare module files with mod at the top level of the crate, instead of just `use`ing them? +### Why do I have to declare module files with mod at the top level of the crate, instead of just `use`ing them? There are two ways to declare modules in Rust, inline or in another file. Here is an example of each: @@ -687,15 +687,15 @@ In the first example, the module is defined in the same file it's used. In the s A `use`ing declaration just tells the compiler to bring everything from a particular module into the current module. Without a `mod` declaration first, the compiler doesn't know if the `use`d module exists, and so can't import its contents into the current module. -#### How do I configure Cargo to use a proxy? +### How do I configure Cargo to use a proxy? As explained on the Cargo [configuration documentation](http://doc.crates.io/config.html), you can set Cargo to use a proxy by setting the "proxy" variable under `[http]` in the configuration file. -#### Why can't the compiler find the method implementation even through I'm already `use`ing the crate? +### Why can't the compiler find the method implementation even through I'm already `use`ing the crate? For methods defined on a trait, you have to explicitly import the trait declaration. This means it's not enough to import a module where a struct implements the trait, you must also import the trait itself. -#### Why can't the compiler infer `use` declarations for me? +### Why can't the compiler infer `use` declarations for me? It probably could, but you also don't want it to. While in many cases it is likely that the compiler could determine the correct module to import by simply looking for where a given identifier is defined, this may not be the case in general. Any decision rule in `rustc` for choosing between competing options would likely cause surprise and confusion, and not solve much of a problem. @@ -715,16 +715,16 @@ fn main() { If you know this is going to happen, perhaps it saves a small number of keystrokes, but it also greatly increases the possibility for surprising error messages when you actually meant for `baz()` to be `bar::baz()`, and it decreases the readability of the code by making the meaning of a function call dependent on module declaration. These are not tradeoffs we are willing to make. -#### How do I do dynamic Rust library loading? +### How do I do dynamic Rust library loading? Importing dynamic libraries in Rust can be with [libloading](https://crates.io/crates/libloading), which provides a cross-platform system for dynamic linking. -#### Why doesn't [http://crates.io](http://crates.io) have namespaces? +### Why doesn't [http://crates.io](http://crates.io) have namespaces? Quoting the [official explanation](https://internals.rust-lang.org/t/crates-io-package-policies/1041) of [http://crates.io](http://crates.io)'s design: @@ -738,7 +738,7 @@ Quoting the [official explanation](https://internals.rust-lang.org/t/crates-io-p > > Because namespaces are strictly more complicated in a number of ways,and because they can be added compatibly in the future should they become necessary, we're going to stick with a single shared namespace. -#### Why are so many Rust answers on StackOverflow wrong? +### Why are so many Rust answers on StackOverflow wrong? The Rust language has been around for a number of years, and only reached version 1.0 in May of 2015. In the time before then the language changed significantly, and a number of StackOverflow answers were given at the time of older versions of the language. @@ -746,61 +746,61 @@ Over time more and more answers will be offered for the current version, this im

Libraries

-#### How can I make an HTTP request? +### How can I make an HTTP request? [Hyper](https://github.com/hyperium/hyper) is the most popular, but there are [a number of others as well](https://crates.io/keywords/http). -#### How can I write a GUI application in Rust? +### How can I write a GUI application in Rust? There are a variety of ways to write GUI applications in Rust. Just check out [this list of GUI frameworks](https://github.com/kud1ing/awesome-rust#gui). -#### How can I parse JSON/XML? +### How can I parse JSON/XML? [Serde](https://github.com/serde-rs/serde) is the recommended library for serialization and deserialization of Rust data to and from a number of different formats. -#### Is there a standard 2D+ dimensional vector and shape crate? +### Is there a standard 2D+ dimensional vector and shape crate? Not yet! Want to write one? -#### How do I write an OpenGL app in Rust? +### How do I write an OpenGL app in Rust? [Glium](https://github.com/tomaka/glium) is the major library for OpenGL programming in Rust. [GLFW](https://github.com/bjz/glfw-rs) is also a solid option. -#### Can I write a video game in Rust? +### Can I write a video game in Rust? Yes you can! The major game programming library for Rust is [Piston](http://www.piston.rs/), and there's both a [subreddit for game programming in Rust](https://www.reddit.com/r/rust_gamedev/) and an IRC channel (`#rust-gamedev` on [Mozilla IRC](https://wiki.mozilla.org/IRC)) as well.

Design Patterns

-#### Is Rust object oriented? +### Is Rust object oriented? It is multi-paradigm. Not everything is shoe-horned into a single abstraction. Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you're accustomed to. -#### How do I handle configuration of a struct with optional parameters? +### How do I handle configuration of a struct with optional parameters? The easiest way is to use the `Option` type in whatever function you're using to construct instances of the struct (usually `new()`). Another way is to use the builder pattern, where only certain functions instantiating member variables must be called before the construction of the built type. -#### How do I do global variables in Rust? +### How do I do global variables in Rust? Globals in Rust can be done using `const` declarations for compile-time computed global constants, while `static` can be used for mutable globals. Note that modifying a `static` variable requires the use of `unsafe`, as it allows for data races, one of the things guaranteed not to happen in safe Rust. You can also use the `RefCell` and `Option` type to provide interior mutability of an optional global value. It is important to note that `RefCell`s are not thread-safe. -#### How can I set compile-time constants that are defined procedurally? +### How can I set compile-time constants that are defined procedurally? Rust currently has limited support for compile time constants. You can define primitives using `const` declarations (similar to `static`, but immutable) as well as define `const` functions and inherent methods. To define procedural constants that can't be defined via these mechanisms, use the [`lazy-static`](https://github.com/rust-lang-nursery/lazy-static.rs) crate, which emulates compile-time evaluation by automatically evaluating the constant at first use. -#### Can I run initialization code that happens before main? +### Can I run initialization code that happens before main? Rust has no cross-platform concept of "life before `main`". The closest you'll see can be done through the [`lazy_static`](https://github.com/Kimundi/lazy-static.rs) crate, which simulates a "before main" by lazily initializing static variables at their first usage. -#### How do I map object-oriented concepts to Rust? +### How do I map object-oriented concepts to Rust? That depends. There _are_ ways of translating object-oriented concepts like [multiple inheritance](https://www.reddit.com/r/rust/comments/2sryuw/ideaquestion_about_multiple_inheritence/) to Rust, but as Rust is not object-oriented the result of the translation may look substantially different from its appearance in an OO language. -#### Why doesn't Rust have inheritance? +### Why doesn't Rust have inheritance? There are two meanings for the word "inheritance": _subtyping_, and _interface sharing_. Both purposes are already handled by traits. @@ -810,7 +810,7 @@ For the second, interface sharing is handled via trait methods, which define a c Rust has consistently worked to avoid having features with overlapping purposes, preferring to keep features orthogonal. For this reason, and given that the two major purposes are already handled by traits, Rust has opted not to include inheritance. -#### Does Rust allow non-constant-expression values for globals? +### Does Rust allow non-constant-expression values for globals? No. Globals can not have a non-constant-expression constructor and cannot have a destructor at all. This is an opinion of the language. Static constructors are undesirable because they can slow down program startup. Life before main is often considered a misfeature, never to be used. Rust helps this along by just not having the feature. @@ -820,39 +820,39 @@ However, `thread_local!` variables (which are restricted to a single thread) are

Other Languages

-#### How can I implement something like `struct X { static int X; };` in Rust? +### How can I implement something like `struct X { static int X; };` in Rust? Rust does not have `static` fields as shown in the code snippet above. Instead, you can declare a `static` variable in a given module, which is kept private to that module. -#### How can I convert a C-style enum to an integer, or vice-versa? +### How can I convert a C-style enum to an integer, or vice-versa? Converting a C-style enum to an integer to an integer can be done with a simple `as` expression, like `e as i64` (where `e` is some enum). Converting in the other direction is a little tougher, as Rust can't statically ensure that the conversion is valid. As such, it requires `unsafe` via `mem::transmute()`. -#### Why does Rust not have an ABI like C does, and why do I have to annotate things with extern? +### Why does Rust not have an ABI like C does, and why do I have to annotate things with extern? Committing to an ABI is a big thing, and can limit potentially advantageous language changes in the future. Given that Rust only hit 1.0 in May of 2015, it is still too early to make a commitment as big as a stable ABI. This does not mean that one won't happen in the future, though. -#### Can Rust code call C code? +### Can Rust code call C code? Yes. Calling C code from Rust is simple and exactly as efficient as calling C code from C. -#### Can C code call Rust code? +### Can C code call Rust code? Yes. The Rust code has to be exposed via an `extern` declaration, which makes it C-ABI compatible. Such a function can be passed to C code as a function pointer or, if given the `#[no_mangle]` attribute to disable symbol mangling, can be called directly from C code. -#### I already write perfect C++. What does Rust give me? +### I already write perfect C++. What does Rust give me? Modern C++ has made a lot of strides to being a safe and comfortable programming language, but it's not perfect, and it's still very easy to do things unsafely. This is something the C++ core developers are working to overcome, but C++ is limited by a long history that predates a lot of the ideas they are now trying to implement. Rust was designed from day one to be a safe systems programming language, which means it's not limited by historic design decisions that make getting safety right in C++ so complicated. In C++, safety is achieved by careful personal discipline, and is very easy to get wrong. In Rust, safety is the default. -#### How do I do the equivalent of C++ template specialization in Rust? +### How do I do the equivalent of C++ template specialization in Rust? Rust doesn't currently have an equivalent to template specialization, but it is [being worked on](https://github.com/rust-lang/rfcs/pull/1210) and will hopefully be added soon. -#### How does Rust's ownership system related to move semantics in C++? +### How does Rust's ownership system related to move semantics in C++? In C++, moving vs copying was added on late with C++11. With Rust the concept of moving vs copying has been around from the beginning. In C++ something can be moved into a function or out of a function using r-value references and either `std::move` or `std::forward`. In Rust, moves happen for anything that does not implement the `Copy` trait (which will cause the value of the type to be copied, rather than moved). This means that moves are the default operation, and that copies must be opted into explicitly. It's also important to know that moves in Rust leave the moved-out variable as uninitialized memory. This is is contrast to C++, where moves must leave behind a value, resulting the use of dummy values in things like `std::thread`. @@ -866,11 +866,11 @@ fn must_copy(t: T) { } ``` -#### How can I interoperate with C++ from Rust, or with Rust from C++? +### How can I interoperate with C++ from Rust, or with Rust from C++? The simplest way is to interoperate through C. Both Rust and C++ provide a [foreign function interface](https://doc.rust-lang.org/book/ffi.html) for C, and can use that to communicate between each other. If writing C bindings is too tedious, you can always use [rust-bindgen](https://github.com/crabtw/rust-bindgen) to help automatically generate workable C bindings. -#### Does Rust have C++-style constructors? +### Does Rust have C++-style constructors? No. Functions can serve the same purpose as constructors without adding any language complexity. The usual name for the constructor-equivalent function in Rust is `new()`, although this is just a social norm rather than a language rule. The `new()` function in fact is just like any other function. An example of it looks like so: @@ -892,19 +892,19 @@ impl Foo { } ``` -#### Does Rust have copy constructors? +### Does Rust have copy constructors? Not exactly. Types which implement `Copy` will do a standard C-like "shallow copy" with no extra work (similar to "plain old data" in C++). It is impossible to implement `Copy` types that require custom copy behavior. Instead, in Rust "copy constructors" are created by implementing the `Clone` trait, and explicitly calling the `clone` method. Making user-defined copy operators explicit surfaces the underlying complexity, forcing the developer to opt-in to potentially expensive operations. -#### Does Rust have move constructors? +### Does Rust have move constructors? No. Values of all types are moved via `memcpy`. This makes writing generic unsafe code much simpler since assignment, passing and returning are known to never have a side effect like unwinding. -#### Why does Rust not have the ? and ! like in Swift? +### Why does Rust not have the ? and ! like in Swift? In Swift, `?` is used to indicate an optional value. This is already done by `Option` in Rust, and so `?` is not needed. Similarly, `!` is used to "unwrap" an optional value in Swift, which is done by the `unwrap()` function in Rust. In both cases, Rust opted for slightly longer names which more clearly indicate intent. Also, in Rust the `!` symbol already indicates logical negation and macro calls, and does not need a third meaning. -#### How are Go and Rust similar, and how are they different? +### How are Go and Rust similar, and how are they different? Rust and Go have substantially different design goals, and so differ substantially. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones: @@ -915,27 +915,27 @@ Rust and Go have substantially different design goals, and so differ substantial Rust is probably not the best choice in every situation. If you're considering using either Rust or Go for a project it's probably best to try out both languages a bit and make an informed decision rather than base your decision on a small comparison of the two. -#### `gofmt` is great. Where's `rustfmt`? +### `gofmt` is great. Where's `rustfmt`? `rustfmt` is [right here](https://github.com/nrc/rustfmt/), and is being actively developed to make reading Rust code as easy and predictable as possible. -#### How do Rust traits compare to Haskell typeclasses? +### How do Rust traits compare to Haskell typeclasses? Rust traits are similar to Haskell typeclasses, but are currently not as powerful. Rust traits cannot express functional dependencies or type families, nor does Rust have full support for higher-kinded types. Some of these may be added in the future, but are not provided currently.

Documentation

-#### Where do I report issues in the Rust documentation? +### Where do I report issues in the Rust documentation? You can report issues in the Rust documentation on the Rust compiler [issue tracker](https://github.com/rust-lang/rust/issues). Make sure to read the [contributing guidelines](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md) first. -#### How do I view rustdoc documentation for a library my project depends on? +### How do I view rustdoc documentation for a library my project depends on? When you use `cargo doc` to generate documentation for your own project, it also generates docs for the active dependency versions. These are put into the `target/doc` directory of your project. Use `cargo doc --open` to open the docs after building them, or just open up `target/doc/index.html` yourself after building the docs.

Project

-#### What is this project's goal? +### What is this project's goal? To design and implement a safe, concurrent, practical, static systems language. @@ -947,11 +947,11 @@ Rust exists because other languages at this level of abstraction and efficiency Rust exists as alternative language that provides both efficient code and a comfortable level of abstraction, while improving on all three of these points. -#### Is this project controlled by Mozilla? +### Is this project controlled by Mozilla? No. Rust started as Graydon Hoare's part-time side project in 2006 and remained so for over 3 years. Mozilla got involved in 2009 once the language was mature enough to run basic tests and demonstrate its core concepts. Though it remains sponsored by Mozilla, Rust is developed by a diverse community of enthusiasts from many different places around the world. The [Rust Team](https://www.rust-lang.org/team.html) is composed of both Mozilla and non-Mozilla members. -#### What are explicit non-goals of Rust? +### What are explicit non-goals of Rust? 1. To employ any particularly cutting-edge technologies. Old, established techniques are better. 2. To prize expressiveness, minimalism or elegance above other goals. These are desirable but subordinate goals. @@ -959,25 +959,25 @@ No. Rust started as Graydon Hoare's part-time side project in 2006 and remained 4. To be 100% static, 100% safe, 100% reflective, or too dogmatic in any other sense. Trade-offs exist. 5. To run on "every possible platform". It must eventually work without unnecessary compromises on widely-used hardware and software platforms. -#### In which projects is Mozilla using Rust? +### In which projects is Mozilla using Rust? The main project is [Servo](https://github.com/servo/servo), an experimental browser engine Mozilla is working on. They are also working to integrate Rust components into Firefox. -#### What examples are there of large Rust projects? +### What examples are there of large Rust projects? The two biggest open source Rust projects right now are [Servo](https://github.com/servo/servo) and the [Rust compiler](https://github.com/rust-lang/rust) itself. -#### How can I try Rust easily? +### How can I try Rust easily? The easiest way to try Rust is through the [Playground](https://play.rust-lang.org/), an online app for writing and running Rust code. If you want to try it on your system, [install it](https://www.rust-lang.org/install.html) and go through the ["Learn Rust"](https://doc.rust-lang.org/stable/book/learn-rust.html) section of the book. -#### How do I get help with Rust issues? +### How do I get help with Rust issues? There are several ways. You can: @@ -986,11 +986,11 @@ There are several ways. You can: - Ask on [StackOverflow](http://stackoverflow.com/questions/tagged/rust) with the "rust" tag - Post in [/r/rust](https://www.reddit.com/r/rust), the official Rust subreddit -#### Why has Rust changed so much over time? +### Why has Rust changed so much over time? Rust started with a goal of creating a safe but usable systems programming language. In pursuit of this goal it explored a lot of ideas, some of which it kept (lifetimes, traits) while others were discarded (the typestate system). Also, in the run up to 1.0 a lot of the standard library was rewritten. Some of this was out of a desire to improve the old versions of the APIs. Some of it was out of a desire for improved Windows support. -#### How does Rust language versioning work? +### How does Rust language versioning work? Rust maintains three "channels": stable, beta, and nightly. Stable and beta are updated every six weeks, with the current nightly becoming the new beta, and the current beta becoming the new stable. Language and standard library features marked unstable or hidden behind feature gates may only be used on the nightly channel. @@ -1002,25 +1002,25 @@ Anything marked stable will not change without a major version update with three For details, read the Rust blog post ["Stability as a Deliverable."](http://blog.rust-lang.org/2014/10/30/Stability.html) -#### Can I use unstable features in the beta or stable channel? +### Can I use unstable features in the beta or stable channel? No, you cannot. Rust works hard to provide strong guarantees about the stability of the APIs provided on the beta and stable channels. When something is unstable, it means that we can't provide those guarantees for it yet, and don't want people relying on it staying the same. This gives us the opportunity to try changes in the wild on the nightly channel, while still maintaining strong guarantees for people seeking stability. Things stabilize all the time, and the beta and stable channels update every six weeks. If you're waiting for a feature to be available without using the nightly channel, it should hopefully be available soon. -#### What IDE should I use? +### What IDE should I use? There are a couple developing options: [RustDT](https://github.com/RustDT/RustDT) is a Rust plugin for Eclipse, while [SolidOak](https://github.com/oakes/SolidOak) is a from-scratch Rust IDE. Both are solid options for a Rust IDE. Rust also integrates well with a variety of text editors. Detailed information about both text editor and IDE support can be found at [areweideyet.com](http://areweideyet.com/). -#### Why a dual MIT/ASL2 License? +### Why a dual MIT/ASL2 License? The Apache license includes important protection against patent aggression, but it is not compatible with the GPL, version 2. To avoid problems using Rust with GPL2, it is alternately MIT licensed. -#### Why a BSD-style permissive license rather than MPL or tri-license? +### Why a BSD-style permissive license rather than MPL or tri-license? This is partly due to preference of the original developer (Graydon), and partly due to the fact that languages tend to have a wider audience and more diverse set of possible embeddings and end-uses than products such as web browsers. We'd like to appeal to as many of those potential contributors as possible. -#### Why is the language called Rust? +### Why is the language called Rust? As [stated by Graydon Hoare](https://www.reddit.com/r/rust/comments/27jvdt/internet_archaeology_the_definitive_endall_source/), original developer of the Rust language, the name "Rust" comes from his personal interest in fungi, and because it evoked the feeling he was looking for in a programming language name. But truly, as Graydon himself put it: From d718d7cb8921697828606f8e31049e35e43d697d Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Fri, 20 Nov 2015 18:49:16 -0500 Subject: [PATCH 16/41] Updating answers --- faq.md | 65 +++++++++++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/faq.md b/faq.md index 01e5cde08..43cf1e0fd 100644 --- a/faq.md +++ b/faq.md @@ -41,27 +41,29 @@ If there is some common or important question you feel is wrongly left unanswere ### How fast is Rust? -Fast! Rust is already competitive with idiomatic C and C++ in a number of benchmarks. +Fast! Rust is already competitive with idiomatic C and C++ in a number of benchmarks (like the [Benchmarks Game](http://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=rust&lang2=gpp) and [others](https://github.com/kostya/benchmarks)). -It is an explicit goal of Rust to be at least as fast as C++. Language decisions are made with performance in mind, and given that Rust is built on LLVM, any LLVM performance improvements also help Rust. +It is an explicit goal of Rust to be at least as fast as C++. Language decisions are made with performance in mind, and given that Rust is built on LLVM and strives to resemble Clang from LLVM's perspective, any LLVM performance improvements also help Rust. ### Is Rust garbage collected? No. A language that requires a GC is a language that opts into a larger, more complex runtime than Rust cares for. Rust is usable on bare metal with no extra runtime. -Additionally, garbage collection is frequently a source of non-deterministic behavior. Rust provides the tools to make using a GC [possible and even pleasant](http://manishearth.github.io/blog/2015/09/01/designing-a-gc-in-rust/), but it is not part of the language as provided. +Additionally, garbage collection is frequently a source of non-deterministic behavior. Rust provides the tools to make using third-party garbage collectors [possible](http://manishearth.github.io/blog/2015/09/01/designing-a-gc-in-rust/), but it is not part of the language as provided. ### Why is my program slow? -If you compiled with Cargo, did you use the `--release` flag? If you compiled with `rustc` directly, did you use the `-O` flag? Either of these will compile with optimizations turned on. The Rust languages uses a lot of optimizations to create efficient machine code, but you need to explicitly ask for them, as they also result in longer compilation times that may be undesirable during development. +The Rust compiler doesn't compile with optimizations unless asked to, as optimizations slow down compilation and are usually undesirable during development. + +If you compile with `cargo`, use the `--release` flag. If you compile with `rustc` directly, use the `-O` flag. Either of these will turn on optimizations. ### Why is Rust compilation slow? -Most of the compilation time is spent in type checking and code translation, with some time also used for safety checks. All of these are required for the strong guarantees Rust makes, but they require some time to run. Add in optimizations, and Rust's compilation is slower than a simpler language that doesn't provide Rust's guarantees. +Code translation and optimizations. Rust provides a number of high level interfaces that compile down into efficient machine code, and those translations take some time to run. -But all is not lost. The Rust compiler has evolved significantly over a number of years, and a lot of good work is being done to make it work faster, and to make it feel faster during development. +But all is not lost. The Rust compiler has evolved significantly over a number of years, and a lot of good work is being done to [make it work faster](https://github.com/rust-lang/rfcs/pull/1211), and to make it feel faster during development. -### Why is Rust's HashMap so slow? +### What hashing algorithm does Rust's `HashMap` use? By default, Rust's `HashMap` uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). @@ -69,15 +71,15 @@ While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges ### Why can't I run benchmarks? -You can run benchmarks, but only on the nightly channel. Rust's benchmarking mechanism is currently unstable, as the API has not been deemed ready for stabilization. This may change in the future, but until then benchmarking can only be used on nightly. +You can run benchmarks, but only on the nightly channel. Rust's benchmarking mechanism is currently unstable, as the API has not been deemed ready for stabilization. This [may change in the future](https://github.com/rust-lang/rust/issues/29553), but until then benchmarking can only be used on nightly. ### Does Rust do tail-call optimization? -In general, tail-call optimization is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html), but may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization). There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. The compiler is still free to optimize tail-calls [when it pleases](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), however, and the language has a word (`become`) reserved for future explicit tail calls. +In general, tail-call optimization is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html), but may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization). There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. The compiler is still free to optimize tail-calls [when it pleases](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), however, and the language has a keyword (`become`) reserved for future explicit tail calls. ### Does Rust have a runtime? -Rust has a [very small and limited runtime](https://doc.rust-lang.org/std/rt/) providing a heap, backtraces, unwinding, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup. +Just like C, Rust has a [very small and limited runtime](https://doc.rust-lang.org/std/rt/) providing a heap, backtraces, unwinding, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup.

Syntax

@@ -89,7 +91,7 @@ Curly braces also allow for more flexible syntax for the programmer, a simpler p ### I can leave out parentheses on `if` conditions, why do I have to put brackets around single line blocks? Why is the C style not allowed? -Rust does not require parentheses around the conditional for `if`, `else if`, and the like. If C-style bracketless blocks were allowed, there would be no clear delineation between the condition and the body of the block. Requiring braces also eliminates the dangling-else problem, where nested if-else expressions can be to ambiguous. +Whereas C requires mandatory parantheses for `if`-statements but leave brackets optional, Rust makes the opposite choice. Rust's `if`-expressions thus require strictly fewer delimiters than their C counterparts. Furthermore, the optional brackets on C's `if`-statements are well-understood as a hazard to maintenance and refactoring. ### Why is there no literal syntax for dictionaries? @@ -120,11 +122,11 @@ match val.do_something() {

Numerics

-### Should I default to using `f32` or `f64`? +### Which of `f32` and `f64` should I prefer to floating-point math? The choice of which to use is dependent on the focus of the program. -If you're interested in the greatest degree of precision with your floating point numbers, then `f64` is the preferred choice. If you're more interested in keeping the size of the value small, then `f32` is better. +If you're interested in the greatest degree of precision with your floating point numbers, then `f64` is the preferred choice. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated innacuracy of having fewer bits per value, then `f32` is better. All things being equal, `f64` is likely a better default. @@ -134,17 +136,17 @@ You can! Floats implement the `PartialOrd` trait, which means that `>`, `<`, `<= ### Why can't I use `f32` or `f64` as `HashMap` keys? -In order to be used as a key in a `HashMap`, a type must implement the `Eq` and `Hash` traits. `f32` and `f64` implement `PartialEq`, but not `Eq`, because both types include `NaN` (stands for "not a number"). `NaN` values are [not equal to any float, and are not equal to each other](https://en.wikipedia.org/wiki/NaN). This means that `f32` and `f64` can't be used as keys in a HashMap. +In order to be used as a key in a `HashMap`, a type must implement the `Eq` and `Hash` traits. `f32` and `f64` implement `PartialEq`, but not `Eq`, because one of the potential values for floating-point types is `NaN` (or "not a number"). `NaN` values are [not equal to any float, and are not equal to each other](https://en.wikipedia.org/wiki/NaN). This means that `f32` and `f64` can't be used as keys in a HashMap. ### How can I convert between numeric types? -There are three ways: the `as` keyword, which does simple casting for primitive types, the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types), and `transmute`, which is an unsafe function that tells the compiler to treat the bits of one type as those of another type. +There are two ways: the `as` keyword, which does simple casting for primitive types, and the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types).

Strings

### How can I convert a `String` or `Vec` to a slice (`&str` and `&[T]`)? -Using Deref coercions, `Strings` and `Vec`s will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. +Using [Deref coercions](https://doc.rust-lang.org/stable/book/deref-coercions.html), `Strings` and `Vec`s will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. ### How can I convert from `&str` to `String` or the other way around? @@ -161,7 +163,7 @@ fn main() { } ``` -The `to_owned()` is how you convert from a `&str` into a `String`. This is necessary because string literals in Rust are of type `&str`. In this particular example, making `s` into a `String` isn't actually necessary, and the code could be rewritten as: +The `to_owned()` method is how you convert from a `&str` into a `String`. This is necessary because string literals in Rust are of type `&str`. In this particular example, making `s` into a `String` isn't actually necessary, and the code could be rewritten as: ```rust fn say_hello(name: &str) { @@ -174,18 +176,9 @@ fn main() { } ``` -### How do I split a `String` into lines? - -The [`lines()`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.lines) function for `String`s provides an iterator over the lines of a string, which can then be `collect()`ed into a container of lines like so: - -```rust -let s = "This\nis\na\ntest"; -let v: Vec<&str> = s.lines().collect(); -``` +### What are the differences between the two different string types? -### What are the differences between the different string types? - -`String` is an owned string type, while `&str` is a string slice. For a more detailed explanation, [check out the Rust book](https://doc.rust-lang.org/stable/book/strings.html). +`String` is a buffer of UTF-8 bytes allocated on the heap, while `&str` is a "view" into a `String` allocated elsewhere. ### How do I do O(1) character access in a `String`? @@ -213,17 +206,13 @@ For a more in-depth explanation of why UTF-8 is usually preferable over UTF-16 o If your reason for implementing these data structures is to use them for other programs, there's no need, as efficient implementations of these data structures are provided by the standard library. -If, however, your reason is simply to learn, then you will likely need to dip into unsafe code. While these data structures _can_ be implemented entirely in safe Rust, the performance is likely to be worse than they would be with the use of unsafe code. The simple reason for this is that data structures like vectors and link lists rely on pointer and memory operations that are disallowed by safe Rust. +If, however, [your reason is simply to learn](http://cglab.ca/~abeinges/blah/too-many-lists/book/), then you will likely need to dip into unsafe code. While these data structures _can_ be implemented entirely in safe Rust, the performance is likely to be worse than they would be with the use of unsafe code. The simple reason for this is that data structures like vectors and link lists rely on pointer and memory operations that are disallowed by safe Rust. For example, a doubly-linked list requires that there be two mutable references to each node, but this violates Rust's mutable reference aliasing rules. You can solve this using `Weak`, but the performance will be poorer than you likely want. -### How can I join a `Vec` (or an array) of strings into a single string? - -You can do this using the [`join()`](http://doc.rust-lang.org/std/slice/trait.SliceConcatExt.html#tymethod.join) and [`concat()`](http://doc.rust-lang.org/std/slice/trait.SliceConcatExt.html#tymethod.concat) iterator methods. These allow the concatenation of items being iterated over, with `join()` inserting a separator of your choosing. +### How can I iterate over a collection without moving/consuming it? -### How can I iterate over a `Vec` without moving/consuming it? - -The easiest way is by using `Vec`'s `IntoIterator` implementation, like so: +The easiest way is by using the collection's `IntoIterator` implementation. Here is an example for `Vec`: ```rust let v = vec![1,2,3,4,5]; @@ -233,7 +222,7 @@ for item in &v { println!("\nLength: {}", v.len()); ``` -The way Rust `for` loops work, they actually call `into_iter()` (which is defined in the `IntoIterator` trait) for whatever you are trying to iterate over. `IntoIterator` is implemented for `&'a Vec` and `&'a mut Vec`, meaning you can iterate over a vector without consuming it just be using `&v` or `&mut v` (for some vector `v`). +The way Rust `for` loops work, they actually call `into_iter()` (which is defined in the `IntoIterator` trait) for whatever you are trying to iterate over. `IntoIterator` is implemented for `&Vec` and `&Vec`, meaning you can iterate over a vector without consuming it just be using `&v` or `&mut v` (for some vector `v`). The same is true for the other standard collections as well. ### Why do I need to type the array size in the array declaration? @@ -281,10 +270,12 @@ fn main() { ### What is the difference between consuming and moving/taking ownership? -These are different terms for the same thing. In both cases, it means the value has been moved into a function, and moved out of the calling owner. +These are different terms for the same thing. In both cases, it means the value has been moved to another owner, and moved out of the calling owner. ### Why can I use integers after passing them to a function, but not structs? +### Why can values of some types be used after passing them to a function, while reuse of values of other types results in an error? + If a type implements the `Copy` trait, then it will be copied when passed to a function. All numeric types in Rust implement `Copy`, but struct types do not implement `Copy` by default, so they are moved instead. This means that the struct can no longer be used elsewhere, unless it is moved back out of the function via the return. ### How do you deal with a "Use of moved value" error? From 57f62acde7ce4a81d9dedc8794e12a81634d78e2 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Tue, 15 Dec 2015 21:10:36 -0500 Subject: [PATCH 17/41] Addressed latest round of feedback --- faq.md | 209 ++++++++++++++++++++------------------------------------- 1 file changed, 74 insertions(+), 135 deletions(-) diff --git a/faq.md b/faq.md index 43cf1e0fd..c00cdc199 100644 --- a/faq.md +++ b/faq.md @@ -97,7 +97,7 @@ Whereas C requires mandatory parantheses for `if`-statements but leave brackets There are two data types in the Rust standard library that fit the definition of a "dictionary": `BTreeMap` and `HashMap`, but they have different performance characteristics, and it's not clear which one should be the default for any potential dictionary literal syntax. Rust prefers to make performance costs explicit, and any selection of a default from these two choices may lead to performance surprises that undermine this intention. -If you want a more convenient syntax for `BTreeMap` or `HashMap` creation, you can [create a macro](http://stackoverflow.com/questions/27562739/how-do-i-create-a-hashmap-literal/27582993#27582993) to provide it. +If you want a more convenient syntax for `BTreeMap` or `HashMap` creation, you can [create a macro](http://stackoverflow.com/questions/27582739/how-do-i-create-a-hashmap-literal) to provide it. ### When should I use an implicit return? @@ -285,12 +285,12 @@ This error means that the value you're trying to use has been moved to a new own ### What are the rules for using `self`, `&self`, or `&mut self` in a method declaration? - Use `self` when a function needs to consume the type -- Use `&self` when a function only needs a reference to the type +- Use `&self` when a function only needs a read-only reference to the type - Use `&mut self` when a function needs to mutate the type without consuming it ### How can I understand the borrow checker? -There is a certain desire to act as if the borrow checker is some mysterious zen master, doling out knocks on the head whenever its koans are misunderstood. The reality is a little different. In fact, the borrow checker is simply applying a couple simple rules, which can be found in the Rust book's [section on borrowing](https://doc.rust-lang.org/stable/book/references-and-borrowing.html#the-rules): +There is a certain desire to act as if the borrow checker is some mysterious zen master, doling out knocks on the head whenever its koans are misunderstood. The reality is a little different. In fact, the borrow checker applies only a few straightforward rules, which can be found in the Rust book's [section on borrowing](https://doc.rust-lang.org/stable/book/references-and-borrowing.html#the-rules): > First, any borrow must last for a scope no greater than that of the owner. Second, you may have one or the other of these two kinds of borrows, but not both at the same time: > @@ -301,14 +301,7 @@ Understanding these rules and [lifetimes](https://doc.rust-lang.org/stable/book/ ### How do deref coercions work? -[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait, which looks like this: - -```rust -pub trait Deref { - type Target: ?Sized; - fn deref(&'a self) -> &'a Self::Target; -} -``` +[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait. A Deref implementation indicates that the implementing type may be converted into `Target` by a call to the `deref` function, which takes an immutable reference of a certain lifetime to the calling struct, and returns a reference of the same lifetime to the target. @@ -318,11 +311,11 @@ You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/s ### Why lifetimes? -Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety without mechanisms like garbage collection which carry hefty performance costs. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). +Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety without mechanisms like garbage collection, which can have undesirable implications for performance. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). ### Why is the lifetime syntax the way it is? -The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticable, and fit nicely in a type declaration right alonside traits and references. Alternative syntaxes have been discussed, but this seems to work just fine. +The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticeable, and fit nicely in a type declaration right alonside traits and references. Alternative syntaxes have been discussed, but this seems to work just fine. ### When is `Rc` useful? @@ -330,27 +323,7 @@ This is covered in the [official documentation for `Rc`](https://doc.rust-lang.o ### How do I return a borrow to something I created from a function? -You need to ensure that the borrowed item will outlive the function. This can be done in two ways: by binding the output lifetime to some input lifetime, or by declaring the output lifetime as static. The first option is significantly better than the second. - -Here is an example of each: - -```rust -// The first method -fn example1<'a>(s: &'a str) -> &'a str { - // Do something... -} - -// The second method -fn example2<'a>(s: &'a str) -> &'static str { - // Do something else... -} -``` - -The problem with declaring the lifetime as `static` is that it's rarely what you actually mean, and is instead a way of escaping the lifetime system. References with a `static` lifetime outlive everything else, and this means that they can be used in ways that would otherwise be invalid with the first method. - -An alternative is to return an owning type like `String`. This eliminates the reference issues entirely, at the cost of possibly unnecessary allocations. - -There is also the `Cow` ("copy on write") type, which will only do the extra allocation if you attempt to mutate the contained value. +You need to ensure that the borrowed item will outlive the function. This can be done by binding the output lifetime to some input lifetime. An alternative is to return an owning type like `String`. This eliminates the reference issues entirely, at the cost of possibly unnecessary allocations. There is also the `Cow` ("copy on write") type, which will only do the extra allocation if you attempt to mutate the contained value. ### How do I return a closure from a function? @@ -368,15 +341,17 @@ If these rules would result in incorrect code elsewhere, then the Rust compiler ### How can Rust guarantee "no null pointers"? -Data values in the language can only be constructed through a fixed set of initializer forms. Each of those forms requires that its inputs already be initialized. A liveness analysis ensures that local variables are initialized before use. +The only way to construct a value of type `&Foo` or `&mut Foo` is to specify an existing value of type `Foo` that the reference points to. In this way Rust makes sure no null references are introduced. -

Generics

+### How do I express the absence of a value without `null`? + +You can do that with the `Option` type, which can either be `Some(T)` or `None`. `Some(T)` indicates that a value of type `T` is contained within, while `None` indicates the absence of a value. -### What is "monomorphisation"? +

Generics

-Monomorphisation is the process by which Rust generates specific instances of a generic function based on the types of the various calls to that function. This is used to provide static dispatch for generic functions. For functions using trait objects for generics, dynamic dispatch is used instead, with calls to the function going through a vtable to identify specific function calls for the provided type implementing the given trait. +### What is "monomorphization"? -In C++ people would likely know this as "template instantiation." But unlike C++, Rust's monomorphisation is an implementation detail, and not a language feature. +Monomorphisation is the process by which Rust generates specific instances of a generic function based on the parameter types of calls to that function. This is used to provide static dispatch for generic functions. For functions using trait objects for polymorphism, dynamic dispatch is used instead, with calls to the function monomorphized at runtime based on the particular type implementing the boxed trait. ### What's the difference between a function and a closure that doesn't capture any variables? @@ -384,6 +359,8 @@ Functions are a built-in primitive of the language, while closures are essential The big difference between these traits is how they take the `self` parameter. `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. +In the end, functions and closures are operationally equivalent, but have different runtime representations due to their different implementations (as a language primitive and a syntactic sugar over traits, respectively). + ### What are higher-kinded types, why would I want them, and why doesn't Rust have them? Let's go through these one by one: @@ -398,56 +375,19 @@ trait Functor { } ``` -The part that Rust currently can't do is that `Self` above is a type constructor parameterized by another type constructor. This is what support for higher-kinded types lets you express. +The part that Rust currently can't do is that `Self` above is a type constructor parameterized by another type constructor. This is what support for higher-kinded types would let you express. Finally, Rust doesn't currently have them simply because they haven't been a priority. There is nothing inherent to the language that stops us from implementing higher-kinded types, it just hasn't been done yet. There is an open RFC for implementing them, but no real proposal exists yet. If one comes around, it will definitely be considered. (Credit to anasaziwochi for his [useful explanation](https://www.reddit.com/r/rust/comments/2av5tv/why_does_rust_not_have_a_functor_trait/ciz6iwm) of higher-kinded types in Rust.) -### What do named type parameters in generic types mean? +### What do named type parameters like `` in generic types mean? These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a simple `where` clause. In essence, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. -### Does Rust have type reflection? - -Rust does have limited type reflection through the `Reflect` and `Any` traits. `Reflect` is a marker trait (meaning it has no functions associated with it) that indicates a function expects a type which can be reflected over. It is implemented for all types. `Any` is automatically implemented for any type that is both `Reflect` and `'static`, and is used for basic dynamic typing, as in the following example, which implements a map indexed on the type of the mapped-to value: - -```rust -use std::any::{Any, TypeId}; -use std::collections::HashMap; - -type Entry = Box; - -#[derive(Debug)] -struct AnyMap(HashMap); - -impl AnyMap { - fn new() -> Self { - AnyMap(HashMap::new()) - } - - fn insert(&mut self, val: T) -> Option{ - self.0.insert(TypeId::of::(), Box::new(val) as Entry) - } - - fn get(&self) -> Option<&T> { - self.0.get(&TypeId::of::()).unwrap().downcast_ref() - } -} - -fn main() { - let mut map = AnyMap::new(); - map.insert(123i32); - map.insert(456i64); - - println!("{:?}", map); - println!("{:?}", map.get::()); -} -``` - ### Can I override operators? Which ones and how? -You can provide custom implementations for a variety of operators using their associated traits: `Add` for `+`, `Mult` for `*`. It looks like this: +You can provide custom implementations for a variety of operators using their associated traits: `Add` for `+`, `Mul` for `*`. It looks like this: ```rust struct Foo; @@ -484,7 +424,7 @@ The following operators can be overloaded: ### Why the split between `Eq`/`PartialEq` and `Ord`/`PartialOrd`? -There are some types in Rust that have a partial ordering, or partial equality, but no total ordering or total equality. The floating point types `f32` and `f64` are examples of this. Because a floating point value may be `NaN`, and because `NaN`s aren't equal to any other floating point type, nor less than or greater to any other floating point type, nor equal to each other, these types _can't_ implement `Eq` and `Ord`, although they _can_ implement `PartialEq` and `PartialOrd`. +There are some types in Rust whose values are only partially ordered, or have only partial equality. This means that there are values which are not less than or greater than each other, or values which are not equal to themselves, respectively. The floating point types `f32` and `f64` are examples of this. Because a floating point value may be `NaN`, and because `NaN`s aren't equal to any other floating point type, nor less than or greater to any other floating point type, nor equal to each other, these types _can't_ implement `Eq` and `Ord`, although they _can_ implement `PartialEq` and `PartialOrd`.

Input / Output

@@ -534,17 +474,17 @@ Rust prefers a type-based approach to error handling, which is [covered at lengt ### Why do I get an error when I try to run example code that uses the `try!` macro? -It's probably an issue with the function's return type. The [`try!` macro](https://doc.rust-lang.org/stable/std/macro.try!.html) either extracts the value from a `Result`, or returns early with the error `Result` is carrying. This means that `try` only works for functions that return `Result` themselves, where the `Err`-constructed type implements `From::from(err)`. +It's probably an issue with the function's return type. The [`try!` macro](https://doc.rust-lang.org/stable/std/macro.try!.html) either extracts the value from a `Result`, or returns early with the error `Result` is carrying. This means that `try` only works for functions that return `Result` themselves, where the `Err`-constructed type implements `From::from(err)`. In particular, this means that the `try!` macro cannot work inside the `main` function. ### Is there an easier way to do error handling than having `Result`s everywhere? -If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you want. `Result` is an indicator that some computation may or may not complete successfully. The fact that some languages allow you to ignore failure cases is an anti-feature. Forcing you to handle them is one of the ways that Rust encourages safety. So, if you really don't want to handle an error, use `unwrap()`, but you should probably just handle the error for real. +If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you want. `Result` is an indicator that some computation may or may not complete successfully. Requiring you to handle them is one of the ways that Rust encourages safety. If you really don't want to handle an error, use `unwrap()`, but know that doing so means that the given code will cause the entire process to panic on failure, which is usually undesirable.

Concurrency

-### Can I use globals across threads without `unsafe`? +### Can I use static values across threads without an `unsafe` block? -Yes, if the type implements `Sync`, doesn't implement `Drop`, and you don't try to mutate the global value. +Yes, if the type implements `Sync`, doesn't implement `Drop`, and you don't try to mutate the value.

Macros

@@ -560,12 +500,14 @@ Rust programs can be debugged using gdb or lldb, same as C and C++. In fact, eve ### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? -This error is usually caused by `unwrap()`ing a `None` or `Err`. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build` is also helpful). Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful. +This error is usually caused by `unwrap()`ing a `None` or `Err` in client code. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build` is also helpful). Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful.

Low-Level

### How do I `memcpy` bytes? +If you want to clone an existing slice safely, you can use `std::slice::clone_from_slice`. This function is currently unstable, but [should be stabilized soon](https://internals.rust-lang.org/t/stabilizing-basic-functions-on-arrays-and-slices/2868). + To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapping bytes, use `std::ptr::cpy_nonoverlapping`. Both of these functions are `unsafe`, as both can be used to subvert the language's safety guarantees. Use caution when using them. ### Can Rust reasonably function without the standard library? @@ -580,9 +522,9 @@ Yes! In fact there are several projects underway doing just that, including [ree You should check out the [byteorder crate](http://burntsushi.net/rustdoc/byteorder/), which provides utilities for exactly that. -### Does Rust specify data layout? +### Does Rust guarantee a specific data layout? -No. In the general case, `enum` and `struct` layout is undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested `enum`s, reordering fields to remove padding, etc. `enums` which carry no data ("C-like") are eligible to have a defined representation. Such `enums` are easily distinguished in that they are simply a list of names that carry no data: +Not by default. In the general case, `enum` and `struct` layout is undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested `enum`s, reordering fields to remove padding, etc. `enums` which carry no data ("C-like") are eligible to have a defined representation. Such `enums` are easily distinguished in that they are simply a list of names that carry no data: ```rust enum CLike { @@ -593,7 +535,7 @@ enum CLike { } ``` -The `repr` attribute can be applied to such `enums` to give them the same representation as a primitive. This allows using Rust `enum`s in FFI where C `enum`s are also used, for most use cases. The attribute can also be applied to `struct`s to get the same layout as a C `struct` would. +The `repr` attribute can be applied to such `enums` to give them the same representation they would have in equivalent C code. This allows using Rust `enum`s in FFI code where C `enum`s are also used, for most use cases. The attribute can also be applied to `struct`s to get the same layout as a C `struct` would.

Cross-Platform

@@ -629,7 +571,7 @@ Cross compilation is possible in Rust, but it requires [a bit of work](https://g ### What is the relationship between a module and a crate? -- A crate is a top-level compilation unit that corresponds to a single loadable object. +- A crate is a compilation unit, which is the smallest amount of code that the Rust compiler can operate on. - A module is a (possibly nested) unit of name-management inside a crate. - A crate contains an implicit, un-named top-level module. - Recursive definitions can span modules, but not crates. @@ -639,10 +581,12 @@ Cross compilation is possible in Rust, but it requires [a bit of work](https://g ### Why can't the Rust compiler find this library I'm `use`ing? -There are a number of possible answers, but a common mistake is not realizing that `use` declarations are _always_ relative to the crate root. Try rewriting your declarations to use the paths they would use if defined in the root file of your project and see if that fixes the problem. +There are a number of possible answers, but a common mistake is not realizing that `use` declarations are relative to the crate root. Try rewriting your declarations to use the paths they would use if defined in the root file of your project and see if that fixes the problem. There are also `self` and `super`, which disambiguate `use` paths as being relative to the current module or parent module, respectively. +For complete information on `use`ing libraries, read the Rust book's chapter ["Crates and Modules"](https://doc.rust-lang.org/stable/book/crates-and-modules.html). + ### Why do I have to declare module files with mod at the top level of the crate, instead of just `use`ing them? There are two ways to declare modules in Rust, inline or in another file. Here is an example of each: @@ -769,17 +713,17 @@ It is multi-paradigm. Not everything is shoe-horned into a single abstraction. M ### How do I handle configuration of a struct with optional parameters? -The easiest way is to use the `Option` type in whatever function you're using to construct instances of the struct (usually `new()`). Another way is to use the builder pattern, where only certain functions instantiating member variables must be called before the construction of the built type. +The easiest way is to use the `Option` type in whatever function you're using to construct instances of the struct (usually `new()`). Another way is to use the [builder pattern](https://aturon.github.io/ownership/builders.html), where only certain functions instantiating member variables must be called before the construction of the built type. ### How do I do global variables in Rust? -Globals in Rust can be done using `const` declarations for compile-time computed global constants, while `static` can be used for mutable globals. Note that modifying a `static` variable requires the use of `unsafe`, as it allows for data races, one of the things guaranteed not to happen in safe Rust. +Globals in Rust can be done using `const` declarations for compile-time computed global constants, while `static` can be used for mutable globals. Note that modifying a `static` variable requires the use of `unsafe`, as it allows for data races, one of the things guaranteed not to happen in safe Rust. One important distinction between `const` and `static` values is that you can take references to `static` values, but not references to `const` values, which don't have a specified memory location. For more information on `const` vs. `static`, read [the Rust book](https://doc.rust-lang.org/book/const-and-static.html). You can also use the `RefCell` and `Option` type to provide interior mutability of an optional global value. It is important to note that `RefCell`s are not thread-safe. ### How can I set compile-time constants that are defined procedurally? -Rust currently has limited support for compile time constants. You can define primitives using `const` declarations (similar to `static`, but immutable) as well as define `const` functions and inherent methods. +Rust currently has limited support for compile time constants. You can define primitives using `const` declarations (similar to `static`, but immutable and without a specified location in memory) as well as define `const` functions and inherent methods. To define procedural constants that can't be defined via these mechanisms, use the [`lazy-static`](https://github.com/rust-lang-nursery/lazy-static.rs) crate, which emulates compile-time evaluation by automatically evaluating the constant at first use. @@ -803,7 +747,7 @@ Rust has consistently worked to avoid having features with overlapping purposes, ### Does Rust allow non-constant-expression values for globals? -No. Globals can not have a non-constant-expression constructor and cannot have a destructor at all. This is an opinion of the language. Static constructors are undesirable because they can slow down program startup. Life before main is often considered a misfeature, never to be used. Rust helps this along by just not having the feature. +No. Globals can not have a non-constant-expression constructor and cannot have a destructor at all. This is an opinion of the language. Static constructors are undesirable because portably ensuring a static initialization order is difficult. Life before main is often considered a misfeature, never to be used. Rust helps this along by just not having the feature. See the [C++ FQA](http://yosefk.com/c++fqa/ctors.html#fqa-10.12) about the "static initialization order fiasco", and [Eric Lippert's blog](http://ericlippert.com/2013/02/06/static-constructors-part-one/) for the challenges in C#, which also has this feature. @@ -811,15 +755,15 @@ However, `thread_local!` variables (which are restricted to a single thread) are

Other Languages

-### How can I implement something like `struct X { static int X; };` in Rust? +### How can I implement something like C's `struct X { static int X; };` in Rust? Rust does not have `static` fields as shown in the code snippet above. Instead, you can declare a `static` variable in a given module, which is kept private to that module. ### How can I convert a C-style enum to an integer, or vice-versa? -Converting a C-style enum to an integer to an integer can be done with a simple `as` expression, like `e as i64` (where `e` is some enum). +Converting a C-style enum to an integer can be done with a simple `as` expression, like `e as i64` (where `e` is some enum). -Converting in the other direction is a little tougher, as Rust can't statically ensure that the conversion is valid. As such, it requires `unsafe` via `mem::transmute()`. +Converting in the other direction can be done with a `match` statement, which maps different numeric values to different potential values for the enum. ### Why does Rust not have an ABI like C does, and why do I have to annotate things with extern? @@ -841,21 +785,15 @@ Rust was designed from day one to be a safe systems programming language, which ### How do I do the equivalent of C++ template specialization in Rust? -Rust doesn't currently have an equivalent to template specialization, but it is [being worked on](https://github.com/rust-lang/rfcs/pull/1210) and will hopefully be added soon. +Rust doesn't currently have an exact equivalent to template specialization, but it is [being worked on](https://github.com/rust-lang/rfcs/pull/1210) and will hopefully be added soon. However, similar effects can be achieved via [associated types](https://doc.rust-lang.org/stable/book/associated-types.html). ### How does Rust's ownership system related to move semantics in C++? -In C++, moving vs copying was added on late with C++11. With Rust the concept of moving vs copying has been around from the beginning. In C++ something can be moved into a function or out of a function using r-value references and either `std::move` or `std::forward`. In Rust, moves happen for anything that does not implement the `Copy` trait (which will cause the value of the type to be copied, rather than moved). This means that moves are the default operation, and that copies must be opted into explicitly. It's also important to know that moves in Rust leave the moved-out variable as uninitialized memory. This is is contrast to C++, where moves must leave behind a value, resulting the use of dummy values in things like `std::thread`. - -Moves are often not necessary or desirable in Rust. If the function you're writing does not require ownership of the value being passed in, it should probably be borrowed (mutably or immutably, as necessary) rather than moved or copied. +The notions of a "move" in Rust and a "move" in C++ are quite different, owing to the different systems in which they exist. -It's also useful to note that functions can explicitly require that an input parameter be copied like so: +In C++, R-value references come from a temporary value, or are explicitly created from a named value via `std::move`. In this way, C++ enforces that no mutable references exist to the moved-out value, so that the memory may be safely invalidated. In Rust, mutable aliases are statically eliminated by the borrow checker, and so the rough equivalent of C++'s R-values are found in Rust's mutable references (`&mut`), which can only be used if no other mutable alias already exists to the given memory location. -```rust -fn must_copy(t: T) { - // Do something in here... -} -``` +Rust "move"s are about transferring ownership, rather than eliminating mutable aliases (which are handled via the borrow checker). By default, the ownership of any function parameter is transferred into the function and out of the parameter at the call site, unless that parameter's type implements the `Copy` trait, in which case a shallow copy of the value is used to instantiate the actual parameter of the function. Rust's "move"s are often unecessary and undesirable. If the function you're writing does not require ownership of the value being passed in, that value should probably be borrowed (mutably or immutably, as necessary) rather than moved or copied. ### How can I interoperate with C++ from Rust, or with Rust from C++? @@ -899,7 +837,7 @@ In Swift, `?` is used to indicate an optional value. This is already done by `Op Rust and Go have substantially different design goals, and so differ substantially. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones: -- Rust is lower level than Go, comparable with C, C++, D, and Nim. It provides access to memory management primitives that do not exist in Go (which has a garbage collector) +- Rust is lower level than Go, comparable with C and C++. It provides access to memory management primitives that do not exist in Go (which has a garbage collector) - Rust's focus is on ensuring safety and efficiency while also providing high-level affordances, while Go's is on being a small, simple language which compiles quickly and can work nicely with a variety of tools - Rust has strong support for generics, which Go does not - Rust has strong influences from the world of functional programming, including a type system which draws from Haskell's typeclasses. Go has a simpler type system, using interfaces for basic generic programming @@ -912,7 +850,15 @@ Rust is probably not the best choice in every situation. If you're considering u ### How do Rust traits compare to Haskell typeclasses? -Rust traits are similar to Haskell typeclasses, but are currently not as powerful. Rust traits cannot express functional dependencies or type families, nor does Rust have full support for higher-kinded types. Some of these may be added in the future, but are not provided currently. +Rust traits are similar to Haskell typeclasses, but are currently not as powerful, as Rust cannot express higher-kinded types. Rust's associated types are equivalent to Haskell type families. + +Some specific difference between Haskell typeclasses and Rust traits include: + +- Rust traits have an implicit first parameter called `Self`. `trait Bar` in Rust corresponds to `class Bar self` in Haskell, and `trait Bar` in Rust corresponds to `class Boo foo self` in Haskell. +- "Supertraits" or "superclass constraints" in Rust are written `trait Sub: Super`, compared to `class Super self => Sub self` in Haskell. +- Rust forbids orphan instances, resulting in different coherence rules in Rust compared to Haskell. +- Rust's `impl` resolution considers the relevant `where` clauses and trait bounds when deciding whether two `impl`s overlap, or choosing between potential `impl`s. Haskell only considers the constraints in the `instance` declaration, disregarding any constraints provided elsewhere. +- A subset of Rust's traits (the ["object safe"](https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md) ones) can be used for dynamic dispatch via trait objects. The same feature is available in Haskell via GHC's `ExistentialQuantification`.

Documentation

@@ -928,31 +874,34 @@ When you use `cargo doc` to generate documentation for your own project, it also ### What is this project's goal? -To design and implement a safe, concurrent, practical, static systems language. +To design and implement a safe, concurrent, practical systems language. Rust exists because other languages at this level of abstraction and efficiency are unsatisfactory. In particular: 1. There is too little attention paid to safety. 2. They have poor concurrency support. 3. There is a lack of practical affordances. +4. They offer limited control over resources. -Rust exists as alternative language that provides both efficient code and a comfortable level of abstraction, while improving on all three of these points. +Rust exists as alternative language that provides both efficient code and a comfortable level of abstraction, while improving on all four of these points. ### Is this project controlled by Mozilla? -No. Rust started as Graydon Hoare's part-time side project in 2006 and remained so for over 3 years. Mozilla got involved in 2009 once the language was mature enough to run basic tests and demonstrate its core concepts. Though it remains sponsored by Mozilla, Rust is developed by a diverse community of enthusiasts from many different places around the world. The [Rust Team](https://www.rust-lang.org/team.html) is composed of both Mozilla and non-Mozilla members. +No. Rust started as Graydon Hoare's part-time side project in 2006 and remained so for over 3 years. Mozilla got involved in 2009 once the language was mature enough to run basic tests and demonstrate its core concepts. Though it remains sponsored by Mozilla, Rust is developed by a diverse community of enthusiasts from many different places around the world. The [Rust Team](https://www.rust-lang.org/team.html) is composed of both Mozilla and non-Mozilla members, and `rustc` (Rust's compiler) has had over [1,000 unique contributors](https://github.com/rust-lang/rust/) so far. + +As far as [project governance](https://github.com/rust-lang/rfcs/blob/master/text/1068-rust-governance.md) goes, Rust is managed by a core team that sets the vision and priorities for the project, and accepts input on the design of the language via RFC proposals. There are also subteams to guide and foster development of particular areas of interest, including Rust libraries, Rust tools, and moderation of the official Rust communities. For changes which do not require an RFC, decisions are made through pull requests on the [`rustc` repository](https://github.com/rust-lang/rust). -### What are explicit non-goals of Rust? +### What are some design goals of Rust? -1. To employ any particularly cutting-edge technologies. Old, established techniques are better. -2. To prize expressiveness, minimalism or elegance above other goals. These are desirable but subordinate goals. -3. To cover the complete feature-set of C++, or any other language. It should provide majority-case features. -4. To be 100% static, 100% safe, 100% reflective, or too dogmatic in any other sense. Trade-offs exist. -5. To run on "every possible platform". It must eventually work without unnecessary compromises on widely-used hardware and software platforms. +1. We do not employ any particularly cutting-edge technologies. Old, established techniques are better. +2. We do not prize expressiveness, minimalism or elegance above other goals. These are desirable but subordinate goals. +3. We do not intend to cover the complete feature-set of C++, or any other language. Rust should provide majority-case features. +4. We do not intend to be 100% static, 100% safe, 100% reflective, or too dogmatic in any other sense. Trade-offs exist. +5. We do not demand that Rust run on "every possible platform". It must eventually work without unnecessary compromises on widely-used hardware and software platforms. ### In which projects is Mozilla using Rust? -The main project is [Servo](https://github.com/servo/servo), an experimental browser engine Mozilla is working on. They are also working to integrate Rust components into Firefox. +The main project is [Servo](https://github.com/servo/servo), an experimental browser engine Mozilla is working on. They are also working to [integrate Rust components](https://bugzilla.mozilla.org/show_bug.cgi?id=1135640) into Firefox. ### What examples are there of large Rust projects? @@ -966,7 +915,7 @@ TODO: Write this answer. ### How can I try Rust easily? -The easiest way to try Rust is through the [Playground](https://play.rust-lang.org/), an online app for writing and running Rust code. If you want to try it on your system, [install it](https://www.rust-lang.org/install.html) and go through the ["Learn Rust"](https://doc.rust-lang.org/stable/book/learn-rust.html) section of the book. +The easiest way to try Rust is through the [playpen](https://play.rust-lang.org/), an online app for writing and running Rust code. If you want to try Rust on your system, [install it](https://www.rust-lang.org/install.html) and go through the ["Learn Rust"](https://doc.rust-lang.org/stable/book/learn-rust.html) section of the book. ### How do I get help with Rust issues? @@ -979,17 +928,13 @@ There are several ways. You can: ### Why has Rust changed so much over time? -Rust started with a goal of creating a safe but usable systems programming language. In pursuit of this goal it explored a lot of ideas, some of which it kept (lifetimes, traits) while others were discarded (the typestate system). Also, in the run up to 1.0 a lot of the standard library was rewritten. Some of this was out of a desire to improve the old versions of the APIs. Some of it was out of a desire for improved Windows support. +Rust started with a goal of creating a safe but usable systems programming language. In pursuit of this goal it explored a lot of ideas, some of which it kept (lifetimes, traits) while others were discarded (the typestate system). Also, in the run up to 1.0 a lot of the standard library was rewritten as early designs were updated to best use Rust's features and provide quality, consistent cross-platform APIs. ### How does Rust language versioning work? -Rust maintains three "channels": stable, beta, and nightly. Stable and beta are updated every six weeks, with the current nightly becoming the new beta, and the current beta becoming the new stable. Language and standard library features marked unstable or hidden behind feature gates may only be used on the nightly channel. +Rust's language versioning follows Semver, with backwards incompatible changes of stable APIs only allowed in minor versions if those changes fix compiler bugs, patch safety holes, or change type inference to require additional annotation. -Anything marked stable will not change without a major version update with three exceptions: - -- Fixing compiler bugs -- Patching safety holes -- Changing type inference to require new annotations +Rust maintains three "release channels": stable, beta, and nightly. Stable and beta are updated every six weeks, with the current nightly becoming the new beta, and the current beta becoming the new stable. Language and standard library features marked unstable or hidden behind feature gates may only be used on the nightly channel. For details, read the Rust blog post ["Stability as a Deliverable."](http://blog.rust-lang.org/2014/10/30/Stability.html) @@ -997,11 +942,11 @@ For details, read the Rust blog post ["Stability as a Deliverable."](http://blog No, you cannot. Rust works hard to provide strong guarantees about the stability of the APIs provided on the beta and stable channels. When something is unstable, it means that we can't provide those guarantees for it yet, and don't want people relying on it staying the same. This gives us the opportunity to try changes in the wild on the nightly channel, while still maintaining strong guarantees for people seeking stability. -Things stabilize all the time, and the beta and stable channels update every six weeks. If you're waiting for a feature to be available without using the nightly channel, it should hopefully be available soon. +Things stabilize all the time, and the beta and stable channels update every six weeks. If you're waiting for a feature to be available without using the nightly channel, you can locate its tracking issue by checking the [`B-unstable`](https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+tracking+label%3AB-unstable) tag on the issue tracker. ### What IDE should I use? -There are a couple developing options: [RustDT](https://github.com/RustDT/RustDT) is a Rust plugin for Eclipse, while [SolidOak](https://github.com/oakes/SolidOak) is a from-scratch Rust IDE. Both are solid options for a Rust IDE. Rust also integrates well with a variety of text editors. Detailed information about both text editor and IDE support can be found at [areweideyet.com](http://areweideyet.com/). +There are a number of options for development environment with Rust, all of which are detailed on the official [IDE support page](https://www.rust-lang.org/ides.html). ### Why a dual MIT/ASL2 License? @@ -1011,9 +956,3 @@ The Apache license includes important protection against patent aggression, but This is partly due to preference of the original developer (Graydon), and partly due to the fact that languages tend to have a wider audience and more diverse set of possible embeddings and end-uses than products such as web browsers. We'd like to appeal to as many of those potential contributors as possible. -### Why is the language called Rust? - -As [stated by Graydon Hoare](https://www.reddit.com/r/rust/comments/27jvdt/internet_archaeology_the_definitive_endall_source/), original developer of the Rust language, the name "Rust" comes from his personal interest in fungi, and because it evoked the feeling he was looking for in a programming language name. But truly, as Graydon himself put it: - -> <graydon> IOW I don't have a really good explanation. it seemed like a good name. (also a substring of "trust", "frustrating", "rustic" and ... "thrust"?)
-> <graydon> I think I named it after fungi. rusts are amazing creatures. From fabd2ba0276f2d9660fa2f12ab4ee21cc49cffce Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 20 Dec 2015 12:11:31 -0800 Subject: [PATCH 18/41] Take a pass over the whole FAQ --- faq.md | 214 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 119 insertions(+), 95 deletions(-) diff --git a/faq.md b/faq.md index c00cdc199..fc1f12b4d 100644 --- a/faq.md +++ b/faq.md @@ -32,7 +32,7 @@ If there is some common or important question you feel is wrongly left unanswere
  • Design Patterns
  • Other Languages
  • Documentation
  • -
  • Project
  • +
  • The Rust Project
  • @@ -49,7 +49,7 @@ It is an explicit goal of Rust to be at least as fast as C++. Language decisions No. A language that requires a GC is a language that opts into a larger, more complex runtime than Rust cares for. Rust is usable on bare metal with no extra runtime. -Additionally, garbage collection is frequently a source of non-deterministic behavior. Rust provides the tools to make using third-party garbage collectors [possible](http://manishearth.github.io/blog/2015/09/01/designing-a-gc-in-rust/), but it is not part of the language as provided. +Additionally, garbage collection is frequently a source of non-deterministic behavior. Rust provides tools to make using third-party garbage collectors [possible](http://manishearth.github.io/blog/2015/09/01/designing-a-gc-in-rust/), but it is not part of the language as provided. ### Why is my program slow? @@ -59,11 +59,13 @@ If you compile with `cargo`, use the `--release` flag. If you compile with `rust ### Why is Rust compilation slow? -Code translation and optimizations. Rust provides a number of high level interfaces that compile down into efficient machine code, and those translations take some time to run. +Code translation and optimizations. Rust provides high level abstractions that compile down into efficient machine code, and those translations take time to run, especially when optimizing. -But all is not lost. The Rust compiler has evolved significantly over a number of years, and a lot of good work is being done to [make it work faster](https://github.com/rust-lang/rfcs/pull/1211), and to make it feel faster during development. +But Rust's compilation time is not as bad as it may seem, and there is reason to believe it will improve. When comparing projects of similar size between C++ and Rust, compilation time of the entire project is generally believed to be comparable. The common perception that Rust compilation is slow is in large part due to the differences in the *compilation model* between C++ and Rust: C++'s compilation unit is the file, while Rust's is the crate, composed of many files. Thus, during development, modifying a single C++ file can result in much less recompilation than in Rust. There is a major effort underway to refactor the compiler to introduce [incremental compilation](https://github.com/rust-lang/rfcs/blob/master/text/1298-incremental-compilation.md), which will provide Rust the compile time benefits of C++'s model. -### What hashing algorithm does Rust's `HashMap` use? +Aside from the compilation model, there are several other aspects of Rust's language design and compiler implementation that affect compile-time performance. First, Rust has a moderatly-complex type system, and must spend a non-neglibable amount of compile time enforcing the constraints that make Rust safe at runtime. Secondly, Rust's use of LLVM for code generation is a double-edged sword: while it enables Rust to have world-class runtime performance, LLVM is a large framework that is not focused on compile-time performance. Thirdly, the Rust compiler suffers from long-standing technical debt, and notably generates poor-quality LLVM IR which LLVM must spend time "fixing". There is hope that future [MIR-based](https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md) optimization and translation passes will ease the burden the Rust compiler places on LLVM. Finally, Rust's preferred strategy of monomorphising generics (ala C++), while producing fast code, demands that significantly more code be generated than other translation strategies. + +### Why are Rust's `HashMap`s slow? By default, Rust's `HashMap` uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). @@ -75,11 +77,11 @@ You can run benchmarks, but only on the nightly channel. Rust's benchmarking mec ### Does Rust do tail-call optimization? -In general, tail-call optimization is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html), but may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization). There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. The compiler is still free to optimize tail-calls [when it pleases](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), however, and the language has a keyword (`become`) reserved for future explicit tail calls. +Not generally, no. Tail-call optimization may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), but is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html). As the feature has always been desired Rust has a keyword (`become`) reserved, though it is not clear yet whether it is technically possible, nor whether it will be implemented. There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. ### Does Rust have a runtime? -Just like C, Rust has a [very small and limited runtime](https://doc.rust-lang.org/std/rt/) providing a heap, backtraces, unwinding, and stack guards. This runtime is comparable to the [C runtime](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html), and allows for the calling of Rust functions from C without setup. +Not in the typical sense used by languages such as Java, but parts of the Rust standard library can be considered a "runtime", providing a heap, backtraces, unwinding, and stack guards. There is a [small amount of initialization code](https://github.com/rust-lang/rust/blob/33916307780495fe311fe9c080b330d266f35bfb/src/libstd/rt.rs#L43) that runs before the user's `main` function. The Rust standard library additionally links to the the C standard library, which does similar [runtime initialization](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html). Rust code can be compiled without the standard library, in which case there is no runtime at all.

    Syntax

    @@ -89,19 +91,19 @@ Use of curly braces to denote blocks is a common design choice in a variety of p Curly braces also allow for more flexible syntax for the programmer, a simpler parser in the compiler, and help reduce the possibility of logic mistakes caused by incorrect indentation, like Apple's [goto fail](https://gotofail.com/) bug. -### I can leave out parentheses on `if` conditions, why do I have to put brackets around single line blocks? Why is the C style not allowed? +### I can leave out parentheses on `if` conditions, so why do I have to put brackets around single line blocks? Why is the C style not allowed? Whereas C requires mandatory parantheses for `if`-statements but leave brackets optional, Rust makes the opposite choice. Rust's `if`-expressions thus require strictly fewer delimiters than their C counterparts. Furthermore, the optional brackets on C's `if`-statements are well-understood as a hazard to maintenance and refactoring. ### Why is there no literal syntax for dictionaries? -There are two data types in the Rust standard library that fit the definition of a "dictionary": `BTreeMap` and `HashMap`, but they have different performance characteristics, and it's not clear which one should be the default for any potential dictionary literal syntax. Rust prefers to make performance costs explicit, and any selection of a default from these two choices may lead to performance surprises that undermine this intention. +The reason Rust does not have syntax for initializing dictionaries — or collections in general — is due to Rust's overall design preference for limiting the size of the *language* while enabling powerful *libraries*. The only type of collection that Rust has direct syntax for initializing is the array type, which is also the only type of collection built into the language. Note that Rust does not even have syntax for initializing the common `Vec` collection type, instead the standard library defins the [`vec!`](http://doc.rust-lang.org/std/macro.vec!.html) macro. -If you want a more convenient syntax for `BTreeMap` or `HashMap` creation, you can [create a macro](http://stackoverflow.com/questions/27582739/how-do-i-create-a-hashmap-literal) to provide it. +This design choice of using Rust's macro facilities to initialize collections will likely be extended generically to other collections in the future, enabling simple initialization of not only `HashMap` and `Vec`, but also other collection types such as [`BTreeMap`](http://doc.rust-lang.org/collections/struct.BTreeMap.html). In the meantime, if you want a more convenient syntax for initializing collections, you can [create your own macro](http://stackoverflow.com/questions/27582739/how-do-i-create-a-hashmap-literal) to provide it. ### When should I use an implicit return? -Implicit returns are simply a coding style option, and can be used anywhere they make sense. While early returns require an explicit `return`, any other return can be made implicit according to your preferences or the preferences of your project. +Implicit returns are simply a coding style option, and can be used anywhere they make sense. While early returns require an explicit `return`, any other return can be made implicit according to your preferences or the preferences of your project. In the Rust project itself, the style guidelines lean toward preferring implicit returns. ### Why aren't function signatures inferred? @@ -111,7 +113,9 @@ Implicit returns are simply a coding style option, and can be used anywhere they ### Why does `match` have to be exhaustive? -`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to an `enum` in the future will cause a compilation failure, rather than an error at runtime. Second, it makes cost explicit. In general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched, though it could fall through if the type of the `match` expression is `()`. This sort of hidden cost and special casing is against the language's philosophy. It is easy to ignore all unspecified cases by using the `_` wildcard: +`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to an `enum` in the future will cause a compilation failure, rather than an error at runtime. Second, it makes the semantics of the default case explicit: in general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched. Early versions of Rust did not require `match` cases to be exhaustive and it was found to be a great source of bugs. + +It is easy to ignore all unspecified cases by using the `_` wildcard: ```rust match val.do_something() { @@ -124,23 +128,25 @@ match val.do_something() { ### Which of `f32` and `f64` should I prefer to floating-point math? -The choice of which to use is dependent on the focus of the program. - -If you're interested in the greatest degree of precision with your floating point numbers, then `f64` is the preferred choice. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated innacuracy of having fewer bits per value, then `f32` is better. +The choice of which to use is dependent on the purpose of the program. -All things being equal, `f64` is likely a better default. - -### Why can't I compare floats? +If you are interested in the greatest degree of precision with your floating point numbers, then prefer `f64`. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated innacuracy of having fewer bits per value, then `f32` is better. Operations on `f32` are usually faster, even on 64-bit hardware. As a common example, graphics programming typically uses `f32` because it requires high performance, and 32-bit floats are sufficient for representing pixels on the screen. -You can! Floats implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) there is no total ordering for floating point numbers. There [is a crate](https://crates.io/crates/ordered-float) that provides a total ordering on floats by wrapping them, which may be desirable depending on your use-case. You can still do all of the normal comparison operations you would expect, but you can't use the `cmp` function. +If in doubt, choose `f64` for the more accurate precision. ### Why can't I use `f32` or `f64` as `HashMap` keys? In order to be used as a key in a `HashMap`, a type must implement the `Eq` and `Hash` traits. `f32` and `f64` implement `PartialEq`, but not `Eq`, because one of the potential values for floating-point types is `NaN` (or "not a number"). `NaN` values are [not equal to any float, and are not equal to each other](https://en.wikipedia.org/wiki/NaN). This means that `f32` and `f64` can't be used as keys in a HashMap. +### Why can't I compare floats? + +Floats can be compared in some circumstances, but not others. Floats do implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) [there is no total ordering for floating point numbers](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate). The practical effect of this is that data structures that require a total ordering, such as [`BTreeMap`](http://doc.rust-lang.org/std/collections/struct.BTreeMap.html) do not work with floating point numbers. + +There [is a crate](https://crates.io/crates/ordered-float) that provides a total ordering on floats by wrapping them, which may be desirable depending on your use-case. You can still do all of the normal comparison operations you would expect, but you can't use the `cmp` function. + ### How can I convert between numeric types? -There are two ways: the `as` keyword, which does simple casting for primitive types, and the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types). +There are two ways: the `as` keyword, which does simple casting for primitive types, and the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types). The `Into` and `From` traits are only implemented in cases where conversions are lossless, so for example, `f64::from(0f32)` will compile while `f32:from(0f64)` will not. `as` on the other hand will convert between any two primitive types, truncating values as necessary.

    Strings

    @@ -150,39 +156,30 @@ Using [Deref coercions](https://doc.rust-lang.org/stable/book/deref-coercions.ht ### How can I convert from `&str` to `String` or the other way around? -`String`s are automatically converted into `&str` when you take a reference of them. For example, the following code works: +The `to_owned()` method converts from a `&str` into a `String`, and `String`s are automatically converted into `&str` when you borrow a reference to them. Both are demonstrated in the following example: ```rust -fn say_hello(name: &str) { - println!("Hello {}!", name); -} - fn main() { let s = "Jane Doe".to_owned(); say_hello(&s); } -``` - -The `to_owned()` method is how you convert from a `&str` into a `String`. This is necessary because string literals in Rust are of type `&str`. In this particular example, making `s` into a `String` isn't actually necessary, and the code could be rewritten as: -```rust fn say_hello(name: &str) { println!("Hello {}!", name); } - -fn main() { - let s = "Jane Doe"; - say_hello(s); -} ``` ### What are the differences between the two different string types? -`String` is a buffer of UTF-8 bytes allocated on the heap, while `&str` is a "view" into a `String` allocated elsewhere. +`String` is an owned buffer of UTF-8 bytes allocated on the heap. Mutable `String`s can be modified, growing their capacity as needed.`&str` is fixed-capacity "view" into a `String` allocated elsewhere, commonly on the heap, in the case of slices dereferenced from `String`s, or in static memory, in the case of string literals. + +`&str` is a primitive type implemented by the Rust language, while `String` is implemented in the standard library. ### How do I do O(1) character access in a `String`? -Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a "code unit" (In UTF-16, code units 2 bytes instead. In UTF-32 they are 4 bytes). "Code points" are composed of one or more code units, and combine in "grapheme clusters" which most closely approximate characters. +You cannot. At least not without a firm understanding of what you mean by "character", and preprocessing the string to find them. + +Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a "code unit" (in UTF-16, code units are 2 bytes; in UTF-32 they are 4 bytes). "Code points" are composed of one or more code units, and combine in "grapheme clusters" which most closely approximate characters. Thus, even though you may index on bytes in a UTF-8 string, you can't access the `i`th code point or grapheme cluster in constant time. However, if you know at which byte that desired code point or grapheme cluster begins, then you _can_ access it in constant time. Functions including `str::find()` and regex matches return byte indices, facilitating this sort of access. @@ -228,7 +225,7 @@ The way Rust `for` loops work, they actually call `into_iter()` (which is define You don't necessarily have to. If you're declaring an array directly, the size is inferred based on the number of elements. But if you're declaring a function that takes an array, the compiler has to know how big that array will be. -One thing to note is that currently Rust doesn't offer generics over arrays of different size. This is a planned feature, but isn't available currently. If you'd like to accept a contiguous container of a variable number of values, use a Vec or slice (depending on whether you need ownership). +One thing to note is that currently Rust doesn't offer generics over arrays of different size. If you'd like to accept a contiguous container of a variable number of values, use a `Vec` or slice (depending on whether you need ownership).

    Ownership

    @@ -236,7 +233,7 @@ One thing to note is that currently Rust doesn't offer generics over arrays of d There are three major options: -- You can implement it using `Weak` or `Rc` to allow shared ownership of nodes, +- You can implement it using `Rc` and `Weak` to allow shared ownership of nodes, although this approach pays the cost of memory management. - You can implement it using `unsafe` code using raw pointers. This will be more efficient, but bypasses Rust's safety guarantees. @@ -272,15 +269,18 @@ fn main() { These are different terms for the same thing. In both cases, it means the value has been moved to another owner, and moved out of the calling owner. -### Why can I use integers after passing them to a function, but not structs? - ### Why can values of some types be used after passing them to a function, while reuse of values of other types results in an error? If a type implements the `Copy` trait, then it will be copied when passed to a function. All numeric types in Rust implement `Copy`, but struct types do not implement `Copy` by default, so they are moved instead. This means that the struct can no longer be used elsewhere, unless it is moved back out of the function via the return. -### How do you deal with a "Use of moved value" error? +### How do you deal with a "use of moved value" error? -This error means that the value you're trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary. If it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. It may also be possible to implement `Copy` (for implicit copying, rather than moving) or `Clone` (explicit copying) for the type in question. If none of these are possible, you may want to return ownership of the value when the function is done, thus eliminating this error. +This error means that the value you're trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary: if it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. Otherwise if the type being moved implements `Clone`, then calling `clone()` on it before +moving will move a copy of it, leaving the original still available for further use. Note though that cloning a value should typically be the last resort since cloning can be expensive, causing further allocations. + +If the moved value is of your own custom type, consider implementing `Copy` (for implicit copying, rather than moving) or `Clone` (explicit copying). `Copy` is most commonly implemented with `#[derive(Copy, Clone)]` (`Copy` requires `Clone`), and `Clone` with `#[derive(Clone)]`. + +If none of these are possible, you may want to modify the function that acquired ownership to return ownership of the value when the function exits. ### What are the rules for using `self`, `&self`, or `&mut self` in a method declaration? @@ -301,9 +301,16 @@ Understanding these rules and [lifetimes](https://doc.rust-lang.org/stable/book/ ### How do deref coercions work? -[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait. +[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait, which looks like -A Deref implementation indicates that the implementing type may be converted into `Target` by a call to the `deref` function, which takes an immutable reference of a certain lifetime to the calling struct, and returns a reference of the same lifetime to the target. +```rust +pub trait Deref { + type Target: ?Sized; + fn deref(&self) -> &Self::Target; +} +``` + +A Deref implementation indicates that the implementing type may be converted into `Target` by a call to the `deref` function, which takes an immutable reference of a certain lifetime to the calling struct, and returns a reference of the same lifetime to the target. The `*` prefix operator is shorthand for the `deref` method. You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html#implementors) for the standard library in the documentation. @@ -311,7 +318,7 @@ You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/s ### Why lifetimes? -Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety without mechanisms like garbage collection, which can have undesirable implications for performance. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). +Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety garbage collection, which can have undesirable implications for performance. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). ### Why is the lifetime syntax the way it is? @@ -319,7 +326,7 @@ The `'a` syntax comes from the ML family of programming languages, where `'a` is ### When is `Rc` useful? -This is covered in the [official documentation for `Rc`](https://doc.rust-lang.org/stable/std/rc/), Rust's non-atomically reference-counted pointer type. In short, `Rc` and its thread-safe cousin `Arc` are useful to express shared ownership of an immutable value, and have the system automatically deallocate the associated memory when no one has access to it. +This is covered in the [official documentation for `Rc`](https://doc.rust-lang.org/stable/std/rc/), Rust's non-atomically reference-counted pointer type. In short, `Rc` and its thread-safe cousin `Arc` are useful to express shared ownership, and have the system automatically deallocate the associated memory when no one has access to it. ### How do I return a borrow to something I created from a function? @@ -345,17 +352,19 @@ The only way to construct a value of type `&Foo` or `&mut Foo` is to specify an ### How do I express the absence of a value without `null`? -You can do that with the `Option` type, which can either be `Some(T)` or `None`. `Some(T)` indicates that a value of type `T` is contained within, while `None` indicates the absence of a value. +You can do that with the [`Option`](https://doc.rust-lang.org/stable/std/option/index.html) type, which can either be `Some(T)` or `None`. `Some(T)` indicates that a value of type `T` is contained within, while `None` indicates the absence of a value.

    Generics

    ### What is "monomorphization"? -Monomorphisation is the process by which Rust generates specific instances of a generic function based on the parameter types of calls to that function. This is used to provide static dispatch for generic functions. For functions using trait objects for polymorphism, dynamic dispatch is used instead, with calls to the function monomorphized at runtime based on the particular type implementing the boxed trait. +Monomorphisation is the process by which Rust translates to machine code specific instances of a generic function based on the parameter types of calls to that function. During monomorphisisation a new copy of the generic function is translated for each unique set of types the function is instantiated with. This strategy is the same as used by C++. It results in fast code that is specialized for every callsite and statically dispatched, with the tradeoff that functions instantiated with many different types can cause "code bloat", where multiple function instances result in larger binaries than would be created with other translation strategies. + +Functions that accept [trait objects](http://doc.rust-lang.org/book/trait-objects.html) instead of type parameters do not undergo monomorphization. Instead, methods on the trait objects are dispatched dynamically at runtime. ### What's the difference between a function and a closure that doesn't capture any variables? -Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the the struct can be called as a function. +Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the the struct can be called as a function. Bare functions can not capture an environment. The big difference between these traits is how they take the `self` parameter. `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. @@ -379,8 +388,6 @@ The part that Rust currently can't do is that `Self` above is a type constructor Finally, Rust doesn't currently have them simply because they haven't been a priority. There is nothing inherent to the language that stops us from implementing higher-kinded types, it just hasn't been done yet. There is an open RFC for implementing them, but no real proposal exists yet. If one comes around, it will definitely be considered. -(Credit to anasaziwochi for his [useful explanation](https://www.reddit.com/r/rust/comments/2av5tv/why_does_rust_not_have_a_functor_trait/ciz6iwm) of higher-kinded types in Rust.) - ### What do named type parameters like `` in generic types mean? These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a simple `where` clause. In essence, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. @@ -390,6 +397,8 @@ These are called [associated types](https://doc.rust-lang.org/stable/book/associ You can provide custom implementations for a variety of operators using their associated traits: `Add` for `+`, `Mul` for `*`. It looks like this: ```rust +use std::ops::Add; + struct Foo; impl Add for Foo { @@ -403,24 +412,41 @@ impl Add for Foo { The following operators can be overloaded: -| Operation | Trait | -|:--------------------|:-----------| -| `+` | `Add` | -| `binary -` | `Sub` | -| `*` | `Mul` | -| `/` | `Div` | -| `unary -` | `Neg` | -| `%` | `Rem` | -| `&` | `BitAnd` | -| | | `BitOr` | -| `^` | `BitXor` | -| `!` | `Not` | -| `<<` | `Shl` | -| `>>` | `Shr` | -| `*` | `Deref` | -| `mut *` | `DerefMut` | -| `[]` | `Index` | -| `mut []` | `IndexMut` | +| Operation | Trait | +|:--------------------|:-------------| +| `+` | [`Add`] | +| `binary -` | [`Sub`] | +| `*` | [`Mul`] | +| `/` | [`Div`] | +| `unary -` | [`Neg`] | +| `%` | [`Rem`] | +| `&` | [`BitAnd`] | +| | | [`BitOr`] | +| `^` | [`BitXor`] | +| `!` | [`Not`] | +| `<<` | [`Shl`] | +| `>>` | [`Shr`] | +| `*` | [`Deref`] | +| `mut *` | [`DerefMut`] | +| `[]` | [`Index`] | +| `mut []` | [`IndexMut`] | + +[`Add`]: https://doc.rust-lang.org/stable/std/ops/trait.Add.html +[`Sub`]: https://doc.rust-lang.org/stable/std/ops/trait.Sub.html +[`Mul`]: https://doc.rust-lang.org/stable/std/ops/trait.Mul.html +[`Div`]: https://doc.rust-lang.org/stable/std/ops/trait.Div.html +[`Neg`]: https://doc.rust-lang.org/stable/std/ops/trait.Neg.html +[`Rem`]: https://doc.rust-lang.org/stable/std/ops/trait.Rem.html +[`BitAnd`]: https://doc.rust-lang.org/stable/std/ops/trait.BitAnd.html +[`BitOr`]: https://doc.rust-lang.org/stable/std/ops/trait.BitOr.html +[`BitXor`]: https://doc.rust-lang.org/stable/std/ops/trait.BitXor.html +[`Not`]: https://doc.rust-lang.org/stable/std/ops/trait.Not.html +[`Shl`]: https://doc.rust-lang.org/stable/std/ops/trait.Shl.html +[`Shr`]: https://doc.rust-lang.org/stable/std/ops/trait.Shr.html +[`Deref`]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html +[`DerefMut`]: https://doc.rust-lang.org/stable/std/ops/trait.DerefMut.html +[`Index`]: https://doc.rust-lang.org/stable/std/ops/trait.Index.html +[`IndexMut`]: https://doc.rust-lang.org/stable/std/ops/trait.IndexMut.html ### Why the split between `Eq`/`PartialEq` and `Ord`/`PartialOrd`? @@ -450,7 +476,7 @@ fn main() { ### How do I read file input efficiently? -The [`File` type](https://doc.rust-lang.org/stable/std/fs/struct.File.html) implements the `Read` trait, which has a variety of functions for reading and writing data, including `read()`, `read_to_end()`, `bytes()`, `chars()`, and `take()`. Each of these functions reads in a certain amount of input from a given file. `read()` reads as much input as the underlying system will provide in a single call. `read_to_end()` reads the entire buffer into a vector, allocating as much space as is needed. `bytes()` and `chars()` allow you to iterate over the bytes and characters of the file, respectively. Finally, `take()` allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need. +The [`File` type](https://doc.rust-lang.org/stable/std/fs/struct.File.html) implements the `Read` trait, which has a variety of functions for reading and writing data, including `read()`, `read_to_end()`, `bytes()`, `chars()`, and `take()`. Each of these functions reads a certain amount of input from a given file. `read()` reads as much input as the underlying system will provide in a single call. `read_to_end()` reads the entire buffer into a vector, allocating as much space as is needed. `bytes()` and `chars()` allow you to iterate over the bytes and characters of the file, respectively. Finally, `take()` allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need. For buffered reads, use the [`BufReader`](http://doc.rust-lang.org/stable/std/io/struct.BufReader.html) struct, which helps to reduce the number of system calls when reading. @@ -490,7 +516,7 @@ Yes, if the type implements `Sync`, doesn't implement `Drop`, and you don't try ### Can I write a macro to generate identifiers? -Not currently. Rust macros are so-called hygienic macros, not the unlimited compile-time syntax editing you see in C. Macro invocations can only appear in places where they are explicitly supported: items, methods declarations, statements, expressions, and patterns. Here, "method declarations" means a blank space where a method can be put. They can't be used to complete a partial method declaration. By the same logic, they can't be used to complete a partial variable declaration. +Not currently. Rust macros are so-called ["hygienic macros"](https://en.wikipedia.org/wiki/Hygienic_macro), which intentionally avoid capturing or creating identifiers that may cause name unexpected collisions with other identifiers. Their capabilities are significantly different than the style of macros commonly associated with the C preprocessor. Macro invocations can only appear in places where they are explicitly supported: items, methods declarations, statements, expressions, and patterns. Here, "method declarations" means a blank space where a method can be put. They can't be used to complete a partial method declaration. By the same logic, they can't be used to complete a partial variable declaration.

    Debugging

    @@ -512,11 +538,11 @@ To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapp ### Can Rust reasonably function without the standard library? -Absolutely. Rust programs can be set to not load the standard library using the `#![no_std]` attribute. With this attribute set, you can continue to use the Rust core, which is nothing but the platform-agnostic primitives. As such, it doesn't include IO, concurrency, heap allocation, etc. Note however that `libcore` has not been stabilized. +Absolutely. Rust programs can be set to not load the standard library using the `#![no_std]` attribute. With this attribute set, you can continue to use the Rust core library, which is nothing but the platform-agnostic primitives. As such, it doesn't include IO, concurrency, heap allocation, etc. Note however that `libcore` has not been stabilized. ### Can I write an operating system in Rust? -Yes! In fact there are several projects underway doing just that, including [reenix](https://github.com/scialex/reenix), [RustOS](https://github.com/ryanra/RustOS), and [redox](http://www.redox-os.org/). +Yes! In fact there are [several projects underway doing just that](http://wiki.osdev.org/Rust). ### How can I read or write numeric types like `i32` or `f64` in big-endian or little-endian format in a file or other byte stream? @@ -535,7 +561,7 @@ enum CLike { } ``` -The `repr` attribute can be applied to such `enums` to give them the same representation they would have in equivalent C code. This allows using Rust `enum`s in FFI code where C `enum`s are also used, for most use cases. The attribute can also be applied to `struct`s to get the same layout as a C `struct` would. +The `#[repr(C)]` attribute can be applied to such `enums` to give them the same representation they would have in equivalent C code. This allows using Rust `enum`s in FFI code where C `enum`s are also used, for most use cases. The attribute can also be applied to `struct`s to get the same layout as a C `struct` would.

    Cross-Platform

    @@ -546,7 +572,7 @@ TODO: Write this answer. --> @@ -561,11 +587,11 @@ Yes it can! There are already examples of using Rust for both [Android](https:// ### Can I run my Rust program in a web browser? -There [are efforts](https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/) to make Rust run in the web browser using Emscripten. Given that Rust is implemented on top of LLVM, this should be possible, but Rust currently runs on a special patched version of LLVM, and so it is tougher than it would otherwise be. This will likely improve over time. +Not yet, but there are efforts underway to make Rust compile to the web with Emscripten. ### How do I cross-compile in Rust? -Cross compilation is possible in Rust, but it requires [a bit of work](https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md) to set up. Rust does distribute [copies of the standard library](http://static.rust-lang.org/dist/) for each of the supported platforms, which are contained in the `rust-std-*` files for each of the build directories found on the distribution page. +Cross compilation is possible in Rust, but it requires [a bit of work](https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md) to set up. Rust does distribute [copies of the standard library](http://static.rust-lang.org/dist/) for each of the supported platforms, which are contained in the `rust-std-*` files for each of the build directories found on the distribution page, but there are not yet automated ways to install them.

    Modules and Crates

    @@ -587,7 +613,7 @@ There are also `self` and `super`, which disambiguate `use` paths as being relat For complete information on `use`ing libraries, read the Rust book's chapter ["Crates and Modules"](https://doc.rust-lang.org/stable/book/crates-and-modules.html). -### Why do I have to declare module files with mod at the top level of the crate, instead of just `use`ing them? +### Why do I have to declare module files with `mod` at the top level of the crate, instead of just `use`ing them? There are two ways to declare modules in Rust, inline or in another file. Here is an example of each: @@ -657,7 +683,7 @@ TODO: Write this answer. ### How do I do dynamic Rust library loading? -Importing dynamic libraries in Rust can be with [libloading](https://crates.io/crates/libloading), which provides a cross-platform system for dynamic linking. +Import dynamic libraries in Rust with [libloading](https://crates.io/crates/libloading), which provides a cross-platform system for dynamic linking. ### Why doesn't [http://crates.io](http://crates.io) have namespaces? @@ -709,7 +735,7 @@ Yes you can! The major game programming library for Rust is [Piston](http://www. ### Is Rust object oriented? -It is multi-paradigm. Not everything is shoe-horned into a single abstraction. Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you're accustomed to. +It is multi-paradigm. Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you're accustomed to. ### How do I handle configuration of a struct with optional parameters? @@ -729,7 +755,7 @@ To define procedural constants that can't be defined via these mechanisms, use t ### Can I run initialization code that happens before main? -Rust has no cross-platform concept of "life before `main`". The closest you'll see can be done through the [`lazy_static`](https://github.com/Kimundi/lazy-static.rs) crate, which simulates a "before main" by lazily initializing static variables at their first usage. +Rust has no concept of "life before `main`". The closest you'll see can be done through the [`lazy_static`](https://github.com/Kimundi/lazy-static.rs) crate, which simulates a "before main" by lazily initializing static variables at their first usage. ### How do I map object-oriented concepts to Rust? @@ -747,12 +773,10 @@ Rust has consistently worked to avoid having features with overlapping purposes, ### Does Rust allow non-constant-expression values for globals? -No. Globals can not have a non-constant-expression constructor and cannot have a destructor at all. This is an opinion of the language. Static constructors are undesirable because portably ensuring a static initialization order is difficult. Life before main is often considered a misfeature, never to be used. Rust helps this along by just not having the feature. +No. Globals can not have a non-constant-expression constructor and cannot have a destructor at all. Static constructors are undesirable because portably ensuring a static initialization order is difficult. Life before main is often considered a misfeature so Rust does not allow it. See the [C++ FQA](http://yosefk.com/c++fqa/ctors.html#fqa-10.12) about the "static initialization order fiasco", and [Eric Lippert's blog](http://ericlippert.com/2013/02/06/static-constructors-part-one/) for the challenges in C#, which also has this feature. -However, `thread_local!` variables (which are restricted to a single thread) are effectively global for the thread in which they are defined, and may have a non-constant constructor and destructor. -

    Other Languages

    ### How can I implement something like C's `struct X { static int X; };` in Rust? @@ -765,10 +789,12 @@ Converting a C-style enum to an integer can be done with a simple `as` expressio Converting in the other direction can be done with a `match` statement, which maps different numeric values to different potential values for the enum. -### Why does Rust not have an ABI like C does, and why do I have to annotate things with extern? +### Why does Rust not have a stable ABI like C does, and why do I have to annotate things with extern? Committing to an ABI is a big thing, and can limit potentially advantageous language changes in the future. Given that Rust only hit 1.0 in May of 2015, it is still too early to make a commitment as big as a stable ABI. This does not mean that one won't happen in the future, though. +The `extern` keyword allows Rust to use specific ABI's, such as the well-defined C ABI, for interop with other languages. + ### Can Rust code call C code? Yes. Calling C code from Rust is simple and exactly as efficient as calling C code from C. @@ -779,7 +805,7 @@ Yes. The Rust code has to be exposed via an `extern` declaration, which makes it ### I already write perfect C++. What does Rust give me? -Modern C++ has made a lot of strides to being a safe and comfortable programming language, but it's not perfect, and it's still very easy to do things unsafely. This is something the C++ core developers are working to overcome, but C++ is limited by a long history that predates a lot of the ideas they are now trying to implement. +Modern C++ includes many features that make writing safe and correct code less error-prone, but it's not perfect, and it's still easy to introduce unsafety. This is something the C++ core developers are working to overcome, but C++ is limited by a long history that predates a lot of the ideas they are now trying to implement. Rust was designed from day one to be a safe systems programming language, which means it's not limited by historic design decisions that make getting safety right in C++ so complicated. In C++, safety is achieved by careful personal discipline, and is very easy to get wrong. In Rust, safety is the default. @@ -801,7 +827,7 @@ The simplest way is to interoperate through C. Both Rust and C++ provide a [fore ### Does Rust have C++-style constructors? -No. Functions can serve the same purpose as constructors without adding any language complexity. The usual name for the constructor-equivalent function in Rust is `new()`, although this is just a social norm rather than a language rule. The `new()` function in fact is just like any other function. An example of it looks like so: +No. Functions serve the same purpose as constructors without adding language complexity. The usual name for the constructor-equivalent function in Rust is `new()`, although this is just a convention rather than a language rule. The `new()` function in fact is just like any other function. An example of it looks like so: ```rust struct Foo { @@ -835,18 +861,16 @@ In Swift, `?` is used to indicate an optional value. This is already done by `Op ### How are Go and Rust similar, and how are they different? -Rust and Go have substantially different design goals, and so differ substantially. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones: +Rust and Go have substantially different design goals. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones: - Rust is lower level than Go, comparable with C and C++. It provides access to memory management primitives that do not exist in Go (which has a garbage collector) - Rust's focus is on ensuring safety and efficiency while also providing high-level affordances, while Go's is on being a small, simple language which compiles quickly and can work nicely with a variety of tools - Rust has strong support for generics, which Go does not - Rust has strong influences from the world of functional programming, including a type system which draws from Haskell's typeclasses. Go has a simpler type system, using interfaces for basic generic programming -Rust is probably not the best choice in every situation. If you're considering using either Rust or Go for a project it's probably best to try out both languages a bit and make an informed decision rather than base your decision on a small comparison of the two. - ### `gofmt` is great. Where's `rustfmt`? -`rustfmt` is [right here](https://github.com/nrc/rustfmt/), and is being actively developed to make reading Rust code as easy and predictable as possible. +`rustfmt` is [right here](https://github.com/rust-lang-nursery/rustfmt), and is being actively developed to make reading Rust code as easy and predictable as possible. ### How do Rust traits compare to Haskell typeclasses? @@ -870,7 +894,7 @@ You can report issues in the Rust documentation on the Rust compiler [issue trac When you use `cargo doc` to generate documentation for your own project, it also generates docs for the active dependency versions. These are put into the `target/doc` directory of your project. Use `cargo doc --open` to open the docs after building them, or just open up `target/doc/index.html` yourself after building the docs. -

    Project

    +

    The Rust Project

    ### What is this project's goal? @@ -928,11 +952,11 @@ There are several ways. You can: ### Why has Rust changed so much over time? -Rust started with a goal of creating a safe but usable systems programming language. In pursuit of this goal it explored a lot of ideas, some of which it kept (lifetimes, traits) while others were discarded (the typestate system). Also, in the run up to 1.0 a lot of the standard library was rewritten as early designs were updated to best use Rust's features and provide quality, consistent cross-platform APIs. +Rust started with a goal of creating a safe but usable systems programming language. In pursuit of this goal it explored a lot of ideas, some of which it kept (lifetimes, traits) while others were discarded (the typestate system, green threading). Also, in the run up to 1.0 a lot of the standard library was rewritten as early designs were updated to best use Rust's features and provide quality, consistent cross-platform APIs. ### How does Rust language versioning work? -Rust's language versioning follows Semver, with backwards incompatible changes of stable APIs only allowed in minor versions if those changes fix compiler bugs, patch safety holes, or change type inference to require additional annotation. +Rust's language versioning follows [SemVer](http://semver.org/), with backwards incompatible changes of stable APIs only allowed in minor versions if those changes fix compiler bugs, patch safety holes, or change type inference to require additional annotation. Rust maintains three "release channels": stable, beta, and nightly. Stable and beta are updated every six weeks, with the current nightly becoming the new beta, and the current beta becoming the new stable. Language and standard library features marked unstable or hidden behind feature gates may only be used on the nightly channel. @@ -940,7 +964,7 @@ For details, read the Rust blog post ["Stability as a Deliverable."](http://blog ### Can I use unstable features in the beta or stable channel? -No, you cannot. Rust works hard to provide strong guarantees about the stability of the APIs provided on the beta and stable channels. When something is unstable, it means that we can't provide those guarantees for it yet, and don't want people relying on it staying the same. This gives us the opportunity to try changes in the wild on the nightly channel, while still maintaining strong guarantees for people seeking stability. +No, you cannot. Rust works hard to provide strong guarantees about the stability of the features provided on the beta and stable channels. When something is unstable, it means that we can't provide those guarantees for it yet, and don't want people relying on it staying the same. This gives us the opportunity to try changes in the wild on the nightly channel, while still maintaining strong guarantees for people seeking stability. Things stabilize all the time, and the beta and stable channels update every six weeks. If you're waiting for a feature to be available without using the nightly channel, you can locate its tracking issue by checking the [`B-unstable`](https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+tracking+label%3AB-unstable) tag on the issue tracker. From 8b3265fdc4e246b4c83a5d32472a4f70f34960e3 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 20 Dec 2015 12:18:48 -0800 Subject: [PATCH 19/41] Fix alignment of operator table in FAQ --- css/style.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/css/style.css b/css/style.css index bfa665f92..69f7e8829 100644 --- a/css/style.css +++ b/css/style.css @@ -484,3 +484,7 @@ ul.laundry-list { -moz-columns: 150px 3; columns: 150px 3; } + + .faq table { + margin-left: 8rem; + } \ No newline at end of file From 0ef5d237b7621dd583185fd8bafb0ee664538791 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 2 Jan 2016 20:25:03 -0500 Subject: [PATCH 20/41] Fixed typos --- faq.md | 55 +++++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/faq.md b/faq.md index fc1f12b4d..b4f9f2f4f 100644 --- a/faq.md +++ b/faq.md @@ -63,7 +63,7 @@ Code translation and optimizations. Rust provides high level abstractions that c But Rust's compilation time is not as bad as it may seem, and there is reason to believe it will improve. When comparing projects of similar size between C++ and Rust, compilation time of the entire project is generally believed to be comparable. The common perception that Rust compilation is slow is in large part due to the differences in the *compilation model* between C++ and Rust: C++'s compilation unit is the file, while Rust's is the crate, composed of many files. Thus, during development, modifying a single C++ file can result in much less recompilation than in Rust. There is a major effort underway to refactor the compiler to introduce [incremental compilation](https://github.com/rust-lang/rfcs/blob/master/text/1298-incremental-compilation.md), which will provide Rust the compile time benefits of C++'s model. -Aside from the compilation model, there are several other aspects of Rust's language design and compiler implementation that affect compile-time performance. First, Rust has a moderatly-complex type system, and must spend a non-neglibable amount of compile time enforcing the constraints that make Rust safe at runtime. Secondly, Rust's use of LLVM for code generation is a double-edged sword: while it enables Rust to have world-class runtime performance, LLVM is a large framework that is not focused on compile-time performance. Thirdly, the Rust compiler suffers from long-standing technical debt, and notably generates poor-quality LLVM IR which LLVM must spend time "fixing". There is hope that future [MIR-based](https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md) optimization and translation passes will ease the burden the Rust compiler places on LLVM. Finally, Rust's preferred strategy of monomorphising generics (ala C++), while producing fast code, demands that significantly more code be generated than other translation strategies. +Aside from the compilation model, there are several other aspects of Rust's language design and compiler implementation that affect compile-time performance. First, Rust has a moderately-complex type system, and must spend a non-negligible amount of compile time enforcing the constraints that make Rust safe at runtime. Secondly, Rust's use of LLVM for code generation is a double-edged sword: while it enables Rust to have world-class runtime performance, LLVM is a large framework that is not focused on compile-time performance. Thirdly, the Rust compiler suffers from long-standing technical debt, and notably generates poor-quality LLVM IR which LLVM must spend time "fixing". There is hope that future [MIR-based](https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md) optimization and translation passes will ease the burden the Rust compiler places on LLVM. Finally, while Rust's preferred strategy of monomorphising generics (ala C++) produces fast code, it demands that significantly more code be generated than other translation strategies. ### Why are Rust's `HashMap`s slow? @@ -93,7 +93,7 @@ Curly braces also allow for more flexible syntax for the programmer, a simpler p ### I can leave out parentheses on `if` conditions, so why do I have to put brackets around single line blocks? Why is the C style not allowed? -Whereas C requires mandatory parantheses for `if`-statements but leave brackets optional, Rust makes the opposite choice. Rust's `if`-expressions thus require strictly fewer delimiters than their C counterparts. Furthermore, the optional brackets on C's `if`-statements are well-understood as a hazard to maintenance and refactoring. +Whereas C requires mandatory parantheses for `if`-statements but leaveis brackets optional, Rust makes the opposite choice. Rust's `if`-expressions thus require strictly fewer delimiters than their C counterparts. Furthermore, the optional brackets on C's `if`-statements are well-understood as a hazard to maintenance and refactoring. ### Why is there no literal syntax for dictionaries? @@ -109,11 +109,11 @@ Implicit returns are simply a coding style option, and can be used anywhere they - Mechanically, it simplifies the inference algorithm, as inference only requires looking at one function at a time. - Mandatory function signatures help enforce interface stability at both the module and crate level. -- It improves code comprehension for programmer, eliminating the need for an IDE running an inference algorithm across an entire crate to be able to guess at a function's argument types; it's always explicit and nearby. +- It improves code comprehension for the programmer, eliminating the need for an IDE running an inference algorithm across an entire crate to be able to guess at a function's argument types; it's always explicit and nearby. ### Why does `match` have to be exhaustive? -`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to an `enum` in the future will cause a compilation failure, rather than an error at runtime. Second, it makes the semantics of the default case explicit: in general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched. Early versions of Rust did not require `match` cases to be exhaustive and it was found to be a great source of bugs. +`match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding variants to the `enum` in the future will cause a compilation failure, rather than an error at runtime. Second, it makes the semantics of the default case explicit: in general, the only safe way to have a non-exhaustive `match` would be to panic the thread if nothing is matched. Early versions of Rust did not require `match` cases to be exhaustive and it was found to be a great source of bugs. It is easy to ignore all unspecified cases by using the `_` wildcard: @@ -126,13 +126,13 @@ match val.do_something() {

    Numerics

    -### Which of `f32` and `f64` should I prefer to floating-point math? +### Which of `f32` and `f64` should I prefer for floating-point math? The choice of which to use is dependent on the purpose of the program. If you are interested in the greatest degree of precision with your floating point numbers, then prefer `f64`. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated innacuracy of having fewer bits per value, then `f32` is better. Operations on `f32` are usually faster, even on 64-bit hardware. As a common example, graphics programming typically uses `f32` because it requires high performance, and 32-bit floats are sufficient for representing pixels on the screen. -If in doubt, choose `f64` for the more accurate precision. +If in doubt, choose `f64` for the greater precision. ### Why can't I use `f32` or `f64` as `HashMap` keys? @@ -171,13 +171,13 @@ fn say_hello(name: &str) { ### What are the differences between the two different string types? -`String` is an owned buffer of UTF-8 bytes allocated on the heap. Mutable `String`s can be modified, growing their capacity as needed.`&str` is fixed-capacity "view" into a `String` allocated elsewhere, commonly on the heap, in the case of slices dereferenced from `String`s, or in static memory, in the case of string literals. +`String` is an owned buffer of UTF-8 bytes allocated on the heap. Mutable `String`s can be modified, growing their capacity as needed. `&str` is a fixed-capacity "view" into a `String` allocated elsewhere, commonly on the heap, in the case of slices dereferenced from `String`s, or in static memory, in the case of string literals. `&str` is a primitive type implemented by the Rust language, while `String` is implemented in the standard library. ### How do I do O(1) character access in a `String`? -You cannot. At least not without a firm understanding of what you mean by "character", and preprocessing the string to find them. +You cannot. At least not without a firm understanding of what you mean by "character", and preprocessing the string to find the index of the desired character. Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a "code unit" (in UTF-16, code units are 2 bytes; in UTF-32 they are 4 bytes). "Code points" are composed of one or more code units, and combine in "grapheme clusters" which most closely approximate characters. @@ -187,7 +187,7 @@ Thus, even though you may index on bytes in a UTF-8 string, you can't access the The `str` type is UTF-8 because we observe more text in the wild in this encoding – particularly in network transmissions, which are endian-agnostic – and we think it's best that the default treatment of I/O not involve having to recode codepoints in each direction. -This does mean that locating a particular Unicode codepoint inside a string is an O(n) operation, although if the starting byte index is already known then they can be accessed in O(1) as expected. On the one hand, this is clearly undesirable; on the other hand, this problem is full of trade-offs and we'd like to point a few important qualifications: +This does mean that locating a particular Unicode codepoint inside a string is an O(n) operation, although if the starting byte index is already known then they can be accessed in O(1) as expected. On the one hand, this is clearly undesirable; on the other hand, this problem is full of trade-offs and we'd like to point out a few important qualifications: Scanning a `str` for ASCII-range codepoints can still be done safely byte-at-a-time. If you use `.as_bytes()`, pulling out a `u8` costs only `O(1)` and produces a value that can be cast and compared to an ASCII-range `char`. So if you're (say) line-breaking on `'\n'`, byte-based treatment still works. UTF8 was well-designed this way. @@ -203,9 +203,9 @@ For a more in-depth explanation of why UTF-8 is usually preferable over UTF-16 o If your reason for implementing these data structures is to use them for other programs, there's no need, as efficient implementations of these data structures are provided by the standard library. -If, however, [your reason is simply to learn](http://cglab.ca/~abeinges/blah/too-many-lists/book/), then you will likely need to dip into unsafe code. While these data structures _can_ be implemented entirely in safe Rust, the performance is likely to be worse than they would be with the use of unsafe code. The simple reason for this is that data structures like vectors and link lists rely on pointer and memory operations that are disallowed by safe Rust. +If, however, [your reason is simply to learn](http://cglab.ca/~abeinges/blah/too-many-lists/book/), then you will likely need to dip into unsafe code. While these data structures _can_ be implemented entirely in safe Rust, the performance is likely to be worse than it would be with the use of unsafe code. The simple reason for this is that data structures like vectors and linked lists rely on pointer and memory operations that are disallowed in safe Rust. -For example, a doubly-linked list requires that there be two mutable references to each node, but this violates Rust's mutable reference aliasing rules. You can solve this using `Weak`, but the performance will be poorer than you likely want. +For example, a doubly-linked list requires that there be two mutable references to each node, but this violates Rust's mutable reference aliasing rules. You can solve this using `Weak`, but the performance will be poorer than you likely want. With unsafe code you can bypass the mutable reference aliasing rule restriction, but must manually verify that your code introduces no memory safety violations. ### How can I iterate over a collection without moving/consuming it? @@ -219,7 +219,7 @@ for item in &v { println!("\nLength: {}", v.len()); ``` -The way Rust `for` loops work, they actually call `into_iter()` (which is defined in the `IntoIterator` trait) for whatever you are trying to iterate over. `IntoIterator` is implemented for `&Vec` and `&Vec`, meaning you can iterate over a vector without consuming it just be using `&v` or `&mut v` (for some vector `v`). The same is true for the other standard collections as well. +The way Rust `for` loops work, they actually call `into_iter()` (which is defined in the `IntoIterator` trait) for whatever you are trying to iterate over. `IntoIterator` is implemented for `&Vec` and `&mut Vec`, meaning you can iterate over a vector without consuming it by using `&v` or `&mut v` (for some vector `v`). The same is true for the other standard collections as well. ### Why do I need to type the array size in the array declaration? @@ -275,8 +275,7 @@ If a type implements the `Copy` trait, then it will be copied when passed to a f ### How do you deal with a "use of moved value" error? -This error means that the value you're trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary: if it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. Otherwise if the type being moved implements `Clone`, then calling `clone()` on it before -moving will move a copy of it, leaving the original still available for further use. Note though that cloning a value should typically be the last resort since cloning can be expensive, causing further allocations. +This error means that the value you're trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary: if it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. Otherwise if the type being moved implements `Clone`, then calling `clone()` on it before moving will move a copy of it, leaving the original still available for further use. Note though that cloning a value should typically be the last resort since cloning can be expensive, causing further allocations. If the moved value is of your own custom type, consider implementing `Copy` (for implicit copying, rather than moving) or `Clone` (explicit copying). `Copy` is most commonly implemented with `#[derive(Copy, Clone)]` (`Copy` requires `Clone`), and `Clone` with `#[derive(Clone)]`. @@ -318,11 +317,11 @@ You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/s ### Why lifetimes? -Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety garbage collection, which can have undesirable implications for performance. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). +Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety without garbage collection, which can have undesirable implications for performance. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). ### Why is the lifetime syntax the way it is? -The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticeable, and fit nicely in a type declaration right alonside traits and references. Alternative syntaxes have been discussed, but this seems to work just fine. +The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticeable, and fit nicely in a type declaration right alonside traits and references. Alternative syntaxes have been discussed, but this seems to work fine. ### When is `Rc` useful? @@ -356,15 +355,15 @@ You can do that with the [`Option`](https://doc.rust-lang.org/stable/std/option/

    Generics

    -### What is "monomorphization"? +### What is "monomorphisation"? -Monomorphisation is the process by which Rust translates to machine code specific instances of a generic function based on the parameter types of calls to that function. During monomorphisisation a new copy of the generic function is translated for each unique set of types the function is instantiated with. This strategy is the same as used by C++. It results in fast code that is specialized for every callsite and statically dispatched, with the tradeoff that functions instantiated with many different types can cause "code bloat", where multiple function instances result in larger binaries than would be created with other translation strategies. +Monomorphisation is the process by which Rust translates to machine code specific instances of a generic function based on the parameter types of calls to that function. During monomorphisisation a new copy of the generic function is translated for each unique set of types the function is instantiated with. This is the same strategy used by C++. It results in fast code that is specialized for every call-site and statically dispatched, with the tradeoff that functions instantiated with many different types can cause "code bloat", where multiple function instances result in larger binaries than would be created with other translation strategies. -Functions that accept [trait objects](http://doc.rust-lang.org/book/trait-objects.html) instead of type parameters do not undergo monomorphization. Instead, methods on the trait objects are dispatched dynamically at runtime. +Functions that accept [trait objects](http://doc.rust-lang.org/book/trait-objects.html) instead of type parameters do not undergo monomorphisation. Instead, methods on the trait objects are dispatched dynamically at runtime. ### What's the difference between a function and a closure that doesn't capture any variables? -Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the the struct can be called as a function. Bare functions can not capture an environment. +Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the struct can be called as a function. Bare functions can not capture an environment. The big difference between these traits is how they take the `self` parameter. `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. @@ -376,7 +375,7 @@ Let's go through these one by one: First, higher-kinded types are types that take other types as parameters. Type constructors, like `Vec` are examples. What support for higher-kinded types means is that you can use these type constructors wherever you can use types, such as in a trait `impl`. -Next, the lack of higher-kinded types makes expression of certain ideas far more tedious than it would otherwise be. For example, implementing a `Functor` trait (a math-y term for something which can be mapped over, obeying certain rules) without higher-kinded types is a pain. With higher-kinded types, it's as simple as (note: theoretical syntax, this does not actually work, and has no guarantee to be how higher-kinded types look when and if they're implemented): +Next, the lack of higher-kinded types makes expression of certain ideas far more tedious than it would otherwise be. For example, implementing a `Functor` trait (a term for something which can be mapped over, obeying certain rules) without higher-kinded types is a pain. With higher-kinded types, it's as simple as (note: theoretical syntax, this does not actually work, and has no guarantee to be how higher-kinded types look when and if they're implemented): ```rust trait Functor { @@ -504,7 +503,7 @@ It's probably an issue with the function's return type. The [`try!` macro](https ### Is there an easier way to do error handling than having `Result`s everywhere? -If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you want. `Result` is an indicator that some computation may or may not complete successfully. Requiring you to handle them is one of the ways that Rust encourages safety. If you really don't want to handle an error, use `unwrap()`, but know that doing so means that the given code will cause the entire process to panic on failure, which is usually undesirable. +If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you want. `Result` is an indicator that some computation may or may not complete successfully. Requiring you to handle these failures explicitly is one of the ways that Rust encourages safety. If you really don't want to handle an error, use `unwrap()`, but know that doing so means that the given code will cause the entire process to panic on failure, which is usually undesirable.

    Concurrency

    @@ -516,7 +515,7 @@ Yes, if the type implements `Sync`, doesn't implement `Drop`, and you don't try ### Can I write a macro to generate identifiers? -Not currently. Rust macros are so-called ["hygienic macros"](https://en.wikipedia.org/wiki/Hygienic_macro), which intentionally avoid capturing or creating identifiers that may cause name unexpected collisions with other identifiers. Their capabilities are significantly different than the style of macros commonly associated with the C preprocessor. Macro invocations can only appear in places where they are explicitly supported: items, methods declarations, statements, expressions, and patterns. Here, "method declarations" means a blank space where a method can be put. They can't be used to complete a partial method declaration. By the same logic, they can't be used to complete a partial variable declaration. +Not currently. Rust macros are ["hygienic macros"](https://en.wikipedia.org/wiki/Hygienic_macro), which intentionally avoid capturing or creating identifiers that may cause unexpected collisions with other identifiers. Their capabilities are significantly different than the style of macros commonly associated with the C preprocessor. Macro invocations can only appear in places where they are explicitly supported: items, method declarations, statements, expressions, and patterns. Here, "method declarations" means a blank space where a method can be put. They can't be used to complete a partial method declaration. By the same logic, they can't be used to complete a partial variable declaration.

    Debugging

    @@ -534,9 +533,9 @@ This error is usually caused by `unwrap()`ing a `None` or `Err` in client code. If you want to clone an existing slice safely, you can use `std::slice::clone_from_slice`. This function is currently unstable, but [should be stabilized soon](https://internals.rust-lang.org/t/stabilizing-basic-functions-on-arrays-and-slices/2868). -To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapping bytes, use `std::ptr::cpy_nonoverlapping`. Both of these functions are `unsafe`, as both can be used to subvert the language's safety guarantees. Use caution when using them. +To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapping bytes, use `std::ptr::cpy_nonoverlapping`. Both of these functions are `unsafe`, as both can be used to subvert the language's safety guarantees. Take care when using them. -### Can Rust reasonably function without the standard library? +### Can Rust function reasonably without the standard library? Absolutely. Rust programs can be set to not load the standard library using the `#![no_std]` attribute. With this attribute set, you can continue to use the Rust core library, which is nothing but the platform-agnostic primitives. As such, it doesn't include IO, concurrency, heap allocation, etc. Note however that `libcore` has not been stabilized. @@ -550,7 +549,7 @@ You should check out the [byteorder crate](http://burntsushi.net/rustdoc/byteord ### Does Rust guarantee a specific data layout? -Not by default. In the general case, `enum` and `struct` layout is undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested `enum`s, reordering fields to remove padding, etc. `enums` which carry no data ("C-like") are eligible to have a defined representation. Such `enums` are easily distinguished in that they are simply a list of names that carry no data: +Not by default. In the general case, `enum` and `struct` layouts are undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested `enum`s, reordering fields to remove padding, etc. `enums` which carry no data ("C-like") are eligible to have a defined representation. Such `enums` are easily distinguished in that they are simply a list of names that carry no data: ```rust enum CLike { @@ -703,7 +702,7 @@ Quoting the [official explanation](https://internals.rust-lang.org/t/crates-io-p The Rust language has been around for a number of years, and only reached version 1.0 in May of 2015. In the time before then the language changed significantly, and a number of StackOverflow answers were given at the time of older versions of the language. -Over time more and more answers will be offered for the current version, this improving this issue as the proportion of out-of-date answers is reduced. +Over time more and more answers will be offered for the current version, thus improving this issue as the proportion of out-of-date answers is reduced.

    Libraries

    @@ -791,7 +790,7 @@ Converting in the other direction can be done with a `match` statement, which ma ### Why does Rust not have a stable ABI like C does, and why do I have to annotate things with extern? -Committing to an ABI is a big thing, and can limit potentially advantageous language changes in the future. Given that Rust only hit 1.0 in May of 2015, it is still too early to make a commitment as big as a stable ABI. This does not mean that one won't happen in the future, though. +Committing to an ABI is a big decision that can limit potentially advantageous language changes in the future. Given that Rust only hit 1.0 in May of 2015, it is still too early to make a commitment as big as a stable ABI. This does not mean that one won't happen in the future, though. The `extern` keyword allows Rust to use specific ABI's, such as the well-defined C ABI, for interop with other languages. From 9da71ecb21c80fb99dd753db22a1b03e9090006c Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 2 Jan 2016 20:44:00 -0500 Subject: [PATCH 21/41] Updated answer about higher-kinded type support --- faq.md | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/faq.md b/faq.md index b4f9f2f4f..1389c4172 100644 --- a/faq.md +++ b/faq.md @@ -371,21 +371,11 @@ In the end, functions and closures are operationally equivalent, but have differ ### What are higher-kinded types, why would I want them, and why doesn't Rust have them? -Let's go through these one by one: +Higher-kinded types are types with unfilled parameters. Support for higher-kinded types means "incomplete" types may be used anywhere "complete" types can be used, such as in a trait `impl`. -First, higher-kinded types are types that take other types as parameters. Type constructors, like `Vec` are examples. What support for higher-kinded types means is that you can use these type constructors wherever you can use types, such as in a trait `impl`. +The lack of support for higher-kinded types makes expression of certain ideas more tedious than it would otherwise be. For example, implementing a `Functor` trait (a term for a container which can be mapped over, obeying certain rules) without higher-kinded types would be difficult, as a `Functor` should be implemented for the container regardless of the type of values it contains (that is, the `impl` should leave the containers type parameter unfilled, with no concrete type). -Next, the lack of higher-kinded types makes expression of certain ideas far more tedious than it would otherwise be. For example, implementing a `Functor` trait (a term for something which can be mapped over, obeying certain rules) without higher-kinded types is a pain. With higher-kinded types, it's as simple as (note: theoretical syntax, this does not actually work, and has no guarantee to be how higher-kinded types look when and if they're implemented): - -```rust -trait Functor { - fn fmap B>(&self, f: F) -> Self; -} -``` - -The part that Rust currently can't do is that `Self` above is a type constructor parameterized by another type constructor. This is what support for higher-kinded types would let you express. - -Finally, Rust doesn't currently have them simply because they haven't been a priority. There is nothing inherent to the language that stops us from implementing higher-kinded types, it just hasn't been done yet. There is an open RFC for implementing them, but no real proposal exists yet. If one comes around, it will definitely be considered. +Rust doesn't currently have them simply because they haven't been a priority. There is nothing inherent to the language that stops us from implementing support for higher-kinded types, it just hasn't been done yet. ### What do named type parameters like `` in generic types mean? From 20c365fb3b68392399e16fb3a946427442629046 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 2 Jan 2016 20:50:38 -0500 Subject: [PATCH 22/41] Clarified answer on Ord/PartialOrd and Eq/PartialEq split --- faq.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/faq.md b/faq.md index 1389c4172..9a2318103 100644 --- a/faq.md +++ b/faq.md @@ -439,7 +439,9 @@ The following operators can be overloaded: ### Why the split between `Eq`/`PartialEq` and `Ord`/`PartialOrd`? -There are some types in Rust whose values are only partially ordered, or have only partial equality. This means that there are values which are not less than or greater than each other, or values which are not equal to themselves, respectively. The floating point types `f32` and `f64` are examples of this. Because a floating point value may be `NaN`, and because `NaN`s aren't equal to any other floating point type, nor less than or greater to any other floating point type, nor equal to each other, these types _can't_ implement `Eq` and `Ord`, although they _can_ implement `PartialEq` and `PartialOrd`. +There are some types in Rust whose values are only partially ordered, or have only partial equality. Partial ordering means that there may be values of the given type that are neither less than nor greater than each other. Partial equality means that there may be values of the given type that are not equal to themselves. + +Floating point types (`f32` and `f64`) are good examples of each. Any floating point type may have the value `NaN` (meaning "not a number") `NaN` is not equal to itself (`NaN == Nan` is false), and not less than or greater than any other floating point value. As such, both `f32` and `f64` implement `PartialOrd` and `PartialEq` but not `Ord` and not `Eq`.

    Input / Output

    From 095d45c0ffaf93854b73282a27c2cfdf235e328f Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 2 Jan 2016 20:55:44 -0500 Subject: [PATCH 23/41] Updated borrow checker answer --- faq.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/faq.md b/faq.md index 9a2318103..4acdfda17 100644 --- a/faq.md +++ b/faq.md @@ -289,14 +289,14 @@ If none of these are possible, you may want to modify the function that acquired ### How can I understand the borrow checker? -There is a certain desire to act as if the borrow checker is some mysterious zen master, doling out knocks on the head whenever its koans are misunderstood. The reality is a little different. In fact, the borrow checker applies only a few straightforward rules, which can be found in the Rust book's [section on borrowing](https://doc.rust-lang.org/stable/book/references-and-borrowing.html#the-rules): +The borrow checker applies only a few rules, which can be found in the Rust book's [section on borrowing](https://doc.rust-lang.org/stable/book/references-and-borrowing.html#the-rules), when evaluating Rust code. These rules are: > First, any borrow must last for a scope no greater than that of the owner. Second, you may have one or the other of these two kinds of borrows, but not both at the same time: > > - one or more references (&T) to a resource. > - exactly one mutable reference (&mut T) -Understanding these rules and [lifetimes](https://doc.rust-lang.org/stable/book/lifetimes.html) is all you need to do to understand the borrow checker. +While the rules themselves are simple, making sure your code conforms to them can be complicated. It is easy to attempt to borrow a value for longer than its lifetime, or to introduce two mutable references to the same value. The borrow checker is useful because it verifies that your code follows these rules, and helps guide corrections when the code doesn't. Many new Rust programmers struggle to satisfy the borrow checker at first, but over time become more skilled at writing memory safe code with minimal borrow checker intervention. ### How do deref coercions work? From 7721973702db58ec71960d45bc407a4f6eacaeb6 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sun, 3 Jan 2016 11:36:47 -0500 Subject: [PATCH 24/41] Typo fixes --- faq.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/faq.md b/faq.md index 4acdfda17..21963e1c4 100644 --- a/faq.md +++ b/faq.md @@ -77,7 +77,7 @@ You can run benchmarks, but only on the nightly channel. Rust's benchmarking mec ### Does Rust do tail-call optimization? -Not generally, no. Tail-call optimization may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), but is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html). As the feature has always been desired Rust has a keyword (`become`) reserved, though it is not clear yet whether it is technically possible, nor whether it will be implemented. There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. +Not generally, no. Tail-call optimization may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), but is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html). As the feature has always been desired, Rust has a keyword (`become`) reserved, though it is not clear yet whether it is technically possible, nor whether it will be implemented. There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. ### Does Rust have a runtime? @@ -93,7 +93,7 @@ Curly braces also allow for more flexible syntax for the programmer, a simpler p ### I can leave out parentheses on `if` conditions, so why do I have to put brackets around single line blocks? Why is the C style not allowed? -Whereas C requires mandatory parantheses for `if`-statements but leaveis brackets optional, Rust makes the opposite choice. Rust's `if`-expressions thus require strictly fewer delimiters than their C counterparts. Furthermore, the optional brackets on C's `if`-statements are well-understood as a hazard to maintenance and refactoring. +Whereas C requires mandatory parantheses for `if`-statements but leaves brackets optional, Rust makes the opposite choice. Rust's `if`-expressions thus require strictly fewer delimiters than their C counterparts. Furthermore, the optional brackets on C's `if`-statements are well-understood as a hazard to maintenance and refactoring. ### Why is there no literal syntax for dictionaries? @@ -146,7 +146,7 @@ There [is a crate](https://crates.io/crates/ordered-float) that provides a total ### How can I convert between numeric types? -There are two ways: the `as` keyword, which does simple casting for primitive types, and the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types). The `Into` and `From` traits are only implemented in cases where conversions are lossless, so for example, `f64::from(0f32)` will compile while `f32:from(0f64)` will not. `as` on the other hand will convert between any two primitive types, truncating values as necessary. +There are two ways: the `as` keyword, which does simple casting for primitive types, and the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types). The `Into` and `From` traits are only implemented in cases where conversions are lossless, so for example, `f64::from(0f32)` will compile while `f32:from(0f64)` will not. On the other hand, `as` will convert between any two primitive types, truncating values as necessary.

    Strings

    From 435b1def1921bb0d12e4c38324993ac2fc07969e Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sun, 3 Jan 2016 11:56:37 -0500 Subject: [PATCH 25/41] Addressed charlotteis' suggestions --- faq.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/faq.md b/faq.md index 21963e1c4..87a6ce30a 100644 --- a/faq.md +++ b/faq.md @@ -55,7 +55,7 @@ Additionally, garbage collection is frequently a source of non-deterministic beh The Rust compiler doesn't compile with optimizations unless asked to, as optimizations slow down compilation and are usually undesirable during development. -If you compile with `cargo`, use the `--release` flag. If you compile with `rustc` directly, use the `-O` flag. Either of these will turn on optimizations. +If you compile with `cargo`, use the `--release` flag. If you compile with `rustc` directly, use the `-O` flag. Either of these will turn on optimizations. Optimizations are not turned on by default because they [slow down compilation and complicate debugging](https://users.rust-lang.org/t/why-does-cargo-build-not-optimise-by-default/4150/3?u=andrewbrinker). ### Why is Rust compilation slow? @@ -379,7 +379,7 @@ Rust doesn't currently have them simply because they haven't been a priority. Th ### What do named type parameters like `` in generic types mean? -These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a simple `where` clause. In essence, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. +These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a `where` clause. In essence, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. ### Can I override operators? Which ones and how? @@ -776,7 +776,7 @@ Rust does not have `static` fields as shown in the code snippet above. Instead, ### How can I convert a C-style enum to an integer, or vice-versa? -Converting a C-style enum to an integer can be done with a simple `as` expression, like `e as i64` (where `e` is some enum). +Converting a C-style enum to an integer can be done with an `as` expression, like `e as i64` (where `e` is some enum). Converting in the other direction can be done with a `match` statement, which maps different numeric values to different potential values for the enum. @@ -788,7 +788,7 @@ The `extern` keyword allows Rust to use specific ABI's, such as the well-defined ### Can Rust code call C code? -Yes. Calling C code from Rust is simple and exactly as efficient as calling C code from C. +Yes. Calling C code from Rust is designed to be as efficient as calling C code from C++. ### Can C code call Rust code? @@ -814,7 +814,7 @@ Rust "move"s are about transferring ownership, rather than eliminating mutable a ### How can I interoperate with C++ from Rust, or with Rust from C++? -The simplest way is to interoperate through C. Both Rust and C++ provide a [foreign function interface](https://doc.rust-lang.org/book/ffi.html) for C, and can use that to communicate between each other. If writing C bindings is too tedious, you can always use [rust-bindgen](https://github.com/crabtw/rust-bindgen) to help automatically generate workable C bindings. +Rust and C++ can interoperate through C. Both Rust and C++ provide a [foreign function interface](https://doc.rust-lang.org/book/ffi.html) for C, and can use that to communicate between each other. If writing C bindings is too tedious, you can always use [rust-bindgen](https://github.com/crabtw/rust-bindgen) to help automatically generate workable C bindings. ### Does Rust have C++-style constructors? From 601a473050b1e767f08a8289d358dff13fe0b0f5 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sun, 3 Jan 2016 12:31:27 -0500 Subject: [PATCH 26/41] Small fixes --- faq.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/faq.md b/faq.md index 87a6ce30a..4e43f721f 100644 --- a/faq.md +++ b/faq.md @@ -53,9 +53,9 @@ Additionally, garbage collection is frequently a source of non-deterministic beh ### Why is my program slow? -The Rust compiler doesn't compile with optimizations unless asked to, as optimizations slow down compilation and are usually undesirable during development. +The Rust compiler doesn't compile with optimizations unless asked to, [as optimizations slow down compilation and are usually undesirable during development](https://users.rust-lang.org/t/why-does-cargo-build-not-optimise-by-default/4150/3). -If you compile with `cargo`, use the `--release` flag. If you compile with `rustc` directly, use the `-O` flag. Either of these will turn on optimizations. Optimizations are not turned on by default because they [slow down compilation and complicate debugging](https://users.rust-lang.org/t/why-does-cargo-build-not-optimise-by-default/4150/3?u=andrewbrinker). +If you compile with `cargo`, use the `--release` flag. If you compile with `rustc` directly, use the `-O` flag. Either of these will turn on optimizations. ### Why is Rust compilation slow? @@ -513,7 +513,7 @@ Not currently. Rust macros are ["hygienic macros"](https://en.wikipedia.org/wiki ### How do I debug Rust programs? -Rust programs can be debugged using gdb or lldb, same as C and C++. In fact, every Rust installation comes with rust-gdb and rust-lldb, wrappers over gdb and lldb with Rust pretty-printing enabled. +Rust programs can be debugged using [gdb](http://sourceware.org/gdb/current/onlinedocs/gdb/) or [lldb](http://lldb.llvm.org/tutorial.html), same as C and C++. In fact, every Rust installation comes with rust-gdb and rust-lldb, wrappers over gdb and lldb with Rust pretty-printing enabled. ### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? From ef9715aa610a31985c96a97dd26c9cfc419c1810 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sun, 3 Jan 2016 17:11:36 -0500 Subject: [PATCH 27/41] Changed to 4-space indent in code samples --- faq.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/faq.md b/faq.md index 4e43f721f..32b651477 100644 --- a/faq.md +++ b/faq.md @@ -160,12 +160,12 @@ The `to_owned()` method converts from a `&str` into a `String`, and `String`s ar ```rust fn main() { - let s = "Jane Doe".to_owned(); - say_hello(&s); + let s = "Jane Doe".to_owned(); + say_hello(&s); } fn say_hello(name: &str) { - println!("Hello {}!", name); + println!("Hello {}!", name); } ``` From 123c8033d3fbb238447e4a324f56cb2a126f57a1 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Mon, 4 Jan 2016 16:52:40 -0500 Subject: [PATCH 28/41] Updated based on tshepang's latest feedback --- faq.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/faq.md b/faq.md index 32b651477..5765c3ebc 100644 --- a/faq.md +++ b/faq.md @@ -317,7 +317,7 @@ You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/s ### Why lifetimes? -Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety without garbage collection, which can have undesirable implications for performance. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). +Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ensure memory safety without the performance costs of garbage collection. They are based on a variety of academic work, which can be found in the [Rust book](https://doc.rust-lang.org/stable/book/academic-research.html#type-system). ### Why is the lifetime syntax the way it is? @@ -333,7 +333,7 @@ You need to ensure that the borrowed item will outlive the function. This can be ### How do I return a closure from a function? -To return a closure from a function, it must be a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own copy of the captured variables, independent of its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer valid (put another way, it would allow reading potentially invalid memory). The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). +To return a closure from a function, it must be a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own copy of the captured variables, independent of its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer valid; put another way: it would allow reading potentially invalid memory. The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). ### When are lifetimes required to be defined? @@ -373,7 +373,7 @@ In the end, functions and closures are operationally equivalent, but have differ Higher-kinded types are types with unfilled parameters. Support for higher-kinded types means "incomplete" types may be used anywhere "complete" types can be used, such as in a trait `impl`. -The lack of support for higher-kinded types makes expression of certain ideas more tedious than it would otherwise be. For example, implementing a `Functor` trait (a term for a container which can be mapped over, obeying certain rules) without higher-kinded types would be difficult, as a `Functor` should be implemented for the container regardless of the type of values it contains (that is, the `impl` should leave the containers type parameter unfilled, with no concrete type). +The lack of support for higher-kinded types makes expression of certain ideas more tedious than it would otherwise be. For example, implementing a `Functor` trait (a term for a container which can be mapped over, obeying certain rules) without higher-kinded types would be difficult, as a `Functor` should be implemented for the container regardless of the type of values it contains. With higher-kinded types, the Functor `impl` for some container could leave the container's type parameter unfilled, with no concrete type. Rust doesn't currently have them simply because they haven't been a priority. There is nothing inherent to the language that stops us from implementing support for higher-kinded types, it just hasn't been done yet. @@ -441,7 +441,7 @@ The following operators can be overloaded: There are some types in Rust whose values are only partially ordered, or have only partial equality. Partial ordering means that there may be values of the given type that are neither less than nor greater than each other. Partial equality means that there may be values of the given type that are not equal to themselves. -Floating point types (`f32` and `f64`) are good examples of each. Any floating point type may have the value `NaN` (meaning "not a number") `NaN` is not equal to itself (`NaN == Nan` is false), and not less than or greater than any other floating point value. As such, both `f32` and `f64` implement `PartialOrd` and `PartialEq` but not `Ord` and not `Eq`. +Floating point types (`f32` and `f64`) are good examples of each. Any floating point type may have the value `NaN` (meaning "not a number"). `NaN` is not equal to itself (`NaN == Nan` is false), and not less than or greater than any other floating point value. As such, both `f32` and `f64` implement `PartialOrd` and `PartialEq` but not `Ord` and not `Eq`.

    Input / Output

    @@ -451,17 +451,17 @@ Using the `read_to_string()` method, which is defined on the `Read` trait in `st ```rust fn read_file(path: &str) -> Result { - let mut f = try!(File::open(path)); - let mut s = String::new(); - try!(f.read_to_string(&mut s)); // `s` contains the contents of "foo.txt" - s + let mut f = try!(File::open(path)); + let mut s = String::new(); + try!(f.read_to_string(&mut s)); // `s` contains the contents of "foo.txt" + s } fn main() { - match read_file("foo.txt") { - Ok(_) => println!("Got file contents!"), - Err(err) => println!("Getting file contents failed with error: {}", err) - }; + match read_file("foo.txt") { + Ok(_) => println!("Got file contents!"), + Err(err) => println!("Getting file contents failed with error: {}", err) + }; } ``` @@ -517,7 +517,7 @@ Rust programs can be debugged using [gdb](http://sourceware.org/gdb/current/onli ### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? -This error is usually caused by `unwrap()`ing a `None` or `Err` in client code. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build` is also helpful). Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful. +This error is usually caused by `unwrap()`ing a `None` or `Err` in client code. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build`) is also helpful. Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful.

    Low-Level

    @@ -529,7 +529,7 @@ To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapp ### Can Rust function reasonably without the standard library? -Absolutely. Rust programs can be set to not load the standard library using the `#![no_std]` attribute. With this attribute set, you can continue to use the Rust core library, which is nothing but the platform-agnostic primitives. As such, it doesn't include IO, concurrency, heap allocation, etc. Note however that `libcore` has not been stabilized. +Absolutely. Rust programs can be set to not load the standard library using the `#![no_std]` attribute. With this attribute set, you can continue to use the Rust core library, which is nothing but the platform-agnostic primitives. As such, it doesn't include IO, concurrency, heap allocation, etc. ### Can I write an operating system in Rust? @@ -643,7 +643,7 @@ A `use`ing declaration just tells the compiler to bring everything from a partic As explained on the Cargo [configuration documentation](http://doc.crates.io/config.html), you can set Cargo to use a proxy by setting the "proxy" variable under `[http]` in the configuration file. -### Why can't the compiler find the method implementation even through I'm already `use`ing the crate? +### Why can't the compiler find the method implementation even though I'm already `use`ing the crate? For methods defined on a trait, you have to explicitly import the trait declaration. This means it's not enough to import a module where a struct implements the trait, you must also import the trait itself. From 1c3a038834dc623157bad05e44bae8d37d019ed1 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Mon, 4 Jan 2016 16:53:54 -0500 Subject: [PATCH 29/41] More corrections based on tshepang's feedback --- faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/faq.md b/faq.md index 5765c3ebc..9ba91d5c6 100644 --- a/faq.md +++ b/faq.md @@ -764,7 +764,7 @@ Rust has consistently worked to avoid having features with overlapping purposes, ### Does Rust allow non-constant-expression values for globals? -No. Globals can not have a non-constant-expression constructor and cannot have a destructor at all. Static constructors are undesirable because portably ensuring a static initialization order is difficult. Life before main is often considered a misfeature so Rust does not allow it. +No. Globals cannot have a non-constant-expression constructor and cannot have a destructor at all. Static constructors are undesirable because portably ensuring a static initialization order is difficult. Life before main is often considered a misfeature, so Rust does not allow it. See the [C++ FQA](http://yosefk.com/c++fqa/ctors.html#fqa-10.12) about the "static initialization order fiasco", and [Eric Lippert's blog](http://ericlippert.com/2013/02/06/static-constructors-part-one/) for the challenges in C#, which also has this feature. From 3425bdd58174e31fa6a9d31346ee934c6507b66e Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Mon, 4 Jan 2016 18:43:33 -0500 Subject: [PATCH 30/41] Integrated latest feedback from tshepang --- faq.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/faq.md b/faq.md index 9ba91d5c6..7812993fc 100644 --- a/faq.md +++ b/faq.md @@ -804,7 +804,7 @@ Rust was designed from day one to be a safe systems programming language, which Rust doesn't currently have an exact equivalent to template specialization, but it is [being worked on](https://github.com/rust-lang/rfcs/pull/1210) and will hopefully be added soon. However, similar effects can be achieved via [associated types](https://doc.rust-lang.org/stable/book/associated-types.html). -### How does Rust's ownership system related to move semantics in C++? +### How does Rust's ownership system relate to move semantics in C++? The notions of a "move" in Rust and a "move" in C++ are quite different, owing to the different systems in which they exist. @@ -824,7 +824,7 @@ No. Functions serve the same purpose as constructors without adding language com struct Foo { a: i32, b: f64, - c: bool + c: bool, } impl Foo { @@ -832,7 +832,7 @@ impl Foo { Foo { a: 0, b: 0.0, - c: false + c: false, } } } @@ -854,10 +854,10 @@ In Swift, `?` is used to indicate an optional value. This is already done by `Op Rust and Go have substantially different design goals. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones: -- Rust is lower level than Go, comparable with C and C++. It provides access to memory management primitives that do not exist in Go (which has a garbage collector) -- Rust's focus is on ensuring safety and efficiency while also providing high-level affordances, while Go's is on being a small, simple language which compiles quickly and can work nicely with a variety of tools -- Rust has strong support for generics, which Go does not -- Rust has strong influences from the world of functional programming, including a type system which draws from Haskell's typeclasses. Go has a simpler type system, using interfaces for basic generic programming +- Rust is lower level than Go, comparable with C and C++. It provides access to memory management primitives that do not exist in Go (which has a garbage collector). +- Rust's focus is on ensuring safety and efficiency while also providing high-level affordances, while Go's is on being a small, simple language which compiles quickly and can work nicely with a variety of tools. +- Rust has strong support for generics, which Go does not. +- Rust has strong influences from the world of functional programming, including a type system which draws from Haskell's typeclasses. Go has a simpler type system, using interfaces for basic generic programming. ### `gofmt` is great. Where's `rustfmt`? @@ -883,7 +883,7 @@ You can report issues in the Rust documentation on the Rust compiler [issue trac ### How do I view rustdoc documentation for a library my project depends on? -When you use `cargo doc` to generate documentation for your own project, it also generates docs for the active dependency versions. These are put into the `target/doc` directory of your project. Use `cargo doc --open` to open the docs after building them, or just open up `target/doc/index.html` yourself after building the docs. +When you use `cargo doc` to generate documentation for your own project, it also generates docs for the active dependency versions. These are put into the `target/doc` directory of your project. Use `cargo doc --open` to open the docs after building them, or just open up `target/doc/index.html` yourself.

    The Rust Project

    @@ -898,7 +898,7 @@ Rust exists because other languages at this level of abstraction and efficiency 3. There is a lack of practical affordances. 4. They offer limited control over resources. -Rust exists as alternative language that provides both efficient code and a comfortable level of abstraction, while improving on all four of these points. +Rust exists as an alternative that provides both efficient code and a comfortable level of abstraction, while improving on all four of these points. ### Is this project controlled by Mozilla? From c374cbb5b4cb166d4b53941eae01d1151702af0d Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Thu, 7 Jan 2016 18:16:47 -0500 Subject: [PATCH 31/41] First pass with new feedback --- faq.md | 143 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 45 deletions(-) diff --git a/faq.md b/faq.md index 7812993fc..8b780204b 100644 --- a/faq.md +++ b/faq.md @@ -57,21 +57,29 @@ The Rust compiler doesn't compile with optimizations unless asked to, [as optimi If you compile with `cargo`, use the `--release` flag. If you compile with `rustc` directly, use the `-O` flag. Either of these will turn on optimizations. -### Why is Rust compilation slow? +### Rust compilation seems slow. Why is that? Code translation and optimizations. Rust provides high level abstractions that compile down into efficient machine code, and those translations take time to run, especially when optimizing. But Rust's compilation time is not as bad as it may seem, and there is reason to believe it will improve. When comparing projects of similar size between C++ and Rust, compilation time of the entire project is generally believed to be comparable. The common perception that Rust compilation is slow is in large part due to the differences in the *compilation model* between C++ and Rust: C++'s compilation unit is the file, while Rust's is the crate, composed of many files. Thus, during development, modifying a single C++ file can result in much less recompilation than in Rust. There is a major effort underway to refactor the compiler to introduce [incremental compilation](https://github.com/rust-lang/rfcs/blob/master/text/1298-incremental-compilation.md), which will provide Rust the compile time benefits of C++'s model. -Aside from the compilation model, there are several other aspects of Rust's language design and compiler implementation that affect compile-time performance. First, Rust has a moderately-complex type system, and must spend a non-negligible amount of compile time enforcing the constraints that make Rust safe at runtime. Secondly, Rust's use of LLVM for code generation is a double-edged sword: while it enables Rust to have world-class runtime performance, LLVM is a large framework that is not focused on compile-time performance. Thirdly, the Rust compiler suffers from long-standing technical debt, and notably generates poor-quality LLVM IR which LLVM must spend time "fixing". There is hope that future [MIR-based](https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md) optimization and translation passes will ease the burden the Rust compiler places on LLVM. Finally, while Rust's preferred strategy of monomorphising generics (ala C++) produces fast code, it demands that significantly more code be generated than other translation strategies. +Aside from the compilation model, there are several other aspects of Rust's language design and compiler implementation that affect compile-time performance. + +First, Rust has a moderately-complex type system, and must spend a non-negligible amount of compile time enforcing the constraints that make Rust safe at runtime. + +Secondly, the Rust compiler suffers from long-standing technical debt, and notably generates poor-quality LLVM IR which LLVM must spend time "fixing". There is hope that future [MIR-based](https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md) optimization and translation passes will ease the burden the Rust compiler places on LLVM. + +Thirdly, Rust's use of LLVM for code generation is a double-edged sword: while it enables Rust to have world-class runtime performance, LLVM is a large framework that is not focused on compile-time performance, particularly when working with poor-quality inputs. + +Finally, while Rust's preferred strategy of monomorphising generics (ala C++) produces fast code, it demands that significantly more code be generated than other translation strategies. ### Why are Rust's `HashMap`s slow? By default, Rust's `HashMap` uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). -While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges/blah/hash-rs/) in many cases, one case where it is notably slower than other hashing algorithms is with short keys, such as integers. This is why Rust programmers often observe slow performance with `HashMap`. The [FNV hasher](https://crates.io/crates/fnv) is frequently recommended for these cases, but be aware that it does not have the same collision-resistence properties as SipHash. +While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges/blah/hash-rs/) in many cases, one case where it is notably slower than other hashing algorithms is with short keys, such as integers. This is why Rust programmers often observe slow performance with `HashMap`. The [FNV hasher](https://crates.io/crates/fnv) is frequently recommended for these cases, but be aware that it does not have the same collision-resistance properties as SipHash. -### Why can't I run benchmarks? +### Why is there no integrated benchmarking infrastructure? You can run benchmarks, but only on the nightly channel. Rust's benchmarking mechanism is currently unstable, as the API has not been deemed ready for stabilization. This [may change in the future](https://github.com/rust-lang/rust/issues/29553), but until then benchmarking can only be used on nightly. @@ -81,11 +89,11 @@ Not generally, no. Tail-call optimization may be done in [limited circumstances] ### Does Rust have a runtime? -Not in the typical sense used by languages such as Java, but parts of the Rust standard library can be considered a "runtime", providing a heap, backtraces, unwinding, and stack guards. There is a [small amount of initialization code](https://github.com/rust-lang/rust/blob/33916307780495fe311fe9c080b330d266f35bfb/src/libstd/rt.rs#L43) that runs before the user's `main` function. The Rust standard library additionally links to the the C standard library, which does similar [runtime initialization](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html). Rust code can be compiled without the standard library, in which case there is no runtime at all. +Not in the typical sense used by languages such as Java, but parts of the Rust standard library can be considered a "runtime", providing a heap, backtraces, unwinding, and stack guards. There is a [small amount of initialization code](https://github.com/rust-lang/rust/blob/33916307780495fe311fe9c080b330d266f35bfb/src/libstd/rt.rs#L43) that runs before the user's `main` function. The Rust standard library additionally links to the the C standard library, which does similar [runtime initialization](http://www.embecosm.com/appnotes/ean9/html/ch05s02.html). Rust code can be compiled without the standard library, in which case the runtime is roughly equivalent to C's.

    Syntax

    -### Why curly braces? Why can't everything be like Haskell/Python? +### Why curly braces? Why can't Rust's syntax be like Haskell's or Python's? Use of curly braces to denote blocks is a common design choice in a variety of programming languages, and Rust's consistency is useful for people already familiar with the style. @@ -93,23 +101,23 @@ Curly braces also allow for more flexible syntax for the programmer, a simpler p ### I can leave out parentheses on `if` conditions, so why do I have to put brackets around single line blocks? Why is the C style not allowed? -Whereas C requires mandatory parantheses for `if`-statements but leaves brackets optional, Rust makes the opposite choice. Rust's `if`-expressions thus require strictly fewer delimiters than their C counterparts. Furthermore, the optional brackets on C's `if`-statements are well-understood as a hazard to maintenance and refactoring. +Whereas C requires mandatory parentheses for `if`-statement conditionals but leaves brackets optional, Rust makes the opposite choice for its `if`-expressions. This keeps the conditional clearly separate from the body and avoids the hazard of optional brackets, which can lead to easy-to-miss errors during refactoring. ### Why is there no literal syntax for dictionaries? -The reason Rust does not have syntax for initializing dictionaries — or collections in general — is due to Rust's overall design preference for limiting the size of the *language* while enabling powerful *libraries*. The only type of collection that Rust has direct syntax for initializing is the array type, which is also the only type of collection built into the language. Note that Rust does not even have syntax for initializing the common `Vec` collection type, instead the standard library defins the [`vec!`](http://doc.rust-lang.org/std/macro.vec!.html) macro. +The reason Rust does not have syntax for initializing dictionaries — or collections in general — is due to Rust's overall design preference for limiting the size of the *language* while enabling powerful *libraries*. The only type of collection that Rust has direct syntax for initializing is the array type, which is also the only type of collection built into the language. Note that Rust does not even have syntax for initializing the common `Vec` collection type, instead the standard library defines the [`vec!`](http://doc.rust-lang.org/std/macro.vec!.html) macro. This design choice of using Rust's macro facilities to initialize collections will likely be extended generically to other collections in the future, enabling simple initialization of not only `HashMap` and `Vec`, but also other collection types such as [`BTreeMap`](http://doc.rust-lang.org/collections/struct.BTreeMap.html). In the meantime, if you want a more convenient syntax for initializing collections, you can [create your own macro](http://stackoverflow.com/questions/27582739/how-do-i-create-a-hashmap-literal) to provide it. ### When should I use an implicit return? -Implicit returns are simply a coding style option, and can be used anywhere they make sense. While early returns require an explicit `return`, any other return can be made implicit according to your preferences or the preferences of your project. In the Rust project itself, the style guidelines lean toward preferring implicit returns. +Implicit returns are simply a coding style option, and can be used as the final line in a block expression. While early returns require an explicit `return` keyword, any other return can be made implicit according to your preferences or the preferences of your project. In the Rust project itself, the style guidelines lean toward preferring implicit returns. ### Why aren't function signatures inferred? -- Mechanically, it simplifies the inference algorithm, as inference only requires looking at one function at a time. - Mandatory function signatures help enforce interface stability at both the module and crate level. - It improves code comprehension for the programmer, eliminating the need for an IDE running an inference algorithm across an entire crate to be able to guess at a function's argument types; it's always explicit and nearby. +- Mechanically, it simplifies the inference algorithm, as inference only requires looking at one function at a time. ### Why does `match` have to be exhaustive? @@ -130,7 +138,7 @@ match val.do_something() { The choice of which to use is dependent on the purpose of the program. -If you are interested in the greatest degree of precision with your floating point numbers, then prefer `f64`. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated innacuracy of having fewer bits per value, then `f32` is better. Operations on `f32` are usually faster, even on 64-bit hardware. As a common example, graphics programming typically uses `f32` because it requires high performance, and 32-bit floats are sufficient for representing pixels on the screen. +If you are interested in the greatest degree of precision with your floating point numbers, then prefer `f64`. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated inaccuracy of having fewer bits per value, then `f32` is better. Operations on `f32` are usually faster, even on 64-bit hardware. As a common example, graphics programming typically uses `f32` because it requires high performance, and 32-bit floats are sufficient for representing pixels on the screen. If in doubt, choose `f64` for the greater precision. @@ -179,7 +187,7 @@ fn say_hello(name: &str) { You cannot. At least not without a firm understanding of what you mean by "character", and preprocessing the string to find the index of the desired character. -Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a "code unit" (in UTF-16, code units are 2 bytes; in UTF-32 they are 4 bytes). "Code points" are composed of one or more code units, and combine in "grapheme clusters" which most closely approximate characters. +Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a "code unit" (in UTF-16, code units are 2 bytes; in UTF-32 they are 4 bytes). "Code points" are composed of one or more code units, and combine in "grapheme clusters" which most closely approximate characters. Thus, even though you may index on bytes in a UTF-8 string, you can't access the `i`th code point or grapheme cluster in constant time. However, if you know at which byte that desired code point or grapheme cluster begins, then you _can_ access it in constant time. Functions including `str::find()` and regex matches return byte indices, facilitating this sort of access. @@ -189,7 +197,7 @@ The `str` type is UTF-8 because we observe more text in the wild in this encodin This does mean that locating a particular Unicode codepoint inside a string is an O(n) operation, although if the starting byte index is already known then they can be accessed in O(1) as expected. On the one hand, this is clearly undesirable; on the other hand, this problem is full of trade-offs and we'd like to point out a few important qualifications: -Scanning a `str` for ASCII-range codepoints can still be done safely byte-at-a-time. If you use `.as_bytes()`, pulling out a `u8` costs only `O(1)` and produces a value that can be cast and compared to an ASCII-range `char`. So if you're (say) line-breaking on `'\n'`, byte-based treatment still works. UTF8 was well-designed this way. +Scanning a `str` for ASCII-range codepoints can still be done safely byte-at-a-time. If you use `.as_bytes()`, pulling out a `u8` costs only `O(1)` and produces a value that can be cast and compared to an ASCII-range `char`. So if you're (say) line-breaking on `'\n'`, byte-based treatment still works. UTF-8 was well-designed this way. Most "character oriented" operations on text only work under very restricted language assumptions such as "ASCII-range codepoints only". Outside ASCII-range, you tend to have to use a complex (non-constant-time) algorithm for determining linguistic-unit (glyph, word, paragraph) boundaries anyway. We recommend using an "honest" linguistically-aware, Unicode-approved algorithm. @@ -209,7 +217,7 @@ For example, a doubly-linked list requires that there be two mutable references ### How can I iterate over a collection without moving/consuming it? -The easiest way is by using the collection's `IntoIterator` implementation. Here is an example for `Vec`: +The easiest way is by using the collection's `IntoIterator` implementation. Here is an example for `&Vec`: ```rust let v = vec![1,2,3,4,5]; @@ -219,7 +227,9 @@ for item in &v { println!("\nLength: {}", v.len()); ``` -The way Rust `for` loops work, they actually call `into_iter()` (which is defined in the `IntoIterator` trait) for whatever you are trying to iterate over. `IntoIterator` is implemented for `&Vec` and `&mut Vec`, meaning you can iterate over a vector without consuming it by using `&v` or `&mut v` (for some vector `v`). The same is true for the other standard collections as well. +Rust `for` loops call `into_iter()` (defined on the `IntoIterator` trait) for whatever they're iterating over. Anything implementing the `IntoIterator` trait may be looped over with a `for` loop. `IntoIterator` is implemented for `&Vec` and `&mut Vec`, causing the iterator from `into_iter()` to borrow the contents of the collection, rather than moving/consuming them. The same is true for other standard collections as well. + +If a moving/consuming iterator is desired, write the `for` loop without `&` or `&mut` on the collection. ### Why do I need to type the array size in the array declaration? @@ -231,13 +241,14 @@ One thing to note is that currently Rust doesn't offer generics over arrays of d ### How can I implement a graph or other data structure that contains cycles? -There are three major options: +There are four major options: - You can implement it using `Rc` and `Weak` to allow shared ownership of nodes, although this approach pays the cost of memory management. - You can implement it using `unsafe` code using raw pointers. This will be more efficient, but bypasses Rust's safety guarantees. - Using vectors and indices into those vectors. There are [several](http://smallcultfollowing.com/babysteps/blog/2015/04/06/modeling-graphs-in-rust-using-vector-indices/) [available](http://featherweightmusings.blogspot.com/2015/04/graphs-in-rust.html) examples and explanations of this approach. +- Using borrowed references with `UnsafeCell`. There are [explanations and code](https://github.com/nrc/r4cppp/blob/master/graphs/README.md#node-and-unsafecell) available for this approach. ### How can I define a struct that contains a pointer to one of its own fields? @@ -263,7 +274,7 @@ fn main() { ### What does it mean to "consume a value"? -"Consuming a value" means taking ownership of a value. When this is done, the value can't be used elsewhere. +"Consuming a value" means taking ownership of a value. When this is done, the value can't be used elsewhere. "Consume" is a fairly evocative term for this event. ### What is the difference between consuming and moving/taking ownership? @@ -300,16 +311,15 @@ While the rules themselves are simple, making sure your code conforms to them ca ### How do deref coercions work? -[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait, which looks like +[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait. -```rust -pub trait Deref { - type Target: ?Sized; - fn deref(&self) -> &Self::Target; -} -``` +A Deref implementation indicates that the implementing type may be converted into a target by a call to the `deref` method, which takes an immutable reference to the calling type and returns a reference (of the same lifetime) to the target type. The `*` prefix operator is shorthand for the `deref` method. -A Deref implementation indicates that the implementing type may be converted into `Target` by a call to the `deref` function, which takes an immutable reference of a certain lifetime to the calling struct, and returns a reference of the same lifetime to the target. The `*` prefix operator is shorthand for the `deref` method. +They're called "coercions" because of the following rule, quoted here [from the Rust book](https://doc.rust-lang.org/stable/book/deref-coercions.html): + +> If you have a type `U`, and it implements `Deref`, values of `&U` will automatically coerce to a `&T`. + +For example, if you have a `&Rc`, it will coerce via this rule into a `&String`, which then coerces to a `&str` in the same way. So if a function takes a `&str` parameter, you can pass in a `&Rc` directly, with all coercions handled automatically via the `Deref` trait. You can see a [full list of `Deref` implementations](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html#implementors) for the standard library in the documentation. @@ -321,7 +331,7 @@ Lifetimes are Rust's answer to the question of memory safety. They allow Rust to ### Why is the lifetime syntax the way it is? -The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticeable, and fit nicely in a type declaration right alonside traits and references. Alternative syntaxes have been discussed, but this seems to work fine. +The `'a` syntax comes from the ML family of programming languages, where `'a` is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticeable, and fit nicely in a type declaration right alonside traits and references. Alternative syntaxes have been discussed, but no alternative syntax has been demonstrated to be clearly better. ### When is `Rc` useful? @@ -329,7 +339,46 @@ This is covered in the [official documentation for `Rc`](https://doc.rust-lang.o ### How do I return a borrow to something I created from a function? -You need to ensure that the borrowed item will outlive the function. This can be done by binding the output lifetime to some input lifetime. An alternative is to return an owning type like `String`. This eliminates the reference issues entirely, at the cost of possibly unnecessary allocations. There is also the `Cow` ("copy on write") type, which will only do the extra allocation if you attempt to mutate the contained value. +You need to ensure that the borrowed item will outlive the function. This can be done by binding the output lifetime to some input lifetime like so: + +```rust +type Pool = TypedArena; + +// (the lifetime below is only written explicitly for +// expository purposes; it can be omitted via the +// elision rules described in a later FAQ entry) +fn create_borrowed<'a>(pool: &'a Pool, + x: i32, + y: i32) -> &'a Thing { + pool.alloc(Thing { x: x, y: y }) +} +``` + +An alternative is to eliminate the references entirely by returning an owning type like `String`: + +```rust +fn happy_birthday(name: &str, age: i64) -> String { + format!("Hello {}! You're {} years old!", name, age) +} +``` + +This approach is simpler, but often results in unnecessary allocations. + +There is also the `Cow` ("copy on write") type, which will only do the extra allocation if you attempt to mutate the contained value: + +```rust +use std::borrow::Cow; + +fn abs_all(input: &mut Cow<[i32]>) { + for i in 0..input.len() { + let v = input[i]; + if v < 0 { + // clones into a vector the first time (if not already owned) + input.to_mut()[i] = -v; + } + } +} +``` ### How do I return a closure from a function? @@ -363,11 +412,13 @@ Functions that accept [trait objects](http://doc.rust-lang.org/book/trait-object ### What's the difference between a function and a closure that doesn't capture any variables? +Functions and closures are operationally equivalent, but have different runtime representations due to their differing implementations. + Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the struct can be called as a function. Bare functions can not capture an environment. The big difference between these traits is how they take the `self` parameter. `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. -In the end, functions and closures are operationally equivalent, but have different runtime representations due to their different implementations (as a language primitive and a syntactic sugar over traits, respectively). +Even if a closure does not capture any environment variables, it is represeted at runtime as two points, same as any other closure. ### What are higher-kinded types, why would I want them, and why doesn't Rust have them? @@ -379,9 +430,11 @@ Rust doesn't currently have them simply because they haven't been a priority. Th ### What do named type parameters like `` in generic types mean? -These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a `where` clause. In essence, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. +These are called [associated types](https://doc.rust-lang.org/stable/book/associated-types.html), and they allow for the expression of trait bounds that can't be expressed with a `where` clause. For example, a generic bound `X: Bar` means "`X` must implement the trait `Bar`, and in that implementation of `Bar`, `X` must choose `Foo` for `Bar`'s associated type, `T`." Examples of where such a constraint cannot be expressed via a `where` clause include trait objects like `Box>`. -### Can I override operators? Which ones and how? +Associated types exist because, for a generic type with some type parameters, it is often unecessary to include those type parameters in a function taking that generic type as a parameter. The function shouldn't have to care about being generic over the types which make up the generic type (say, the node and edge types in a graph), but only about being generic over the type itself. + +### Can I overload operators? Which ones and how? You can provide custom implementations for a variety of operators using their associated traits: `Add` for `+`, `Mul` for `*`. It looks like this: @@ -495,7 +548,7 @@ It's probably an issue with the function's return type. The [`try!` macro](https ### Is there an easier way to do error handling than having `Result`s everywhere? -If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you want. `Result` is an indicator that some computation may or may not complete successfully. Requiring you to handle these failures explicitly is one of the ways that Rust encourages safety. If you really don't want to handle an error, use `unwrap()`, but know that doing so means that the given code will cause the entire process to panic on failure, which is usually undesirable. +If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you want. `Result` is an indicator that some computation may or may not complete successfully. Requiring you to handle these failures explicitly is one of the ways that Rust encourages robustness. If you really don't want to handle an error, use `unwrap()`, but know that doing so means that the given code will cause the entire process to panic on failure, which is usually undesirable.

    Concurrency

    @@ -513,7 +566,7 @@ Not currently. Rust macros are ["hygienic macros"](https://en.wikipedia.org/wiki ### How do I debug Rust programs? -Rust programs can be debugged using [gdb](http://sourceware.org/gdb/current/onlinedocs/gdb/) or [lldb](http://lldb.llvm.org/tutorial.html), same as C and C++. In fact, every Rust installation comes with rust-gdb and rust-lldb, wrappers over gdb and lldb with Rust pretty-printing enabled. +Rust programs can be debugged using [gdb](http://sourceware.org/gdb/current/onlinedocs/gdb/) or [lldb](http://lldb.llvm.org/tutorial.html), same as C and C++. In fact, every Rust installation comes with one or both of rust-gdb and rust-lldb (depending on platform support). These are wrappers over gdb and lldb with Rust pretty-printing enabled. ### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? @@ -578,22 +631,22 @@ Yes it can! There are already examples of using Rust for both [Android](https:// ### Can I run my Rust program in a web browser? -Not yet, but there are efforts underway to make Rust compile to the web with Emscripten. +Not yet, but there are efforts underway to make Rust compile to the web with [Emscripten](http://kripken.github.io/emscripten-site/). ### How do I cross-compile in Rust? -Cross compilation is possible in Rust, but it requires [a bit of work](https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md) to set up. Rust does distribute [copies of the standard library](http://static.rust-lang.org/dist/) for each of the supported platforms, which are contained in the `rust-std-*` files for each of the build directories found on the distribution page, but there are not yet automated ways to install them. +Cross compilation is possible in Rust, but it requires [a bit of work](https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md) to set up. Every Rust compiler is a cross-compiler, but libraries need to be cross-compiled for the target platform. + +Rust does distribute [copies of the standard library](http://static.rust-lang.org/dist/) for each of the supported platforms, which are contained in the `rust-std-*` files for each of the build directories found on the distribution page, but there are not yet automated ways to install them.

    Modules and Crates

    ### What is the relationship between a module and a crate? - A crate is a compilation unit, which is the smallest amount of code that the Rust compiler can operate on. -- A module is a (possibly nested) unit of name-management inside a crate. +- A module is a (possibly nested) unit of code organization inside a crate. - A crate contains an implicit, un-named top-level module. - Recursive definitions can span modules, but not crates. -- Crates do not have global names, only a set of non-unique metadata tags. -- There is no global inter-crate namespace; all name management occurs within a crate. - Using another crate binds the root of its namespace into the user's namespace. ### Why can't the Rust compiler find this library I'm `use`ing? @@ -728,6 +781,10 @@ Yes you can! The major game programming library for Rust is [Piston](http://www. It is multi-paradigm. Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you're accustomed to. +### How do I map object-oriented concepts to Rust? + +That depends. There _are_ ways of translating object-oriented concepts like [multiple inheritance](https://www.reddit.com/r/rust/comments/2sryuw/ideaquestion_about_multiple_inheritence/) to Rust, but as Rust is not object-oriented the result of the translation may look substantially different from its appearance in an OO language. + ### How do I handle configuration of a struct with optional parameters? The easiest way is to use the `Option` type in whatever function you're using to construct instances of the struct (usually `new()`). Another way is to use the [builder pattern](https://aturon.github.io/ownership/builders.html), where only certain functions instantiating member variables must be called before the construction of the built type. @@ -748,10 +805,6 @@ To define procedural constants that can't be defined via these mechanisms, use t Rust has no concept of "life before `main`". The closest you'll see can be done through the [`lazy_static`](https://github.com/Kimundi/lazy-static.rs) crate, which simulates a "before main" by lazily initializing static variables at their first usage. -### How do I map object-oriented concepts to Rust? - -That depends. There _are_ ways of translating object-oriented concepts like [multiple inheritance](https://www.reddit.com/r/rust/comments/2sryuw/ideaquestion_about_multiple_inheritence/) to Rust, but as Rust is not object-oriented the result of the translation may look substantially different from its appearance in an OO language. - ### Why doesn't Rust have inheritance? There are two meanings for the word "inheritance": _subtyping_, and _interface sharing_. Both purposes are already handled by traits. @@ -798,7 +851,7 @@ Yes. The Rust code has to be exposed via an `extern` declaration, which makes it Modern C++ includes many features that make writing safe and correct code less error-prone, but it's not perfect, and it's still easy to introduce unsafety. This is something the C++ core developers are working to overcome, but C++ is limited by a long history that predates a lot of the ideas they are now trying to implement. -Rust was designed from day one to be a safe systems programming language, which means it's not limited by historic design decisions that make getting safety right in C++ so complicated. In C++, safety is achieved by careful personal discipline, and is very easy to get wrong. In Rust, safety is the default. +Rust was designed from day one to be a safe systems programming language, which means it's not limited by historic design decisions that make getting safety right in C++ so complicated. In C++, safety is achieved by careful personal discipline, and is very easy to get wrong. In Rust, safety is the default. It gives you the ability to work in a team that includes people less perfect than you are, without having to spend your time double-checking their code for safety bugs. ### How do I do the equivalent of C++ template specialization in Rust? @@ -854,7 +907,7 @@ In Swift, `?` is used to indicate an optional value. This is already done by `Op Rust and Go have substantially different design goals. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones: -- Rust is lower level than Go, comparable with C and C++. It provides access to memory management primitives that do not exist in Go (which has a garbage collector). +- Rust provides access to memory management primitives that do not exist in Go, which has a garbage collector. - Rust's focus is on ensuring safety and efficiency while also providing high-level affordances, while Go's is on being a small, simple language which compiles quickly and can work nicely with a variety of tools. - Rust has strong support for generics, which Go does not. - Rust has strong influences from the world of functional programming, including a type system which draws from Haskell's typeclasses. Go has a simpler type system, using interfaces for basic generic programming. @@ -879,7 +932,7 @@ Some specific difference between Haskell typeclasses and Rust traits include: ### Where do I report issues in the Rust documentation? -You can report issues in the Rust documentation on the Rust compiler [issue tracker](https://github.com/rust-lang/rust/issues). Make sure to read the [contributing guidelines](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md) first. +You can report issues in the Rust documentation on the Rust compiler [issue tracker](https://github.com/rust-lang/rust/issues). Make sure to read the [contributing guidelines](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#writing-documentation) first. ### How do I view rustdoc documentation for a library my project depends on? @@ -906,7 +959,7 @@ No. Rust started as Graydon Hoare's part-time side project in 2006 and remained As far as [project governance](https://github.com/rust-lang/rfcs/blob/master/text/1068-rust-governance.md) goes, Rust is managed by a core team that sets the vision and priorities for the project, and accepts input on the design of the language via RFC proposals. There are also subteams to guide and foster development of particular areas of interest, including Rust libraries, Rust tools, and moderation of the official Rust communities. For changes which do not require an RFC, decisions are made through pull requests on the [`rustc` repository](https://github.com/rust-lang/rust). -### What are some design goals of Rust? +### What are some non-goals of Rust? 1. We do not employ any particularly cutting-edge technologies. Old, established techniques are better. 2. We do not prize expressiveness, minimalism or elegance above other goals. These are desirable but subordinate goals. From 7ba7f3dfd3ab41f2f1fe73598623479c68c3b4cf Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Thu, 7 Jan 2016 19:00:47 -0500 Subject: [PATCH 32/41] New draft of the higher-kinded types answer --- faq.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/faq.md b/faq.md index 8b780204b..c10d6d7c5 100644 --- a/faq.md +++ b/faq.md @@ -422,11 +422,13 @@ Even if a closure does not capture any environment variables, it is represeted a ### What are higher-kinded types, why would I want them, and why doesn't Rust have them? -Higher-kinded types are types with unfilled parameters. Support for higher-kinded types means "incomplete" types may be used anywhere "complete" types can be used, such as in a trait `impl`. +Higher-kinded types are typed with unfilled parameters. Type constructors, like `Vec`, `Result`, and `HashMap` are all examples of higher-kinded types. Support for higher-kinded types means these "incomplete" types may be used anywhere "complete" types can be used, such as trait `impl`s. -The lack of support for higher-kinded types makes expression of certain ideas more tedious than it would otherwise be. For example, implementing a `Functor` trait (a term for a container which can be mapped over, obeying certain rules) without higher-kinded types would be difficult, as a `Functor` should be implemented for the container regardless of the type of values it contains. With higher-kinded types, the Functor `impl` for some container could leave the container's type parameter unfilled, with no concrete type. +Any complete type, like `i32`, `bool`, or `char` is of kind `*`. A type with one parameter, like `Vec` is of kind `* -> *`, meaning that `Vec` takes in a complete type like `i32` and returns a complete type `Vec`. A type which three parameters, like `HashMap` is of kind `* -> * -> * -> *`, and takes in three complete types (like `i32`, `String`, and `RandomState`) to produce a new complete type `HashMap`. -Rust doesn't currently have them simply because they haven't been a priority. There is nothing inherent to the language that stops us from implementing support for higher-kinded types, it just hasn't been done yet. +The lack of support for higher-kinded types makes expression of certain ideas more tedious than it would otherwise be. For example, implementing a `Functor` trait (a term for a container which can be mapped over, obeying certain rules) without higher-kinded types requires explicit and otherwise unnecessary handling of the container's type parameters. With higher-kined types, a `Functor` `impl` can ignore the parameters entirely. + +Rust doesn't currently have support for higher-kinded types because it hasn't been a priority. There is nothing inherent to the language that stops the support from being implemented. It just hasn't been done yet. ### What do named type parameters like `` in generic types mean? From e7bab6490321709329c1ac904b08f96120be51b3 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Thu, 7 Jan 2016 19:17:20 -0500 Subject: [PATCH 33/41] Partial addition of API doc links --- faq.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/faq.md b/faq.md index c10d6d7c5..43ec96db5 100644 --- a/faq.md +++ b/faq.md @@ -75,9 +75,9 @@ Finally, while Rust's preferred strategy of monomorphising generics (ala C++) pr ### Why are Rust's `HashMap`s slow? -By default, Rust's `HashMap` uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). +By default, Rust's [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html) uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). -While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges/blah/hash-rs/) in many cases, one case where it is notably slower than other hashing algorithms is with short keys, such as integers. This is why Rust programmers often observe slow performance with `HashMap`. The [FNV hasher](https://crates.io/crates/fnv) is frequently recommended for these cases, but be aware that it does not have the same collision-resistance properties as SipHash. +While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges/blah/hash-rs/) in many cases, one case where it is notably slower than other hashing algorithms is with short keys, such as integers. This is why Rust programmers often observe slow performance with [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html). The [FNV hasher](https://crates.io/crates/fnv) is frequently recommended for these cases, but be aware that it does not have the same collision-resistance properties as SipHash. ### Why is there no integrated benchmarking infrastructure? @@ -144,27 +144,27 @@ If in doubt, choose `f64` for the greater precision. ### Why can't I use `f32` or `f64` as `HashMap` keys? -In order to be used as a key in a `HashMap`, a type must implement the `Eq` and `Hash` traits. `f32` and `f64` implement `PartialEq`, but not `Eq`, because one of the potential values for floating-point types is `NaN` (or "not a number"). `NaN` values are [not equal to any float, and are not equal to each other](https://en.wikipedia.org/wiki/NaN). This means that `f32` and `f64` can't be used as keys in a HashMap. +In order to be used as a key in a [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html), a type must implement the [`Eq`](https://doc.rust-lang.org/stable/std/cmp/trait.Eq.html) and [`Hash`](https://doc.rust-lang.org/stable/std/hash/trait.Hash.html) traits. [`f32`](https://doc.rust-lang.org/stable/std/primitive.f32.html) and [`f64`](https://doc.rust-lang.org/stable/std/primitive.f64.html) implement [`PartialEq`](https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html), but not `Eq`, because one of the potential values for floating-point types is `NaN` (or "not a number"). `NaN` values are [not equal to any float, and are not equal to each other](https://en.wikipedia.org/wiki/NaN). This means that `f32` and `f64` can't be used as keys in a HashMap. ### Why can't I compare floats? -Floats can be compared in some circumstances, but not others. Floats do implement the `PartialOrd` trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the `Ord` trait, because (thanks to `NaN`) [there is no total ordering for floating point numbers](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate). The practical effect of this is that data structures that require a total ordering, such as [`BTreeMap`](http://doc.rust-lang.org/std/collections/struct.BTreeMap.html) do not work with floating point numbers. +Floats can be compared in some circumstances, but not others. Floats do implement the [`PartialOrd`](https://doc.rust-lang.org/stable/std/cmp/trait.PartialOrd.html) trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the [`Ord`](https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html) trait, because (thanks to `NaN`) [there is no total ordering for floating point numbers](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate). The practical effect of this is that data structures that require a total ordering, such as [`BTreeMap`](http://doc.rust-lang.org/std/collections/struct.BTreeMap.html) do not work with floating point numbers. There [is a crate](https://crates.io/crates/ordered-float) that provides a total ordering on floats by wrapping them, which may be desirable depending on your use-case. You can still do all of the normal comparison operations you would expect, but you can't use the `cmp` function. ### How can I convert between numeric types? -There are two ways: the `as` keyword, which does simple casting for primitive types, and the `Into` and `From` traits, which are implemented for a number of type conversions (and which you can implement for your own types). The `Into` and `From` traits are only implemented in cases where conversions are lossless, so for example, `f64::from(0f32)` will compile while `f32:from(0f64)` will not. On the other hand, `as` will convert between any two primitive types, truncating values as necessary. +There are two ways: the `as` keyword, which does simple casting for primitive types, and the [`Into`](https://doc.rust-lang.org/stable/std/convert/trait.Into.html) and [`From`](https://doc.rust-lang.org/stable/std/convert/trait.From.html) traits, which are implemented for a number of type conversions (and which you can implement for your own types). The `Into` and `From` traits are only implemented in cases where conversions are lossless, so for example, `f64::from(0f32)` will compile while `f32:from(0f64)` will not. On the other hand, `as` will convert between any two primitive types, truncating values as necessary.

    Strings

    ### How can I convert a `String` or `Vec` to a slice (`&str` and `&[T]`)? -Using [Deref coercions](https://doc.rust-lang.org/stable/book/deref-coercions.html), `Strings` and `Vec`s will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. +Using [Deref coercions](https://doc.rust-lang.org/stable/book/deref-coercions.html), [`String`s](https://doc.rust-lang.org/stable/std/string/struct.String.html) and [`Vec`s](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html) will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. ### How can I convert from `&str` to `String` or the other way around? -The `to_owned()` method converts from a `&str` into a `String`, and `String`s are automatically converted into `&str` when you borrow a reference to them. Both are demonstrated in the following example: +The [`to_owned()`](https://doc.rust-lang.org/stable/std/borrow/trait.ToOwned.html#tymethod.to_owned) method converts from a [`&str`](https://doc.rust-lang.org/stable/std/primitive.str.html) into a [`String`](https://doc.rust-lang.org/stable/std/string/struct.String.html), and `String`s are automatically converted into `&str` when you borrow a reference to them. Both are demonstrated in the following example: ```rust fn main() { @@ -179,7 +179,7 @@ fn say_hello(name: &str) { ### What are the differences between the two different string types? -`String` is an owned buffer of UTF-8 bytes allocated on the heap. Mutable `String`s can be modified, growing their capacity as needed. `&str` is a fixed-capacity "view" into a `String` allocated elsewhere, commonly on the heap, in the case of slices dereferenced from `String`s, or in static memory, in the case of string literals. +[`String`](https://doc.rust-lang.org/stable/std/string/struct.String.html) is an owned buffer of UTF-8 bytes allocated on the heap. Mutable `String`s can be modified, growing their capacity as needed. `&str` is a fixed-capacity "view" into a `String` allocated elsewhere, commonly on the heap, in the case of slices dereferenced from `String`s, or in static memory, in the case of string literals. `&str` is a primitive type implemented by the Rust language, while `String` is implemented in the standard library. From 1594ab32b6e305090c5af87bcdd23bc53e85df10 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Thu, 7 Jan 2016 19:18:14 -0500 Subject: [PATCH 34/41] Fixed based on feedback from pnkfelix --- faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/faq.md b/faq.md index 43ec96db5..7b02c11f6 100644 --- a/faq.md +++ b/faq.md @@ -229,7 +229,7 @@ println!("\nLength: {}", v.len()); Rust `for` loops call `into_iter()` (defined on the `IntoIterator` trait) for whatever they're iterating over. Anything implementing the `IntoIterator` trait may be looped over with a `for` loop. `IntoIterator` is implemented for `&Vec` and `&mut Vec`, causing the iterator from `into_iter()` to borrow the contents of the collection, rather than moving/consuming them. The same is true for other standard collections as well. -If a moving/consuming iterator is desired, write the `for` loop without `&` or `&mut` on the collection. +If a moving/consuming iterator is desired, write the `for` loop without `&` or `&mut` in the iteration. ### Why do I need to type the array size in the array declaration? From ffb11a7694ea7e01ab1964df56e816bfca6b27fa Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Thu, 7 Jan 2016 21:45:17 -0500 Subject: [PATCH 35/41] Small correction --- faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/faq.md b/faq.md index 7b02c11f6..c298457dd 100644 --- a/faq.md +++ b/faq.md @@ -390,7 +390,7 @@ Lifetimes can often be elided, as explained in the ["Lifetime elision" section]( - Each elided lifetime in a function’s arguments becomes a distinct lifetime parameter. - If there is exactly one input lifetime, elided or not, that lifetime is assigned to all elided lifetimes in the return values of that function. -- If there are multiple input lifetimes, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes. +- If there are multiple input lifetimes, but one of them is `&self` or `&mut` self, the lifetime of self is assigned to all elided output lifetimes. If these rules would result in incorrect code elsewhere, then the Rust compiler will provide errors, and you will need to define the relevant lifetimes to correct that error. From ea304edfbfbda325f59e1c676b4c10f139b905b0 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 9 Jan 2016 12:01:34 -0500 Subject: [PATCH 36/41] Updated based on latest feedback --- faq.md | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/faq.md b/faq.md index c298457dd..d76ad1779 100644 --- a/faq.md +++ b/faq.md @@ -111,7 +111,25 @@ This design choice of using Rust's macro facilities to initialize collections wi ### When should I use an implicit return? -Implicit returns are simply a coding style option, and can be used as the final line in a block expression. While early returns require an explicit `return` keyword, any other return can be made implicit according to your preferences or the preferences of your project. In the Rust project itself, the style guidelines lean toward preferring implicit returns. +Rust is a very expression-oriented language, and implicit returns are part of that design. `if`s, `match`es, and normal blocks are all expressions in Rust. For example, the following code checks if an `i64` is odd, returning the result with an implicit return: + +```rust +fn is_odd(x: i64) -> bool { + if x % 2 == 1 { true } else { false } +} +``` + +Although it can be simplified even further like so: + +```rust +fn is_odd(x: i64) -> bool { + x % 2 == 1 +} +``` + +In each example, the last line of the function is the return value of that function. It is important to note that if a function ends in a semicolon, its return type will be `()`, indicating no returned value. Implicit returns must omit the semicolon to work. + +Explicit returns are only used if an implicit return is impossible because you are returning before the end of the function's body. While each of the above functions could have been written with a `return` keyword and semicolon, doing so would be unnecessarily verbose, and inconsistent with the conventions of Rust code. ### Why aren't function signatures inferred? @@ -556,7 +574,9 @@ If you're looking for a way to avoid handling `Result`s in other people's code, ### Can I use static values across threads without an `unsafe` block? -Yes, if the type implements `Sync`, doesn't implement `Drop`, and you don't try to mutate the value. +Mutation is safe if it's synchronized. Mutating a static `Mutex` (lazily initialized via the [lazy_static](https://crates.io/crates/lazy_static/) crate) does not require an `unsafe` block, nor does mutating a static `AtomicUsize` (which can be initialized without lazy_static). + +More generally, if a type implements `Sync` and does not implement `Drop`, it [can be used in a `static`](https://doc.rust-lang.org/book/const-and-static.html#static).

    Macros

    @@ -793,9 +813,7 @@ The easiest way is to use the `Option` type in whatever function you're using to ### How do I do global variables in Rust? -Globals in Rust can be done using `const` declarations for compile-time computed global constants, while `static` can be used for mutable globals. Note that modifying a `static` variable requires the use of `unsafe`, as it allows for data races, one of the things guaranteed not to happen in safe Rust. One important distinction between `const` and `static` values is that you can take references to `static` values, but not references to `const` values, which don't have a specified memory location. For more information on `const` vs. `static`, read [the Rust book](https://doc.rust-lang.org/book/const-and-static.html). - -You can also use the `RefCell` and `Option` type to provide interior mutability of an optional global value. It is important to note that `RefCell`s are not thread-safe. +Globals in Rust can be done using `const` declarations for compile-time computed global constants, while `static` can be used for mutable globals. Note that modifying a `static mut` variable requires the use of `unsafe`, as it allows for data races, one of the things guaranteed not to happen in safe Rust. One important distinction between `const` and `static` values is that you can take references to `static` values, but not references to `const` values, which don't have a specified memory location. For more information on `const` vs. `static`, read [the Rust book](https://doc.rust-lang.org/book/const-and-static.html). ### How can I set compile-time constants that are defined procedurally? @@ -823,6 +841,8 @@ No. Globals cannot have a non-constant-expression constructor and cannot have a See the [C++ FQA](http://yosefk.com/c++fqa/ctors.html#fqa-10.12) about the "static initialization order fiasco", and [Eric Lippert's blog](http://ericlippert.com/2013/02/06/static-constructors-part-one/) for the challenges in C#, which also has this feature. +You can approximate non-constant-expression globals with the [lazy_static](https://crates.io/crates/lazy_static/) crate. +

    Other Languages

    ### How can I implement something like C's `struct X { static int X; };` in Rust? @@ -901,10 +921,6 @@ Not exactly. Types which implement `Copy` will do a standard C-like "shallow cop No. Values of all types are moved via `memcpy`. This makes writing generic unsafe code much simpler since assignment, passing and returning are known to never have a side effect like unwinding. -### Why does Rust not have the ? and ! like in Swift? - -In Swift, `?` is used to indicate an optional value. This is already done by `Option` in Rust, and so `?` is not needed. Similarly, `!` is used to "unwrap" an optional value in Swift, which is done by the `unwrap()` function in Rust. In both cases, Rust opted for slightly longer names which more clearly indicate intent. Also, in Rust the `!` symbol already indicates logical negation and macro calls, and does not need a third meaning. - ### How are Go and Rust similar, and how are they different? Rust and Go have substantially different design goals. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones: From 8e490bbc073becf55b9aefc042d56e19cf64ca0a Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 9 Jan 2016 12:22:05 -0500 Subject: [PATCH 37/41] Updated ord/eq answers --- faq.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/faq.md b/faq.md index d76ad1779..5963d9079 100644 --- a/faq.md +++ b/faq.md @@ -160,15 +160,23 @@ If you are interested in the greatest degree of precision with your floating poi If in doubt, choose `f64` for the greater precision. -### Why can't I use `f32` or `f64` as `HashMap` keys? +### Why can't I compare floats? -In order to be used as a key in a [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html), a type must implement the [`Eq`](https://doc.rust-lang.org/stable/std/cmp/trait.Eq.html) and [`Hash`](https://doc.rust-lang.org/stable/std/hash/trait.Hash.html) traits. [`f32`](https://doc.rust-lang.org/stable/std/primitive.f32.html) and [`f64`](https://doc.rust-lang.org/stable/std/primitive.f64.html) implement [`PartialEq`](https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html), but not `Eq`, because one of the potential values for floating-point types is `NaN` (or "not a number"). `NaN` values are [not equal to any float, and are not equal to each other](https://en.wikipedia.org/wiki/NaN). This means that `f32` and `f64` can't be used as keys in a HashMap. +Floats can be compared with the `==`, `!=`, `<`, `<=`, `>`, and `>=` operators, and with the `partial_cmp()` function. `==` and `!=` are part of the `PartialEq` trait, while `<`, `<=`, `>`, `>=`, and `partial_cmp()` are part of the `PartialOrd` trait. -### Why can't I compare floats? +Floats cannot be compared with the `cmp()` function, which is part of the `Ord` trait, as there is no total ordering for floats. Furthermore, there is no total equality relation for floats, and so they also do not implement the `Eq` trait. + +There is no total ordering or equality on floats because the floating-point value `NaN` is not less than, greater than, or equal to any other floating-point value or itself. + +Because floats do not implement `Eq` or `Ord`, they may not be used in types whose trait bounds require those traits, such as `BTreeMap`. + +There [is a crate](https://crates.io/crates/ordered-float) that wraps `f32` and `f64` to provide `Ord` and `Eq` implementations, which may be useful in certain cases. + +### Why can't I use `f32` or `f64` as `HashMap` keys? -Floats can be compared in some circumstances, but not others. Floats do implement the [`PartialOrd`](https://doc.rust-lang.org/stable/std/cmp/trait.PartialOrd.html) trait, which means that `>`, `<`, `<=`, and `>=` are defined for them. But they do _not_ implement the [`Ord`](https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html) trait, because (thanks to `NaN`) [there is no total ordering for floating point numbers](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate). The practical effect of this is that data structures that require a total ordering, such as [`BTreeMap`](http://doc.rust-lang.org/std/collections/struct.BTreeMap.html) do not work with floating point numbers. +In order to be used as a key in a [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html), a type must implement the [`Eq`](https://doc.rust-lang.org/stable/std/cmp/trait.Eq.html) and [`Hash`](https://doc.rust-lang.org/stable/std/hash/trait.Hash.html) traits. `Eq` is required because keys have to be capable of being tested for equality, otherwise indexing on keys wouldn't work. `Hash` is required so that the type may be hashed by `HashMap`'s hashing algorithm. -There [is a crate](https://crates.io/crates/ordered-float) that provides a total ordering on floats by wrapping them, which may be desirable depending on your use-case. You can still do all of the normal comparison operations you would expect, but you can't use the `cmp` function. +[`f32`](https://doc.rust-lang.org/stable/std/primitive.f32.html) and [`f64`](https://doc.rust-lang.org/stable/std/primitive.f64.html) implement [`PartialEq`](https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html), but not `Eq` This is because one of the potential values for floating-point types is `NaN` (or "not a number"). Per the IEEE floating-point specification, `NaN` values are [not equal to any other floating-point value, and not equal to each other](https://en.wikipedia.org/wiki/NaN). This means there is no total equality relation for floating-point types, and thus that `f32` and `f64` can't implement `Eq` and can't used as keys in a `HashMap`. ### How can I convert between numeric types? From 6705771fe1da83876ead054d9c38770b73ccb974 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 9 Jan 2016 12:32:15 -0500 Subject: [PATCH 38/41] Updated borrow checker answer --- faq.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/faq.md b/faq.md index 5963d9079..60821ae27 100644 --- a/faq.md +++ b/faq.md @@ -333,7 +333,15 @@ The borrow checker applies only a few rules, which can be found in the Rust book > - one or more references (&T) to a resource. > - exactly one mutable reference (&mut T) -While the rules themselves are simple, making sure your code conforms to them can be complicated. It is easy to attempt to borrow a value for longer than its lifetime, or to introduce two mutable references to the same value. The borrow checker is useful because it verifies that your code follows these rules, and helps guide corrections when the code doesn't. Many new Rust programmers struggle to satisfy the borrow checker at first, but over time become more skilled at writing memory safe code with minimal borrow checker intervention. +While the rules themselves are simple, following them consistently is not, particularly for those unaccustomed to reasoning about lifetimes and ownership. + +The first step in understanding the borrow checker is reading the errors it produces. A lot of work has been put into making sure the borrow checker provides quality assistance in resolving the issues it identifies. When you encounter a borrow checker problem, the first step is to slowly and carefully read the error reported, and to only approach the code after you understand the error being described. + +The second step is to become familiar with the ownership and mutability-related container types provided by the Rust standard library, including `Cell`, `RefCell`, and `Cow`. These are useful and necessary tools for expressing certain ownership and mutability sutations, and have been written to be of minimal performance cost. + +The single most important part of understanding the borrow checker is practice. Rust's strong static analyses guarantees are strict and quite different from what many programmers have worked with before. It will take some time to become completely comfortable with everything. + +If you find yourself struggling with the borrow checker, or running out of patience, always feel free to reach out to the [Rust community](https://www.rust-lang.org/community.html) for help. ### How do deref coercions work? From 6b75c04be678d841d130984f76024579a41de369 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 9 Jan 2016 12:36:23 -0500 Subject: [PATCH 39/41] Updated lifetime elision answer --- faq.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/faq.md b/faq.md index 60821ae27..3787051fc 100644 --- a/faq.md +++ b/faq.md @@ -418,15 +418,15 @@ fn abs_all(input: &mut Cow<[i32]>) { To return a closure from a function, it must be a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own copy of the captured variables, independent of its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer valid; put another way: it would allow reading potentially invalid memory. The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). -### When are lifetimes required to be defined? +### When are lifetimes required to be explicit? -Lifetimes can often be elided, as explained in the ["Lifetime elision" section](https://doc.rust-lang.org/book/lifetimes.html#lifetime-elision) of the Rust book. "Elided lifetimes" are those lifetimes which are implicit in any code containing references. They are automatically inserted by the compiler with the three following rules: +Lifetimes must be explicit when the rules for automatic lifetime inference result in compilation errors. The Rust compiler tries its best to automatically infer correct lifetimes (called ["elided lifetimes"](https://doc.rust-lang.org/stable/book/lifetimes.html#lifetime-elision)) based on the following rules: - Each elided lifetime in a function’s arguments becomes a distinct lifetime parameter. - If there is exactly one input lifetime, elided or not, that lifetime is assigned to all elided lifetimes in the return values of that function. - If there are multiple input lifetimes, but one of them is `&self` or `&mut` self, the lifetime of self is assigned to all elided output lifetimes. -If these rules would result in incorrect code elsewhere, then the Rust compiler will provide errors, and you will need to define the relevant lifetimes to correct that error. +If these rules result in compilation errors, the Rust compiler will provide an error message indicating the error caused, and suggesting a potential solution based on which step of the inference process caused the error. ### How can Rust guarantee "no null pointers"? From c4e41f08b71411f6484d342b9bf6f40e68e54de8 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 9 Jan 2016 12:49:37 -0500 Subject: [PATCH 40/41] Fixed typo --- faq.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/faq.md b/faq.md index 3787051fc..712f8b4d1 100644 --- a/faq.md +++ b/faq.md @@ -590,7 +590,7 @@ If you're looking for a way to avoid handling `Result`s in other people's code, ### Can I use static values across threads without an `unsafe` block? -Mutation is safe if it's synchronized. Mutating a static `Mutex` (lazily initialized via the [lazy_static](https://crates.io/crates/lazy_static/) crate) does not require an `unsafe` block, nor does mutating a static `AtomicUsize` (which can be initialized without lazy_static). +Mutation is safe if it's synchronized. Mutating a static `Mutex` (lazily initialized via the [lazy-static](https://crates.io/crates/lazy_static/) crate) does not require an `unsafe` block, nor does mutating a static `AtomicUsize` (which can be initialized without lazy_static). More generally, if a type implements `Sync` and does not implement `Drop`, it [can be used in a `static`](https://doc.rust-lang.org/book/const-and-static.html#static). @@ -839,7 +839,7 @@ To define procedural constants that can't be defined via these mechanisms, use t ### Can I run initialization code that happens before main? -Rust has no concept of "life before `main`". The closest you'll see can be done through the [`lazy_static`](https://github.com/Kimundi/lazy-static.rs) crate, which simulates a "before main" by lazily initializing static variables at their first usage. +Rust has no concept of "life before `main`". The closest you'll see can be done through the [`lazy-static`](https://github.com/Kimundi/lazy-static.rs) crate, which simulates a "before main" by lazily initializing static variables at their first usage. ### Why doesn't Rust have inheritance? @@ -857,7 +857,7 @@ No. Globals cannot have a non-constant-expression constructor and cannot have a See the [C++ FQA](http://yosefk.com/c++fqa/ctors.html#fqa-10.12) about the "static initialization order fiasco", and [Eric Lippert's blog](http://ericlippert.com/2013/02/06/static-constructors-part-one/) for the challenges in C#, which also has this feature. -You can approximate non-constant-expression globals with the [lazy_static](https://crates.io/crates/lazy_static/) crate. +You can approximate non-constant-expression globals with the [lazy-static](https://crates.io/crates/lazy_static/) crate.

    Other Languages

    From 898dd0f58d47deed9094c49beb3717106aa8f076 Mon Sep 17 00:00:00 2001 From: Andrew Brinker Date: Sat, 9 Jan 2016 13:42:37 -0500 Subject: [PATCH 41/41] Added links to API docs --- faq.md | 257 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 159 insertions(+), 98 deletions(-) diff --git a/faq.md b/faq.md index 712f8b4d1..e497cc1eb 100644 --- a/faq.md +++ b/faq.md @@ -75,9 +75,9 @@ Finally, while Rust's preferred strategy of monomorphising generics (ala C++) pr ### Why are Rust's `HashMap`s slow? -By default, Rust's [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html) uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). +By default, Rust's [`HashMap`][HashMap] uses the [SipHash](https://131002.net/siphash/) hashing algorithm, which is designed to prevent [hash table collision attacks](http://programmingisterrible.com/post/40620375793/hash-table-denial-of-service-attacks-revisited) while providing [reasonable performance on a variety of workloads](https://www.reddit.com/r/rust/comments/3hw9zf/rust_hasher_comparisons/cub4oh6). -While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges/blah/hash-rs/) in many cases, one case where it is notably slower than other hashing algorithms is with short keys, such as integers. This is why Rust programmers often observe slow performance with [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html). The [FNV hasher](https://crates.io/crates/fnv) is frequently recommended for these cases, but be aware that it does not have the same collision-resistance properties as SipHash. +While SipHash [demonstrates competitive performance](http://cglab.ca/%7Eabeinges/blah/hash-rs/) in many cases, one case where it is notably slower than other hashing algorithms is with short keys, such as integers. This is why Rust programmers often observe slow performance with [`HashMap`][HashMap]. The [FNV hasher](https://crates.io/crates/fnv) is frequently recommended for these cases, but be aware that it does not have the same collision-resistance properties as SipHash. ### Why is there no integrated benchmarking infrastructure? @@ -85,7 +85,7 @@ You can run benchmarks, but only on the nightly channel. Rust's benchmarking mec ### Does Rust do tail-call optimization? -Not generally, no. Tail-call optimization may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), but is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html). As the feature has always been desired, Rust has a keyword (`become`) reserved, though it is not clear yet whether it is technically possible, nor whether it will be implemented. There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. +Not generally, no. Tail-call optimization may be done in [limited circumstances](http://llvm.org/docs/CodeGenerator.html#sibling-call-optimization), but is [not guaranteed](https://mail.mozilla.org/pipermail/rust-dev/2013-April/003557.html). As the feature has always been desired, Rust has a keyword (`become`) reserved, though it is not clear yet whether it is technically possible, nor whether it will be implemented. There was a [proposed extension](https://github.com/rust-lang/rfcs/pull/81) that would allow tail-call elimination in certain contexts, but it is currently postponed. ### Does Rust have a runtime? @@ -105,17 +105,17 @@ Whereas C requires mandatory parentheses for `if`-statement conditionals but lea ### Why is there no literal syntax for dictionaries? -The reason Rust does not have syntax for initializing dictionaries — or collections in general — is due to Rust's overall design preference for limiting the size of the *language* while enabling powerful *libraries*. The only type of collection that Rust has direct syntax for initializing is the array type, which is also the only type of collection built into the language. Note that Rust does not even have syntax for initializing the common `Vec` collection type, instead the standard library defines the [`vec!`](http://doc.rust-lang.org/std/macro.vec!.html) macro. +The reason Rust does not have syntax for initializing dictionaries — or collections in general — is due to Rust's overall design preference for limiting the size of the *language* while enabling powerful *libraries*. The only type of collection that Rust has direct syntax for initializing is the array type, which is also the only type of collection built into the language. Note that Rust does not even have syntax for initializing the common [`Vec`][Vec] collection type, instead the standard library defines the [`vec!`][VecMacro] macro. -This design choice of using Rust's macro facilities to initialize collections will likely be extended generically to other collections in the future, enabling simple initialization of not only `HashMap` and `Vec`, but also other collection types such as [`BTreeMap`](http://doc.rust-lang.org/collections/struct.BTreeMap.html). In the meantime, if you want a more convenient syntax for initializing collections, you can [create your own macro](http://stackoverflow.com/questions/27582739/how-do-i-create-a-hashmap-literal) to provide it. +This design choice of using Rust's macro facilities to initialize collections will likely be extended generically to other collections in the future, enabling simple initialization of not only [`HashMap`][HashMap] and [`Vec`][Vec], but also other collection types such as [`BTreeMap`][BTreeMap]. In the meantime, if you want a more convenient syntax for initializing collections, you can [create your own macro](http://stackoverflow.com/questions/27582739/how-do-i-create-a-hashmap-literal) to provide it. ### When should I use an implicit return? -Rust is a very expression-oriented language, and implicit returns are part of that design. `if`s, `match`es, and normal blocks are all expressions in Rust. For example, the following code checks if an `i64` is odd, returning the result with an implicit return: +Rust is a very expression-oriented language, and implicit returns are part of that design. `if`s, `match`es, and normal blocks are all expressions in Rust. For example, the following code checks if an [`i64`][i64] is odd, returning the result with an implicit return: ```rust fn is_odd(x: i64) -> bool { - if x % 2 == 1 { true } else { false } + if x % 2 != 0 { true } else { false } } ``` @@ -123,7 +123,7 @@ Although it can be simplified even further like so: ```rust fn is_odd(x: i64) -> bool { - x % 2 == 1 + x % 2 != 0 } ``` @@ -156,41 +156,41 @@ match val.do_something() { The choice of which to use is dependent on the purpose of the program. -If you are interested in the greatest degree of precision with your floating point numbers, then prefer `f64`. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated inaccuracy of having fewer bits per value, then `f32` is better. Operations on `f32` are usually faster, even on 64-bit hardware. As a common example, graphics programming typically uses `f32` because it requires high performance, and 32-bit floats are sufficient for representing pixels on the screen. +If you are interested in the greatest degree of precision with your floating point numbers, then prefer [`f64`][f64]. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated inaccuracy of having fewer bits per value, then [`f32`][f32] is better. Operations on [`f32`][f32] are usually faster, even on 64-bit hardware. As a common example, graphics programming typically uses [`f32`][f32] because it requires high performance, and 32-bit floats are sufficient for representing pixels on the screen. -If in doubt, choose `f64` for the greater precision. +If in doubt, choose [`f64`][f64] for the greater precision. ### Why can't I compare floats? -Floats can be compared with the `==`, `!=`, `<`, `<=`, `>`, and `>=` operators, and with the `partial_cmp()` function. `==` and `!=` are part of the `PartialEq` trait, while `<`, `<=`, `>`, `>=`, and `partial_cmp()` are part of the `PartialOrd` trait. +Floats can be compared with the `==`, `!=`, `<`, `<=`, `>`, and `>=` operators, and with the `partial_cmp()` function. `==` and `!=` are part of the [`PartialEq`][PartialEq] trait, while `<`, `<=`, `>`, `>=`, and `partial_cmp()` are part of the [`PartialOrd`][PartialOrd] trait. -Floats cannot be compared with the `cmp()` function, which is part of the `Ord` trait, as there is no total ordering for floats. Furthermore, there is no total equality relation for floats, and so they also do not implement the `Eq` trait. +Floats cannot be compared with the `cmp()` function, which is part of the [`Ord`][Ord] trait, as there is no total ordering for floats. Furthermore, there is no total equality relation for floats, and so they also do not implement the [`Eq`][Eq] trait. There is no total ordering or equality on floats because the floating-point value `NaN` is not less than, greater than, or equal to any other floating-point value or itself. -Because floats do not implement `Eq` or `Ord`, they may not be used in types whose trait bounds require those traits, such as `BTreeMap`. +Because floats do not implement [`Eq`][Eq] or [`Ord`][Ord], they may not be used in types whose trait bounds require those traits, such as [`BTreeMap`][BTreeMap]. -There [is a crate](https://crates.io/crates/ordered-float) that wraps `f32` and `f64` to provide `Ord` and `Eq` implementations, which may be useful in certain cases. +There [is a crate](https://crates.io/crates/ordered-float) that wraps [`f32`][f32] and [`f64`][f64] to provide [`Ord`][Ord] and [`Eq`][Eq] implementations, which may be useful in certain cases. ### Why can't I use `f32` or `f64` as `HashMap` keys? -In order to be used as a key in a [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html), a type must implement the [`Eq`](https://doc.rust-lang.org/stable/std/cmp/trait.Eq.html) and [`Hash`](https://doc.rust-lang.org/stable/std/hash/trait.Hash.html) traits. `Eq` is required because keys have to be capable of being tested for equality, otherwise indexing on keys wouldn't work. `Hash` is required so that the type may be hashed by `HashMap`'s hashing algorithm. +In order to be used as a key in a [`HashMap`][HashMap], a type must implement the [`Eq`][Eq] and [`Hash`][Hash] traits. [`Eq`][Eq] is required because keys have to be capable of being tested for equality, otherwise indexing on keys wouldn't work. [`Hash`][Hash] is required so that the type may be hashed by [`HashMap`'s][HashMap] hashing algorithm. -[`f32`](https://doc.rust-lang.org/stable/std/primitive.f32.html) and [`f64`](https://doc.rust-lang.org/stable/std/primitive.f64.html) implement [`PartialEq`](https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html), but not `Eq` This is because one of the potential values for floating-point types is `NaN` (or "not a number"). Per the IEEE floating-point specification, `NaN` values are [not equal to any other floating-point value, and not equal to each other](https://en.wikipedia.org/wiki/NaN). This means there is no total equality relation for floating-point types, and thus that `f32` and `f64` can't implement `Eq` and can't used as keys in a `HashMap`. +[`f32`][f32] and [`f64`][f64] implement [`PartialEq`][PartialEq], but not [`Eq`][Eq] This is because one of the potential values for floating-point types is `NaN` (or "not a number"). Per the IEEE floating-point specification, `NaN` values are [not equal to any other floating-point value, and not equal to each other](https://en.wikipedia.org/wiki/NaN). This means there is no total equality relation for floating-point types, and thus that [`f32`][f32] and [`f64`][f64] can't implement [`Eq`][Eq] and can't used as keys in a [`HashMap`][HashMap]. ### How can I convert between numeric types? -There are two ways: the `as` keyword, which does simple casting for primitive types, and the [`Into`](https://doc.rust-lang.org/stable/std/convert/trait.Into.html) and [`From`](https://doc.rust-lang.org/stable/std/convert/trait.From.html) traits, which are implemented for a number of type conversions (and which you can implement for your own types). The `Into` and `From` traits are only implemented in cases where conversions are lossless, so for example, `f64::from(0f32)` will compile while `f32:from(0f64)` will not. On the other hand, `as` will convert between any two primitive types, truncating values as necessary. +There are two ways: the `as` keyword, which does simple casting for primitive types, and the [`Into`][Into] and [`From`][From] traits, which are implemented for a number of type conversions (and which you can implement for your own types). The [`Into`][Into] and [`From`][From] traits are only implemented in cases where conversions are lossless, so for example, `f64::from(0f32)` will compile while `f32:from(0f64)` will not. On the other hand, `as` will convert between any two primitive types, truncating values as necessary.

    Strings

    ### How can I convert a `String` or `Vec` to a slice (`&str` and `&[T]`)? -Using [Deref coercions](https://doc.rust-lang.org/stable/book/deref-coercions.html), [`String`s](https://doc.rust-lang.org/stable/std/string/struct.String.html) and [`Vec`s](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html) will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. +Using [Deref coercions](https://doc.rust-lang.org/stable/book/deref-coercions.html), [`String`s][String] and [`Vec`s][Vec] will automatically coerce to their respective slices when passed by reference with `&` or `& mut`. ### How can I convert from `&str` to `String` or the other way around? -The [`to_owned()`](https://doc.rust-lang.org/stable/std/borrow/trait.ToOwned.html#tymethod.to_owned) method converts from a [`&str`](https://doc.rust-lang.org/stable/std/primitive.str.html) into a [`String`](https://doc.rust-lang.org/stable/std/string/struct.String.html), and `String`s are automatically converted into `&str` when you borrow a reference to them. Both are demonstrated in the following example: +The [`to_owned()`][to_owned] method converts from a [`&str`][str] into a [`String`][String], and [`String`s][String] are automatically converted into [`&str`][str] when you borrow a reference to them. Both are demonstrated in the following example: ```rust fn main() { @@ -205,29 +205,29 @@ fn say_hello(name: &str) { ### What are the differences between the two different string types? -[`String`](https://doc.rust-lang.org/stable/std/string/struct.String.html) is an owned buffer of UTF-8 bytes allocated on the heap. Mutable `String`s can be modified, growing their capacity as needed. `&str` is a fixed-capacity "view" into a `String` allocated elsewhere, commonly on the heap, in the case of slices dereferenced from `String`s, or in static memory, in the case of string literals. +[`String`][String] is an owned buffer of UTF-8 bytes allocated on the heap. Mutable [`String`s][String] can be modified, growing their capacity as needed. [`&str`][str] is a fixed-capacity "view" into a [`String`][String] allocated elsewhere, commonly on the heap, in the case of slices dereferenced from [`String`s][String], or in static memory, in the case of string literals. -`&str` is a primitive type implemented by the Rust language, while `String` is implemented in the standard library. +[`&str`][str] is a primitive type implemented by the Rust language, while [`String`][String] is implemented in the standard library. ### How do I do O(1) character access in a `String`? You cannot. At least not without a firm understanding of what you mean by "character", and preprocessing the string to find the index of the desired character. -Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a "code unit" (in UTF-16, code units are 2 bytes; in UTF-32 they are 4 bytes). "Code points" are composed of one or more code units, and combine in "grapheme clusters" which most closely approximate characters. +Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a "code unit" (in UTF-16, code units are 2 bytes; in UTF-32 they are 4 bytes). "Code points" are composed of one or more code units, and combine in "grapheme clusters" which most closely approximate characters. -Thus, even though you may index on bytes in a UTF-8 string, you can't access the `i`th code point or grapheme cluster in constant time. However, if you know at which byte that desired code point or grapheme cluster begins, then you _can_ access it in constant time. Functions including `str::find()` and regex matches return byte indices, facilitating this sort of access. +Thus, even though you may index on bytes in a UTF-8 string, you can't access the `i`th code point or grapheme cluster in constant time. However, if you know at which byte that desired code point or grapheme cluster begins, then you _can_ access it in constant time. Functions including [`str::find()`][str__find] and regex matches return byte indices, facilitating this sort of access. ### Why are strings UTF-8 by default? -The `str` type is UTF-8 because we observe more text in the wild in this encoding – particularly in network transmissions, which are endian-agnostic – and we think it's best that the default treatment of I/O not involve having to recode codepoints in each direction. +The [`str`][str] type is UTF-8 because we observe more text in the wild in this encoding – particularly in network transmissions, which are endian-agnostic – and we think it's best that the default treatment of I/O not involve having to recode codepoints in each direction. This does mean that locating a particular Unicode codepoint inside a string is an O(n) operation, although if the starting byte index is already known then they can be accessed in O(1) as expected. On the one hand, this is clearly undesirable; on the other hand, this problem is full of trade-offs and we'd like to point out a few important qualifications: -Scanning a `str` for ASCII-range codepoints can still be done safely byte-at-a-time. If you use `.as_bytes()`, pulling out a `u8` costs only `O(1)` and produces a value that can be cast and compared to an ASCII-range `char`. So if you're (say) line-breaking on `'\n'`, byte-based treatment still works. UTF-8 was well-designed this way. +Scanning a [`str`][str] for ASCII-range codepoints can still be done safely byte-at-a-time. If you use [`.as_bytes()`][str__as_bytes], pulling out a [`u8`][u8] costs only `O(1)` and produces a value that can be cast and compared to an ASCII-range [`char`][char]. So if you're (say) line-breaking on `'\n'`, byte-based treatment still works. UTF-8 was well-designed this way. Most "character oriented" operations on text only work under very restricted language assumptions such as "ASCII-range codepoints only". Outside ASCII-range, you tend to have to use a complex (non-constant-time) algorithm for determining linguistic-unit (glyph, word, paragraph) boundaries anyway. We recommend using an "honest" linguistically-aware, Unicode-approved algorithm. -The `char` type is UTF32. If you are sure you need to do a codepoint-at-a-time algorithm, it's trivial to write a `type wstr = [char]`, and unpack a `str` into it in a single pass, then work with the `wstr`. In other words: the fact that the language is not "decoding to UTF32 by default" shouldn't stop you from decoding (or re-encoding any other way) if you need to work with that encoding. +The [`char`][char] type is UTF-32. If you are sure you need to do a codepoint-at-a-time algorithm, it's trivial to write a `type wstr = [char]`, and unpack a [`str`][str] into it in a single pass, then work with the `wstr`. In other words: the fact that the language is not "decoding to UTF32 by default" shouldn't stop you from decoding (or re-encoding any other way) if you need to work with that encoding. For a more in-depth explanation of why UTF-8 is usually preferable over UTF-16 or UTF-32, read the [UTF-8 Everywhere manifesto](http://utf8everywhere.org/). @@ -239,11 +239,11 @@ If your reason for implementing these data structures is to use them for other p If, however, [your reason is simply to learn](http://cglab.ca/~abeinges/blah/too-many-lists/book/), then you will likely need to dip into unsafe code. While these data structures _can_ be implemented entirely in safe Rust, the performance is likely to be worse than it would be with the use of unsafe code. The simple reason for this is that data structures like vectors and linked lists rely on pointer and memory operations that are disallowed in safe Rust. -For example, a doubly-linked list requires that there be two mutable references to each node, but this violates Rust's mutable reference aliasing rules. You can solve this using `Weak`, but the performance will be poorer than you likely want. With unsafe code you can bypass the mutable reference aliasing rule restriction, but must manually verify that your code introduces no memory safety violations. +For example, a doubly-linked list requires that there be two mutable references to each node, but this violates Rust's mutable reference aliasing rules. You can solve this using [`Weak`][Weak], but the performance will be poorer than you likely want. With unsafe code you can bypass the mutable reference aliasing rule restriction, but must manually verify that your code introduces no memory safety violations. ### How can I iterate over a collection without moving/consuming it? -The easiest way is by using the collection's `IntoIterator` implementation. Here is an example for `&Vec`: +The easiest way is by using the collection's [`IntoIterator`][IntoIterator] implementation. Here is an example for [`&Vec`][Vec]: ```rust let v = vec![1,2,3,4,5]; @@ -253,7 +253,7 @@ for item in &v { println!("\nLength: {}", v.len()); ``` -Rust `for` loops call `into_iter()` (defined on the `IntoIterator` trait) for whatever they're iterating over. Anything implementing the `IntoIterator` trait may be looped over with a `for` loop. `IntoIterator` is implemented for `&Vec` and `&mut Vec`, causing the iterator from `into_iter()` to borrow the contents of the collection, rather than moving/consuming them. The same is true for other standard collections as well. +Rust `for` loops call `into_iter()` (defined on the [`IntoIterator`][IntoIterator] trait) for whatever they're iterating over. Anything implementing the [`IntoIterator`][IntoIterator] trait may be looped over with a `for` loop. [`IntoIterator`][IntoIterator] is implemented for [`&Vec`][Vec] and [`&mut Vec`][Vec], causing the iterator from `into_iter()` to borrow the contents of the collection, rather than moving/consuming them. The same is true for other standard collections as well. If a moving/consuming iterator is desired, write the `for` loop without `&` or `&mut` in the iteration. @@ -261,7 +261,7 @@ If a moving/consuming iterator is desired, write the `for` loop without `&` or ` You don't necessarily have to. If you're declaring an array directly, the size is inferred based on the number of elements. But if you're declaring a function that takes an array, the compiler has to know how big that array will be. -One thing to note is that currently Rust doesn't offer generics over arrays of different size. If you'd like to accept a contiguous container of a variable number of values, use a `Vec` or slice (depending on whether you need ownership). +One thing to note is that currently Rust doesn't offer generics over arrays of different size. If you'd like to accept a contiguous container of a variable number of values, use a [`Vec`][Vec] or slice (depending on whether you need ownership).

    Ownership

    @@ -269,12 +269,12 @@ One thing to note is that currently Rust doesn't offer generics over arrays of d There are four major options: -- You can implement it using `Rc` and `Weak` to allow shared ownership of nodes, +- You can implement it using [`Rc`][Rc] and [`Weak`][Weak] to allow shared ownership of nodes, although this approach pays the cost of memory management. - You can implement it using `unsafe` code using raw pointers. This will be more efficient, but bypasses Rust's safety guarantees. - Using vectors and indices into those vectors. There are [several](http://smallcultfollowing.com/babysteps/blog/2015/04/06/modeling-graphs-in-rust-using-vector-indices/) [available](http://featherweightmusings.blogspot.com/2015/04/graphs-in-rust.html) examples and explanations of this approach. -- Using borrowed references with `UnsafeCell`. There are [explanations and code](https://github.com/nrc/r4cppp/blob/master/graphs/README.md#node-and-unsafecell) available for this approach. +- Using borrowed references with [`UnsafeCell`][UnsafeCell]. There are [explanations and code](https://github.com/nrc/r4cppp/blob/master/graphs/README.md#node-and-unsafecell) available for this approach. ### How can I define a struct that contains a pointer to one of its own fields? @@ -308,13 +308,13 @@ These are different terms for the same thing. In both cases, it means the value ### Why can values of some types be used after passing them to a function, while reuse of values of other types results in an error? -If a type implements the `Copy` trait, then it will be copied when passed to a function. All numeric types in Rust implement `Copy`, but struct types do not implement `Copy` by default, so they are moved instead. This means that the struct can no longer be used elsewhere, unless it is moved back out of the function via the return. +If a type implements the [`Copy`][Copy] trait, then it will be copied when passed to a function. All numeric types in Rust implement [`Copy`][Copy], but struct types do not implement [`Copy`][Copy] by default, so they are moved instead. This means that the struct can no longer be used elsewhere, unless it is moved back out of the function via the return. ### How do you deal with a "use of moved value" error? -This error means that the value you're trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary: if it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. Otherwise if the type being moved implements `Clone`, then calling `clone()` on it before moving will move a copy of it, leaving the original still available for further use. Note though that cloning a value should typically be the last resort since cloning can be expensive, causing further allocations. +This error means that the value you're trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary: if it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. Otherwise if the type being moved implements [`Clone`][Clone], then calling `clone()` on it before moving will move a copy of it, leaving the original still available for further use. Note though that cloning a value should typically be the last resort since cloning can be expensive, causing further allocations. -If the moved value is of your own custom type, consider implementing `Copy` (for implicit copying, rather than moving) or `Clone` (explicit copying). `Copy` is most commonly implemented with `#[derive(Copy, Clone)]` (`Copy` requires `Clone`), and `Clone` with `#[derive(Clone)]`. +If the moved value is of your own custom type, consider implementing [`Copy`][Copy] (for implicit copying, rather than moving) or [`Clone`][Clone] (explicit copying). [`Copy`][Copy] is most commonly implemented with `#[derive(Copy, Clone)]` ([`Copy`][Copy] requires [`Clone`][Clone]), and [`Clone`][Clone] with `#[derive(Clone)]`. If none of these are possible, you may want to modify the function that acquired ownership to return ownership of the value when the function exits. @@ -337,7 +337,7 @@ While the rules themselves are simple, following them consistently is not, parti The first step in understanding the borrow checker is reading the errors it produces. A lot of work has been put into making sure the borrow checker provides quality assistance in resolving the issues it identifies. When you encounter a borrow checker problem, the first step is to slowly and carefully read the error reported, and to only approach the code after you understand the error being described. -The second step is to become familiar with the ownership and mutability-related container types provided by the Rust standard library, including `Cell`, `RefCell`, and `Cow`. These are useful and necessary tools for expressing certain ownership and mutability sutations, and have been written to be of minimal performance cost. +The second step is to become familiar with the ownership and mutability-related container types provided by the Rust standard library, including [`Cell`][Cell], [`RefCell`][RefCell], and [`Cow`][Cow]. These are useful and necessary tools for expressing certain ownership and mutability sutations, and have been written to be of minimal performance cost. The single most important part of understanding the borrow checker is practice. Rust's strong static analyses guarantees are strict and quite different from what many programmers have worked with before. It will take some time to become completely comfortable with everything. @@ -345,7 +345,7 @@ If you find yourself struggling with the borrow checker, or running out of patie ### How do deref coercions work? -[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`](https://doc.rust-lang.org/stable/std/ops/trait.Deref.html) trait. +[Deref coercions](https://doc.rust-lang.org/book/deref-coercions.html) exist to make using Rust more ergonomic, and are implemented via the [`Deref`][Deref] trait. A Deref implementation indicates that the implementing type may be converted into a target by a call to the `deref` method, which takes an immutable reference to the calling type and returns a reference (of the same lifetime) to the target type. The `*` prefix operator is shorthand for the `deref` method. @@ -369,7 +369,7 @@ The `'a` syntax comes from the ML family of programming languages, where `'a` is ### When is `Rc` useful? -This is covered in the [official documentation for `Rc`](https://doc.rust-lang.org/stable/std/rc/), Rust's non-atomically reference-counted pointer type. In short, `Rc` and its thread-safe cousin `Arc` are useful to express shared ownership, and have the system automatically deallocate the associated memory when no one has access to it. +This is covered in the official documentation for [`Rc`][Rc], Rust's non-atomically reference-counted pointer type. In short, [`Rc`][Rc] and its thread-safe cousin [`Arc`][Arc] are useful to express shared ownership, and have the system automatically deallocate the associated memory when no one has access to it. ### How do I return a borrow to something I created from a function? @@ -388,7 +388,7 @@ fn create_borrowed<'a>(pool: &'a Pool, } ``` -An alternative is to eliminate the references entirely by returning an owning type like `String`: +An alternative is to eliminate the references entirely by returning an owning type like [`String`][String]: ```rust fn happy_birthday(name: &str, age: i64) -> String { @@ -398,7 +398,7 @@ fn happy_birthday(name: &str, age: i64) -> String { This approach is simpler, but often results in unnecessary allocations. -There is also the `Cow` ("copy on write") type, which will only do the extra allocation if you attempt to mutate the contained value: +There is also the [`Cow`][Cow] ("copy on write") type, which will only do the extra allocation if you attempt to mutate the contained value: ```rust use std::borrow::Cow; @@ -416,7 +416,7 @@ fn abs_all(input: &mut Cow<[i32]>) { ### How do I return a closure from a function? -To return a closure from a function, it must be a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own copy of the captured variables, independent of its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer valid; put another way: it would allow reading potentially invalid memory. The closure must also be wrapped in a `Box`, so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). +To return a closure from a function, it must be a "move closure", meaning that the closure is declared with the `move` keyword. As [explained in the Rust book](https://doc.rust-lang.org/book/closures.html#move-closures), this gives the closure its own copy of the captured variables, independent of its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer valid; put another way: it would allow reading potentially invalid memory. The closure must also be wrapped in a [`Box`][Box], so that it is allocated on the heap. Read more about this [in the book](https://doc.rust-lang.org/book/closures.html#returning-closures). ### When are lifetimes required to be explicit? @@ -434,7 +434,7 @@ The only way to construct a value of type `&Foo` or `&mut Foo` is to specify an ### How do I express the absence of a value without `null`? -You can do that with the [`Option`](https://doc.rust-lang.org/stable/std/option/index.html) type, which can either be `Some(T)` or `None`. `Some(T)` indicates that a value of type `T` is contained within, while `None` indicates the absence of a value. +You can do that with the [`Option`][Option] type, which can either be `Some(T)` or `None`. `Some(T)` indicates that a value of type `T` is contained within, while `None` indicates the absence of a value.

    Generics

    @@ -448,17 +448,17 @@ Functions that accept [trait objects](http://doc.rust-lang.org/book/trait-object Functions and closures are operationally equivalent, but have different runtime representations due to their differing implementations. -Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: `Fn`, `FnMut`, and `FnOnce`. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the struct can be called as a function. Bare functions can not capture an environment. +Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: [`Fn`][Fn], [`FnMut`][FnMut], and [`FnOnce`][FnOnce]. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the struct can be called as a function. Bare functions can not capture an environment. -The big difference between these traits is how they take the `self` parameter. `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. +The big difference between these traits is how they take the `self` parameter. [`Fn`][Fn] takes `&self`, [`FnMut`][FnMut] takes `&mut self`, and [`FnOnce`][FnOnce] takes `self`. Even if a closure does not capture any environment variables, it is represeted at runtime as two points, same as any other closure. ### What are higher-kinded types, why would I want them, and why doesn't Rust have them? -Higher-kinded types are typed with unfilled parameters. Type constructors, like `Vec`, `Result`, and `HashMap` are all examples of higher-kinded types. Support for higher-kinded types means these "incomplete" types may be used anywhere "complete" types can be used, such as trait `impl`s. +Higher-kinded types are typed with unfilled parameters. Type constructors, like [`Vec`][Vec], [`Result`][Result], and [`HashMap`][HashMap] are all examples of higher-kinded types. Support for higher-kinded types means these "incomplete" types may be used anywhere "complete" types can be used, such as trait `impl`s. -Any complete type, like `i32`, `bool`, or `char` is of kind `*`. A type with one parameter, like `Vec` is of kind `* -> *`, meaning that `Vec` takes in a complete type like `i32` and returns a complete type `Vec`. A type which three parameters, like `HashMap` is of kind `* -> * -> * -> *`, and takes in three complete types (like `i32`, `String`, and `RandomState`) to produce a new complete type `HashMap`. +Any complete type, like [`i32`][i32], [`bool`][bool], or [`char`][char] is of kind `*`. A type with one parameter, like [`Vec`][Vec] is of kind `* -> *`, meaning that [`Vec`][Vec] takes in a complete type like [`i32`][i32] and returns a complete type `Vec`. A type which three parameters, like [`HashMap`][HashMap] is of kind `* -> * -> * -> *`, and takes in three complete types (like [`i32`][32], [`String`][String], and [`RandomState`][RandomState]) to produce a new complete type `HashMap`. The lack of support for higher-kinded types makes expression of certain ideas more tedious than it would otherwise be. For example, implementing a `Functor` trait (a term for a container which can be mapped over, obeying certain rules) without higher-kinded types requires explicit and otherwise unnecessary handling of the container's type parameters. With higher-kined types, a `Functor` `impl` can ignore the parameters entirely. @@ -472,7 +472,7 @@ Associated types exist because, for a generic type with some type parameters, it ### Can I overload operators? Which ones and how? -You can provide custom implementations for a variety of operators using their associated traits: `Add` for `+`, `Mul` for `*`. It looks like this: +You can provide custom implementations for a variety of operators using their associated traits: [`Add`][Add] for `+`, [`Mul`][Mul] for `*`. It looks like this: ```rust use std::ops::Add; @@ -490,53 +490,36 @@ impl Add for Foo { The following operators can be overloaded: -| Operation | Trait | -|:--------------------|:-------------| -| `+` | [`Add`] | -| `binary -` | [`Sub`] | -| `*` | [`Mul`] | -| `/` | [`Div`] | -| `unary -` | [`Neg`] | -| `%` | [`Rem`] | -| `&` | [`BitAnd`] | -| | | [`BitOr`] | -| `^` | [`BitXor`] | -| `!` | [`Not`] | -| `<<` | [`Shl`] | -| `>>` | [`Shr`] | -| `*` | [`Deref`] | -| `mut *` | [`DerefMut`] | -| `[]` | [`Index`] | -| `mut []` | [`IndexMut`] | - -[`Add`]: https://doc.rust-lang.org/stable/std/ops/trait.Add.html -[`Sub`]: https://doc.rust-lang.org/stable/std/ops/trait.Sub.html -[`Mul`]: https://doc.rust-lang.org/stable/std/ops/trait.Mul.html -[`Div`]: https://doc.rust-lang.org/stable/std/ops/trait.Div.html -[`Neg`]: https://doc.rust-lang.org/stable/std/ops/trait.Neg.html -[`Rem`]: https://doc.rust-lang.org/stable/std/ops/trait.Rem.html -[`BitAnd`]: https://doc.rust-lang.org/stable/std/ops/trait.BitAnd.html -[`BitOr`]: https://doc.rust-lang.org/stable/std/ops/trait.BitOr.html -[`BitXor`]: https://doc.rust-lang.org/stable/std/ops/trait.BitXor.html -[`Not`]: https://doc.rust-lang.org/stable/std/ops/trait.Not.html -[`Shl`]: https://doc.rust-lang.org/stable/std/ops/trait.Shl.html -[`Shr`]: https://doc.rust-lang.org/stable/std/ops/trait.Shr.html -[`Deref`]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html -[`DerefMut`]: https://doc.rust-lang.org/stable/std/ops/trait.DerefMut.html -[`Index`]: https://doc.rust-lang.org/stable/std/ops/trait.Index.html -[`IndexMut`]: https://doc.rust-lang.org/stable/std/ops/trait.IndexMut.html +| Operation | Trait | +|:--------------------|:-----------------------| +| `+` | [`Add`][Add] | +| `binary -` | [`Sub`][Sub] | +| `*` | [`Mul`][Mul] | +| `/` | [`Div`][Div] | +| `unary -` | [`Neg`][Neg] | +| `%` | [`Rem`][Rem] | +| `&` | [`BitAnd`][BitAnd] | +| | | [`BitOr`][BitOr] | +| `^` | [`BitXor`][BitXor] | +| `!` | [`Not`][Not] | +| `<<` | [`Shl`][Shl] | +| `>>` | [`Shr`][Shr] | +| `*` | [`Deref`][Deref] | +| `mut *` | [`DerefMut`][DerefMut] | +| `[]` | [`Index`][Index] | +| `mut []` | [`IndexMut`][IndexMut] | ### Why the split between `Eq`/`PartialEq` and `Ord`/`PartialOrd`? There are some types in Rust whose values are only partially ordered, or have only partial equality. Partial ordering means that there may be values of the given type that are neither less than nor greater than each other. Partial equality means that there may be values of the given type that are not equal to themselves. -Floating point types (`f32` and `f64`) are good examples of each. Any floating point type may have the value `NaN` (meaning "not a number"). `NaN` is not equal to itself (`NaN == Nan` is false), and not less than or greater than any other floating point value. As such, both `f32` and `f64` implement `PartialOrd` and `PartialEq` but not `Ord` and not `Eq`. +Floating point types ([`f32`][f32] and [`f64`][f64]) are good examples of each. Any floating point type may have the value `NaN` (meaning "not a number"). `NaN` is not equal to itself (`NaN == Nan` is false), and not less than or greater than any other floating point value. As such, both [`f32`][f32] and [`f64`][f64] implement [`PartialOrd`][PartialOrd] and [`PartialEq`][PartialEq] but not [`Ord`][Ord] and not [`Eq`][Eq].

    Input / Output

    ### How do I read a file into a `String`? -Using the `read_to_string()` method, which is defined on the `Read` trait in `std::io`. +Using the [`read_to_string()`][read__read_to_string] method, which is defined on the [`Read`][Read] trait in [`std::io`][std-io]. ```rust fn read_file(path: &str) -> Result { @@ -556,13 +539,13 @@ fn main() { ### How do I read file input efficiently? -The [`File` type](https://doc.rust-lang.org/stable/std/fs/struct.File.html) implements the `Read` trait, which has a variety of functions for reading and writing data, including `read()`, `read_to_end()`, `bytes()`, `chars()`, and `take()`. Each of these functions reads a certain amount of input from a given file. `read()` reads as much input as the underlying system will provide in a single call. `read_to_end()` reads the entire buffer into a vector, allocating as much space as is needed. `bytes()` and `chars()` allow you to iterate over the bytes and characters of the file, respectively. Finally, `take()` allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need. +The [`File`][File] type implements the [`Read`][Read] trait, which has a variety of functions for reading and writing data, including [`read()`][read__read], [`read_to_end()`][read__read_to_end], [`bytes()`][read__bytes], [`chars()`][read__chars], and [`take()`][read__take]. Each of these functions reads a certain amount of input from a given file. [`read()`][read__read] reads as much input as the underlying system will provide in a single call. [`read_to_end()`][read__read_to_end] reads the entire buffer into a vector, allocating as much space as is needed. [`bytes()`][read__bytes] and [`chars()`][read__chars] allow you to iterate over the bytes and characters of the file, respectively. Finally, [`take()`][read__take] allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need. -For buffered reads, use the [`BufReader`](http://doc.rust-lang.org/stable/std/io/struct.BufReader.html) struct, which helps to reduce the number of system calls when reading. +For buffered reads, use the [`BufReader`][BufReader] struct, which helps to reduce the number of system calls when reading. ### How do I get command line arguments in Rust? -The easiest way is to use `std::env::Args`, which provides an iterator over the input arguments. +The easiest way is to use [`Args`][Args], which provides an iterator over the input arguments. If you're looking for something more powerful, there are a [number of options on crates.io](https://crates.io/keywords/argument). @@ -576,23 +559,23 @@ Rust prefers a type-based approach to error handling, which is [covered at lengt ### What's the deal with `unwrap()` everywhere? -`unwrap()` is a function that extracts the value inside an `Option` or `Result` and panics if no value is present. It is useful in the presence of truly unrecoverable errors, but is more useful for quick prototypes where you don't want to handle an error yet, or blog posts where error handling would distract from the main point. `unwrap()` shouldn't be your default way to handle errors, but it is a useful tool to have. +`unwrap()` is a function that extracts the value inside an [`Option`][Option] or [`Result`][Result] and panics if no value is present. It is useful in the presence of truly unrecoverable errors, but is more useful for quick prototypes where you don't want to handle an error yet, or blog posts where error handling would distract from the main point. `unwrap()` shouldn't be your default way to handle errors, but it is a useful tool to have. ### Why do I get an error when I try to run example code that uses the `try!` macro? -It's probably an issue with the function's return type. The [`try!` macro](https://doc.rust-lang.org/stable/std/macro.try!.html) either extracts the value from a `Result`, or returns early with the error `Result` is carrying. This means that `try` only works for functions that return `Result` themselves, where the `Err`-constructed type implements `From::from(err)`. In particular, this means that the `try!` macro cannot work inside the `main` function. +It's probably an issue with the function's return type. The [`try!`][TryMacro] macro either extracts the value from a [`Result`][Result], or returns early with the error [`Result`][Result] is carrying. This means that [`try`][TryMacro] only works for functions that return [`Result`][Result] themselves, where the `Err`-constructed type implements `From::from(err)`. In particular, this means that the [`try!`][TryMacro] macro cannot work inside the `main` function. ### Is there an easier way to do error handling than having `Result`s everywhere? -If you're looking for a way to avoid handling `Result`s in other people's code, there's always `unwrap()`, but it's probably not what you want. `Result` is an indicator that some computation may or may not complete successfully. Requiring you to handle these failures explicitly is one of the ways that Rust encourages robustness. If you really don't want to handle an error, use `unwrap()`, but know that doing so means that the given code will cause the entire process to panic on failure, which is usually undesirable. +If you're looking for a way to avoid handling [`Result`s][Result] in other people's code, there's always [`unwrap()`][unwrap], but it's probably not what you want. [`Result`][Result] is an indicator that some computation may or may not complete successfully. Requiring you to handle these failures explicitly is one of the ways that Rust encourages robustness. If you really don't want to handle an error, use [`unwrap()`][unwrap], but know that doing so means that the given code will cause the entire process to panic on failure, which is usually undesirable.

    Concurrency

    ### Can I use static values across threads without an `unsafe` block? -Mutation is safe if it's synchronized. Mutating a static `Mutex` (lazily initialized via the [lazy-static](https://crates.io/crates/lazy_static/) crate) does not require an `unsafe` block, nor does mutating a static `AtomicUsize` (which can be initialized without lazy_static). +Mutation is safe if it's synchronized. Mutating a static [`Mutex`][Mutex] (lazily initialized via the [lazy-static](https://crates.io/crates/lazy_static/) crate) does not require an `unsafe` block, nor does mutating a static [`AtomicUsize`][AtomicUsize] (which can be initialized without lazy_static). -More generally, if a type implements `Sync` and does not implement `Drop`, it [can be used in a `static`](https://doc.rust-lang.org/book/const-and-static.html#static). +More generally, if a type implements [`Sync`][Sync] and does not implement [`Drop`][Drop], it [can be used in a `static`](https://doc.rust-lang.org/book/const-and-static.html#static).

    Macros

    @@ -608,15 +591,15 @@ Rust programs can be debugged using [gdb](http://sourceware.org/gdb/current/onli ### `rustc` said a panic occurred in standard library code. How do I locate the mistake in my code? -This error is usually caused by `unwrap()`ing a `None` or `Err` in client code. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build`) is also helpful. Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful. +This error is usually caused by [`unwrap()`ing][unwrap] a `None` or `Err` in client code. Enabling backtraces by setting the environment variable `RUST_BACKTRACE=1` helps with getting more information. Compiling in debug mode (the default for `cargo build`) is also helpful. Using a debugger like the provided `rust-gdb` or `rust-lldb` is also helpful.

    Low-Level

    ### How do I `memcpy` bytes? -If you want to clone an existing slice safely, you can use `std::slice::clone_from_slice`. This function is currently unstable, but [should be stabilized soon](https://internals.rust-lang.org/t/stabilizing-basic-functions-on-arrays-and-slices/2868). +If you want to clone an existing slice safely, you can use [`clone_from_slice`][clone_from_slice]. This function is currently unstable, but [should be stabilized soon](https://internals.rust-lang.org/t/stabilizing-basic-functions-on-arrays-and-slices/2868). -To copy potentially overlapping bytes, use `std::ptr::copy`. To copy nonoverlapping bytes, use `std::ptr::cpy_nonoverlapping`. Both of these functions are `unsafe`, as both can be used to subvert the language's safety guarantees. Take care when using them. +To copy potentially overlapping bytes, use [`copy`][copy]. To copy nonoverlapping bytes, use [`cpy_nonoverlapping`][copy_nonoverlapping]. Both of these functions are `unsafe`, as both can be used to subvert the language's safety guarantees. Take care when using them. ### Can Rust function reasonably without the standard library? @@ -825,7 +808,7 @@ That depends. There _are_ ways of translating object-oriented concepts like [mul ### How do I handle configuration of a struct with optional parameters? -The easiest way is to use the `Option` type in whatever function you're using to construct instances of the struct (usually `new()`). Another way is to use the [builder pattern](https://aturon.github.io/ownership/builders.html), where only certain functions instantiating member variables must be called before the construction of the built type. +The easiest way is to use the [`Option`][Option] type in whatever function you're using to construct instances of the struct (usually `new()`). Another way is to use the [builder pattern](https://aturon.github.io/ownership/builders.html), where only certain functions instantiating member variables must be called before the construction of the built type. ### How do I do global variables in Rust? @@ -901,7 +884,7 @@ The notions of a "move" in Rust and a "move" in C++ are quite different, owing t In C++, R-value references come from a temporary value, or are explicitly created from a named value via `std::move`. In this way, C++ enforces that no mutable references exist to the moved-out value, so that the memory may be safely invalidated. In Rust, mutable aliases are statically eliminated by the borrow checker, and so the rough equivalent of C++'s R-values are found in Rust's mutable references (`&mut`), which can only be used if no other mutable alias already exists to the given memory location. -Rust "move"s are about transferring ownership, rather than eliminating mutable aliases (which are handled via the borrow checker). By default, the ownership of any function parameter is transferred into the function and out of the parameter at the call site, unless that parameter's type implements the `Copy` trait, in which case a shallow copy of the value is used to instantiate the actual parameter of the function. Rust's "move"s are often unecessary and undesirable. If the function you're writing does not require ownership of the value being passed in, that value should probably be borrowed (mutably or immutably, as necessary) rather than moved or copied. +Rust "move"s are about transferring ownership, rather than eliminating mutable aliases (which are handled via the borrow checker). By default, the ownership of any function parameter is transferred into the function and out of the parameter at the call site, unless that parameter's type implements the [`Copy`][Copy] trait, in which case a shallow copy of the value is used to instantiate the actual parameter of the function. Rust's "move"s are often unecessary and undesirable. If the function you're writing does not require ownership of the value being passed in, that value should probably be borrowed (mutably or immutably, as necessary) rather than moved or copied. ### How can I interoperate with C++ from Rust, or with Rust from C++? @@ -931,7 +914,7 @@ impl Foo { ### Does Rust have copy constructors? -Not exactly. Types which implement `Copy` will do a standard C-like "shallow copy" with no extra work (similar to "plain old data" in C++). It is impossible to implement `Copy` types that require custom copy behavior. Instead, in Rust "copy constructors" are created by implementing the `Clone` trait, and explicitly calling the `clone` method. Making user-defined copy operators explicit surfaces the underlying complexity, forcing the developer to opt-in to potentially expensive operations. +Not exactly. Types which implement [`Copy`][Copy] will do a standard C-like "shallow copy" with no extra work (similar to "plain old data" in C++). It is impossible to implement [`Copy`][Copy] types that require custom copy behavior. Instead, in Rust "copy constructors" are created by implementing the [`Clone`][Clone] trait, and explicitly calling the [`clone`][clone] method. Making user-defined copy operators explicit surfaces the underlying complexity, forcing the developer to opt-in to potentially expensive operations. ### Does Rust have move constructors? @@ -1058,3 +1041,81 @@ The Apache license includes important protection against patent aggression, but This is partly due to preference of the original developer (Graydon), and partly due to the fact that languages tend to have a wider audience and more diverse set of possible embeddings and end-uses than products such as web browsers. We'd like to appeal to as many of those potential contributors as possible. +[Vec]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html +[HashMap]: https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html +[Into]: https://doc.rust-lang.org/stable/std/convert/trait.Into.html +[From]: https://doc.rust-lang.org/stable/std/convert/trait.From.html +[Eq]: https://doc.rust-lang.org/stable/std/cmp/trait.Eq.html +[PartialEq]: https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html +[Ord]: https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html +[PartialOrd]: https://doc.rust-lang.org/stable/std/cmp/trait.PartialOrd.html +[f32]: https://doc.rust-lang.org/stable/std/primitive.f32.html +[f64]: https://doc.rust-lang.org/stable/std/primitive.f64.html +[i32]: https://doc.rust-lang.org/stable/std/primitive.i32.html +[i64]: https://doc.rust-lang.org/stable/std/primitive.i64.html +[bool]: https://doc.rust-lang.org/stable/std/primitive.bool.html +[Hash]: https://doc.rust-lang.org/stable/std/hash/trait.Hash.html +[BTreeMap]: https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html +[VecMacro]: https://doc.rust-lang.org/stable/std/macro.vec!.html +[String]: https://doc.rust-lang.org/stable/std/string/struct.String.html +[to_owned]: https://doc.rust-lang.org/stable/std/borrow/trait.ToOwned.html#tymethod.to_owned +[str]: https://doc.rust-lang.org/stable/std/primitive.str.html +[str__find]: https://doc.rust-lang.org/stable/std/primitive.str.html#method.find +[str__as_bytes]: https://doc.rust-lang.org/stable/std/primitive.str.html#method.as_bytes +[u8]: https://doc.rust-lang.org/stable/std/primitive.u8.html +[char]: https://doc.rust-lang.org/stable/std/primitive.char.html +[Weak]: https://doc.rust-lang.org/stable/std/rc/struct.Weak.html +[IntoIterator]: https://doc.rust-lang.org/stable/std/iter/trait.IntoIterator.html +[Rc]: https://doc.rust-lang.org/stable/std/rc/struct.Rc.html +[UnsafeCell]: https://doc.rust-lang.org/stable/std/cell/struct.UnsafeCell.html +[Copy]: https://doc.rust-lang.org/stable/std/marker/trait.Copy.html +[Clone]: https://doc.rust-lang.org/stable/std/clone/trait.Clone.html +[Cell]: https://doc.rust-lang.org/stable/std/cell/struct.Cell.html +[RefCell]: https://doc.rust-lang.org/stable/std/cell/struct.RefCell.html +[Cow]: https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html +[Deref]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html +[Arc]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html +[Box]: https://doc.rust-lang.org/stable/std/boxed/struct.Box.html +[Option]: https://doc.rust-lang.org/stable/std/option/enum.Option.html +[Fn]: https://doc.rust-lang.org/stable/std/ops/trait.Fn.html +[FnMut]: https://doc.rust-lang.org/stable/std/ops/trait.FnMut.html +[FnOnce]: https://doc.rust-lang.org/stable/std/ops/trait.FnOnce.html +[Result]: https://doc.rust-lang.org/stable/std/result/enum.Result.html +[RandomState]: https://doc.rust-lang.org/stable/std/collections/hash_map/struct.RandomState.html +[Add]: https://doc.rust-lang.org/stable/std/ops/trait.Add.html +[Sub]: https://doc.rust-lang.org/stable/std/ops/trait.Sub.html +[Mul]: https://doc.rust-lang.org/stable/std/ops/trait.Mul.html +[Div]: https://doc.rust-lang.org/stable/std/ops/trait.Div.html +[Neg]: https://doc.rust-lang.org/stable/std/ops/trait.Neg.html +[Rem]: https://doc.rust-lang.org/stable/std/ops/trait.Rem.html +[BitAnd]: https://doc.rust-lang.org/stable/std/ops/trait.BitAnd.html +[BitOr]: https://doc.rust-lang.org/stable/std/ops/trait.BitOr.html +[BitXor]: https://doc.rust-lang.org/stable/std/ops/trait.BitXor.html +[Not]: https://doc.rust-lang.org/stable/std/ops/trait.Not.html +[Shl]: https://doc.rust-lang.org/stable/std/ops/trait.Shl.html +[Shr]: https://doc.rust-lang.org/stable/std/ops/trait.Shr.html +[Deref]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html +[DerefMut]: https://doc.rust-lang.org/stable/std/ops/trait.DerefMut.html +[Index]: https://doc.rust-lang.org/stable/std/ops/trait.Index.html +[IndexMut]: https://doc.rust-lang.org/stable/std/ops/trait.IndexMut.html +[read__read_to_string]: https://doc.rust-lang.org/stable/std/io/trait.Read.html#method.read_to_string +[Read]: https://doc.rust-lang.org/stable/std/io/trait.Read.html +[std-io]: https://doc.rust-lang.org/stable/std/io/index.html +[File]: https://doc.rust-lang.org/stable/std/fs/struct.File.html +[read__read]: https://doc.rust-lang.org/stable/std/io/trait.Read.html#tymethod.read +[read__read_to_end]: https://doc.rust-lang.org/stable/std/io/trait.Read.html#method.read_to_end +[read__bytes]: https://doc.rust-lang.org/stable/std/io/trait.Read.html#method.bytes +[read__chars]: https://doc.rust-lang.org/stable/std/io/trait.Read.html#method.chars +[read__take]: https://doc.rust-lang.org/stable/std/io/trait.Read.html#method.take +[BufReader]: https://doc.rust-lang.org/stable/std/io/struct.BufReader.html +[Args]: https://doc.rust-lang.org/stable/std/env/struct.Args.html +[TryMacro]: https://doc.rust-lang.org/stable/std/macro.try!.html +[unwrap]: https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.unwrap +[Mutex]: https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html +[AtomicUsize]: https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html +[Sync]: https://doc.rust-lang.org/stable/std/marker/trait.Sync.html +[Drop]: https://doc.rust-lang.org/stable/std/ops/trait.Drop.html +[clone_from_slice]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.clone_from_slice +[copy]: https://doc.rust-lang.org/stable/std/ptr/fn.copy.html +[copy_nonoverlapping]: https://doc.rust-lang.org/stable/std/ptr/fn.copy_nonoverlapping.html +[clone]: https://doc.rust-lang.org/stable/std/clone/trait.Clone.html#tymethod.clone