Skip to content

Remove short intro from README #29611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 3 additions & 153 deletions src/doc/trpl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,158 +41,8 @@ Copious cross-linking connects these parts together.

### Contributing

The source files from which this book is generated can be found on GitHub:
[github.com/rust-lang/rust/tree/master/src/doc/trpl](https://github.com/rust-lang/rust/tree/master/src/doc/trpl)
The source files from which this book is generated can be found on
[GitHub][trpl].

## A brief introduction to Rust
[trpl]: https://github.com/rust-lang/rust/tree/master/src/doc/trpl

Is Rust a language you might be interested in? Let’s examine a few small code
samples to show off a few of its strengths.

The main concept that makes Rust unique is called ‘ownership’. Consider this
small example:

```rust
fn main() {
let mut x = vec!["Hello", "world"];
}
```

This program makes a [variable binding][var] named `x`. The value of this
binding is a `Vec<T>`, a ‘vector’, that we create through a [macro][macro]
defined in the standard library. This macro is called `vec`, and we invoke
macros with a `!`. This follows a general principle of Rust: make things
explicit. Macros can do significantly more complicated things than function
calls, and so they’re visually distinct. The `!` also helps with parsing,
making tooling easier to write, which is also important.

We used `mut` to make `x` mutable: bindings are immutable by default in Rust.
We’ll be mutating this vector later in the example.

It’s also worth noting that we didn’t need a type annotation here: while Rust
is statically typed, we didn’t need to explicitly annotate the type. Rust has
type inference to balance out the power of static typing with the verbosity of
annotating types.

Rust prefers stack allocation to heap allocation: `x` is placed directly on the
stack. However, the `Vec<T>` type allocates space for the elements of the vector
on the heap. If you’re not familiar with this distinction, you can ignore it for
now, or check out [‘The Stack and the Heap’][heap]. As a systems programming
language, Rust gives us the ability to control how our memory is allocated, but
when we’re getting started, it’s less of a big deal.

[var]: variable-bindings.html
[macro]: macros.html
[heap]: the-stack-and-the-heap.html

Earlier, we mentioned that ‘ownership’ is the key new concept in Rust. In Rust
parlance, `x` is said to ‘own’ the vector. This means that when `x` goes out of
scope, the vector’s memory will be de-allocated. This is done deterministically
by the Rust compiler, rather than through a mechanism such as a garbage
collector. In other words, in Rust, we don’t call functions like `malloc` and
`free` ourselves: the compiler statically determines when we need to allocate or
deallocate memory, and inserts those calls itself. To err is to be human, but
compilers never forget.

Let’s add another line to our example:

```rust
fn main() {
let mut x = vec!["Hello", "world"];

let y = &x[0];
}
```

We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to the
first element of the vector. Rust’s references are similar to pointers in other
languages, but with additional compile-time safety checks. References interact
with the ownership system by [‘borrowing’][borrowing] what they point to, rather
than owning it. The difference is, when the reference goes out of scope, it
won't deallocate the underlying memory. If it did, we’d de-allocate twice, which
is bad!

[borrowing]: references-and-borrowing.html

Let’s add a third line. It looks innocent enough, but causes a compiler error:

```rust,ignore
fn main() {
let mut x = vec!["Hello", "world"];

let y = &x[0];

x.push("foo");
}
```

`push` is a method on vectors that appends another element to the end of the
vector. When we try to compile this program, we get an error:

```text
error: cannot borrow `x` as mutable because it is also borrowed as immutable
x.push("foo");
^
note: previous borrow of `x` occurs here; the immutable borrow prevents
subsequent moves or mutable borrows of `x` until the borrow ends
let y = &x[0];
^
note: previous borrow ends here
fn main() {

}
^
```

Whew! The Rust compiler gives quite detailed errors at times, and this is one
of those times. As the error explains, while we made our binding mutable, we
still can't call `push`. This is because we already have a reference to an
element of the vector, `y`. Mutating something while another reference exists
is dangerous, because we may invalidate the reference. In this specific case,
when we create the vector, we may have only allocated space for two elements.
Adding a third would mean allocating a new chunk of memory for all those elements,
copying the old values over, and updating the internal pointer to that memory.
That all works just fine. The problem is that `y` wouldn’t get updated, and so
we’d have a ‘dangling pointer’. That’s bad. Any use of `y` would be an error in
this case, and so the compiler has caught this for us.

So how do we solve this problem? There are two approaches we can take. The first
is making a copy rather than using a reference:

```rust
fn main() {
let mut x = vec!["Hello", "world"];

let y = x[0].clone();

x.push("foo");
}
```

Rust has [move semantics][move] by default, so if we want to make a copy of some
data, we call the `clone()` method. In this example, `y` is no longer a reference
to the vector stored in `x`, but a copy of its first element, `"Hello"`. Now
that we don’t have a reference, our `push()` works just fine.

[move]: ownership.html#move-semantics

If we truly want a reference, we need the other option: ensure that our reference
goes out of scope before we try to do the mutation. That looks like this:

```rust
fn main() {
let mut x = vec!["Hello", "world"];

{
let y = &x[0];
}

x.push("foo");
}
```

We created an inner scope with an additional set of curly braces. `y` will go out of
scope before we call `push()`, and so we’re all good.

This concept of ownership isn’t just good for preventing dangling pointers, but an
entire set of related problems, like iterator invalidation, concurrency, and more.