Skip to content

Commit 5d5c206

Browse files
committed
auto merge of #15377 : alexcrichton/rust/rollup, r=alexcrichton
Closes #15276 (Guide: if) Closes #15280 (std::os - Add join_paths, make setenv non-utf8 capable) Closes #15314 (Guide: functions) Closes #15327 (Simplify PatIdent to contain an Ident rather than a Path) Closes #15340 (Guide: add mutable binding section) Closes #15342 (Fix ICE with nested macro_rules!-style macros) Closes #15350 (Remove duplicated slash in install script path) Closes #15351 (correct a few spelling mistakes in the tutorial) Closes #15352 (librustc: Have the kind checker check sub-bounds in trait casts.) Closes #15359 (Fix spelling errors.) Closes #15361 (Rename set_broadast() to set_broadcast().) Closes #15366 (Simplify creating a parser from a token tree) Closes #15367 (Add examples for StrVector methods) Closes #15372 (Vec::grow should use reserve_additional, Vec::reserve should check against capacity) Closes #15373 (Fix minor issues in the documentation of libtime.)
2 parents dd812cc + 9bd6479 commit 5d5c206

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+869
-423
lines changed

src/doc/guide.md

Lines changed: 332 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,9 +515,45 @@ let x: int = 5;
515515
```
516516

517517
If I asked you to read this out loud to the rest of the class, you'd say "`x`
518-
is a binding with the type `int` and the value `five`." Rust requires you to
519-
initialize the binding with a value before you're allowed to use it. If
520-
we try...
518+
is a binding with the type `int` and the value `five`."
519+
520+
By default, bindings are **immutable**. This code will not compile:
521+
522+
```{ignore}
523+
let x = 5i;
524+
x = 10i;
525+
```
526+
527+
It will give you this error:
528+
529+
```{ignore,notrust}
530+
error: re-assignment of immutable variable `x`
531+
x = 10i;
532+
^~~~~~~
533+
```
534+
535+
If you want a binding to be mutable, you can use `mut`:
536+
537+
```{rust}
538+
let mut x = 5i;
539+
x = 10i;
540+
```
541+
542+
There is no single reason that bindings are immutable by default, but we can
543+
think about it through one of Rust's primary focuses: safety. If you forget to
544+
say `mut`, the compiler will catch it, and let you know that you have mutated
545+
something you may not have cared to mutate. If bindings were mutable by
546+
default, the compiler would not be able to tell you this. If you _did_ intend
547+
mutation, then the solution is quite easy: add `mut`.
548+
549+
There are other good reasons to avoid mutable state when possible, but they're
550+
out of the scope of this guide. In general, you can often avoid explicit
551+
mutation, and so it is preferable in Rust. That said, sometimes, mutation is
552+
what you need, so it's not verboten.
553+
554+
Let's get back to bindings. Rust variable bindings have one more aspect that
555+
differs from other languages: bindings are required to be initialized with a
556+
value before you're allowed to use it. If we try...
521557

522558
```{ignore}
523559
let x;
@@ -611,8 +647,301 @@ concept: `if`.
611647

612648
## If
613649

650+
Rust's take on `if` is not particularly complex, but it's much more like the
651+
`if` you'll find in a dynamically typed language than in a more traditional
652+
systems language. So let's talk about it, to make sure you grasp the nuances.
653+
654+
`if` is a specific form of a more general concept, the 'branch.' The name comes
655+
from a branch in a tree: a decision point, where depending on a choice,
656+
multiple paths can be taken.
657+
658+
In the case of `if`, there is one choice that leads down two paths:
659+
660+
```rust
661+
let x = 5i;
662+
663+
if x == 5i {
664+
println!("x is five!");
665+
}
666+
```
667+
668+
If we changed the value of `x` to something else, this line would not print.
669+
More specifically, if the expression after the `if` evaluates to `true`, then
670+
the block is executed. If it's `false`, then it is not.
671+
672+
If you want something to happen in the `false` case, use an `else`:
673+
674+
```
675+
let x = 5i;
676+
677+
if x == 5i {
678+
println!("x is five!");
679+
} else {
680+
println!("x is not five :(");
681+
}
682+
```
683+
684+
This is all pretty standard. However, you can also do this:
685+
686+
687+
```
688+
let x = 5i;
689+
690+
let y = if x == 5i {
691+
10i
692+
} else {
693+
15i
694+
};
695+
```
696+
697+
Which we can (and probably should) write like this:
698+
699+
```
700+
let x = 5i;
701+
702+
let y = if x == 5i { 10i } else { 15i };
703+
```
704+
705+
This reveals two interesting things about Rust: it is an expression-based
706+
language, and semicolons are different than in other 'curly brace and
707+
semicolon'-based languages. These two things are related.
708+
709+
### Expressions vs. Statements
710+
711+
Rust is primarily an expression based language. There are only two kinds of
712+
statements, and everything else is an expression.
713+
714+
So what's the difference? Expressions return a value, and statements do not.
715+
In many languages, `if` is a statement, and therefore, `let x = if ...` would
716+
make no sense. But in Rust, `if` is an expression, which means that it returns
717+
a value. We can then use this value to initialize the binding.
718+
719+
Speaking of which, bindings are a kind of the first of Rust's two statements.
720+
The proper name is a **declaration statement**. So far, `let` is the only kind
721+
of declaration statement we've seen. Let's talk about that some more.
722+
723+
In some languages, variable bindings can be written as expressions, not just
724+
statements. Like Ruby:
725+
726+
```{ruby}
727+
x = y = 5
728+
```
729+
730+
In Rust, however, using `let` to introduce a binding is _not_ an expression. The
731+
following will produce a compile-time error:
732+
733+
```{ignore}
734+
let x = (let y = 5i); // found `let` in ident position
735+
```
736+
737+
The compiler is telling us here that it was expecting to see the beginning of
738+
an expression, and a `let` can only begin a statement, not an expression.
739+
740+
However, re-assigning to a mutable binding is an expression:
741+
742+
```{rust}
743+
let mut x = 0i;
744+
let y = x = 5i;
745+
```
746+
747+
In this case, we have an assignment expression (`x = 5`) whose value is
748+
being used as part of a `let` declaration statement (`let y = ...`).
749+
750+
The second kind of statement in Rust is the **expression statement**. Its
751+
purpose is to turn any expression into a statement. In practical terms, Rust's
752+
grammar expects statements to follow other statements. This means that you use
753+
semicolons to separate expressions from each other. This means that Rust
754+
looks a lot like most other languages that require you to use semicolons
755+
at the end of every line, and you will see semicolons at the end of almost
756+
every line of Rust code you see.
757+
758+
What is this exception that makes us say 'almost?' You saw it already, in this
759+
code:
760+
761+
```
762+
let x = 5i;
763+
764+
let y: int = if x == 5i { 10i } else { 15i };
765+
```
766+
767+
Note that I've added the type annotation to `y`, to specify explicitly that I
768+
want `y` to be an integer.
769+
770+
This is not the same as this, which won't compile:
771+
772+
```{ignore}
773+
let x = 5i;
774+
775+
let y: int = if x == 5 { 10i; } else { 15i; };
776+
```
777+
778+
Note the semicolons after the 10 and 15. Rust will give us the following error:
779+
780+
```{ignore,notrust}
781+
error: mismatched types: expected `int` but found `()` (expected int but found ())
782+
```
783+
784+
We expected an integer, but we got `()`. `()` is pronounced 'unit', and is a
785+
special type in Rust's type system. `()` is different than `null` in other
786+
languages, because `()` is distinct from other types. For example, in C, `null`
787+
is a valid value for a variable of type `int`. In Rust, `()` is _not_ a valid
788+
value for a variable of type `int`. It's only a valid value for variables of
789+
the type `()`, which aren't very useful. Remember how we said statements don't
790+
return a value? Well, that's the purpose of unit in this case. The semicolon
791+
turns any expression into a statement by throwing away its value and returning
792+
unit instead.
793+
794+
There's one more time in which you won't see a semicolon at the end of a line
795+
of Rust code. For that, we'll need our next concept: functions.
796+
614797
## Functions
615798

799+
You've already seen one function so far, the `main` function:
800+
801+
```{rust}
802+
fn main() {
803+
}
804+
```
805+
806+
This is the simplest possible function declaration. As we mentioned before,
807+
`fn` says 'this is a function,' followed by the name, some parenthesis because
808+
this function takes no arguments, and then some curly braces to indicate the
809+
body. Here's a function named `foo`:
810+
811+
```{rust}
812+
fn foo() {
813+
}
814+
```
815+
816+
So, what about taking arguments? Here's a function that prints a number:
817+
818+
```{rust}
819+
fn print_number(x: int) {
820+
println!("x is: {}", x);
821+
}
822+
```
823+
824+
Here's a complete program that uses `print_number`:
825+
826+
```{rust}
827+
fn main() {
828+
print_number(5);
829+
}
830+
831+
fn print_number(x: int) {
832+
println!("x is: {}", x);
833+
}
834+
```
835+
836+
As you can see, function arguments work very similar to `let` declarations:
837+
you add a type to the argument name, after a colon.
838+
839+
Here's a complete program that adds two numbers together and prints them:
840+
841+
```{rust}
842+
fn main() {
843+
print_sum(5, 6);
844+
}
845+
846+
fn print_sum(x: int, y: int) {
847+
println!("sum is: {}", x + y);
848+
}
849+
```
850+
851+
You separate arguments with a comma, both when you call the function, as well
852+
as when you declare it.
853+
854+
Unlike `let`, you _must_ declare the types of function arguments. This does
855+
not work:
856+
857+
```{ignore}
858+
fn print_number(x, y) {
859+
println!("x is: {}", x + y);
860+
}
861+
```
862+
863+
You get this error:
864+
865+
```{ignore,notrust}
866+
hello.rs:5:18: 5:19 error: expected `:` but found `,`
867+
hello.rs:5 fn print_number(x, y) {
868+
```
869+
870+
This is a deliberate design decision. While full-program inference is possible,
871+
languages which have it, like Haskell, often suggest that documenting your
872+
types explicitly is a best-practice. We agree that forcing functions to declare
873+
types while allowing for inference inside of function bodies is a wonderful
874+
compromise between full inference and no inference.
875+
876+
What about returning a value? Here's a function that adds one to an integer:
877+
878+
```{rust}
879+
fn add_one(x: int) -> int {
880+
x + 1
881+
}
882+
```
883+
884+
Rust functions return exactly one value, and you declare the type after an
885+
'arrow', which is a dash (`-`) followed by a greater-than sign (`>`).
886+
887+
You'll note the lack of a semicolon here. If we added it in:
888+
889+
```{ignore}
890+
fn add_one(x: int) -> int {
891+
x + 1;
892+
}
893+
```
894+
895+
We would get an error:
896+
897+
```{ignore,notrust}
898+
note: consider removing this semicolon:
899+
x + 1;
900+
^
901+
error: not all control paths return a value
902+
fn add_one(x: int) -> int {
903+
x + 1;
904+
}
905+
```
906+
907+
Remember our earlier discussions about semicolons and `()`? Our function claims
908+
to return an `int`, but with a semicolon, it would return `()` instead. Rust
909+
realizes this probably isn't what we want, and suggests removing the semicolon.
910+
911+
This is very much like our `if` statement before: the result of the block
912+
(`{}`) is the value of the expression. Other expression-oriented languages,
913+
such as Ruby, work like this, but it's a bit unusual in the systems programming
914+
world. When people first learn about this, they usually assume that it
915+
introduces bugs. But because Rust's type system is so strong, and because unit
916+
is its own unique type, we have never seen an issue where adding or removing a
917+
semicolon in a return position would cause a bug.
918+
919+
But what about early returns? Rust does have a keyword for that, `return`:
920+
921+
```{rust}
922+
fn foo(x: int) -> int {
923+
if x < 5 { return x; }
924+
925+
x + 1
926+
}
927+
```
928+
929+
Using a `return` as the last line of a function works, but is considered poor
930+
style:
931+
932+
```{rust}
933+
fn foo(x: int) -> int {
934+
if x < 5 { return x; }
935+
936+
return x + 1;
937+
}
938+
```
939+
940+
There are some additional ways to define functions, but they involve features
941+
that we haven't learned about yet, so let's just leave it at that for now.
942+
943+
## Comments
944+
616945
return
617946

618947
comments

src/doc/tutorial.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ fn signum(x: int) -> int {
469469

470470
Rust's `match` construct is a generalized, cleaned-up version of C's
471471
`switch` construct. You provide it with a value and a number of
472-
*arms*, each labelled with a pattern, and the code compares the value
472+
*arms*, each labeled with a pattern, and the code compares the value
473473
against each pattern in order until one matches. The matching pattern
474474
executes its corresponding arm.
475475

@@ -2524,7 +2524,7 @@ of the components of types. By design, trait objects don't know the exact type
25242524
of their contents and so the compiler cannot reason about those properties.
25252525

25262526
You can instruct the compiler, however, that the contents of a trait object must
2527-
acribe to a particular bound with a trailing colon (`:`). These are examples of
2527+
ascribe to a particular bound with a trailing colon (`:`). These are examples of
25282528
valid types:
25292529

25302530
~~~rust
@@ -2579,7 +2579,7 @@ This is a silly way to compute the radius of a circle
25792579

25802580
In type-parameterized functions,
25812581
methods of the supertrait may be called on values of subtrait-bound type parameters.
2582-
Refering to the previous example of `trait Circle : Shape`:
2582+
Referring to the previous example of `trait Circle : Shape`:
25832583

25842584
~~~
25852585
# trait Shape { fn area(&self) -> f64; }

src/etc/install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ need_cmd uname
214214
need_cmd tr
215215
need_cmd sed
216216

217-
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
217+
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)"
218218
CFG_SELF="$0"
219219
CFG_ARGS="$@"
220220

src/liballoc/arc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl<T: Share + Send> Drop for Arc<T> {
185185
// deletion of the data. Because it is marked `Release`, the
186186
// decreasing of the reference count synchronizes with this `Acquire`
187187
// fence. This means that use of the data happens before decreasing
188-
// the refernce count, which happens before this fence, which
188+
// the reference count, which happens before this fence, which
189189
// happens before the deletion of the data.
190190
//
191191
// As explained in the [Boost documentation][1],

0 commit comments

Comments
 (0)