Auto merge of #26117 - Manishearth:rollup, r=Manishearth
- Successful merges: #25898, #25909, #25948, #25968, #26073, #26078, #26099, #26104, #26105, #26112, #26113 - Failed merges:
This commit is contained in:
commit
a35ea4d358
@ -1038,7 +1038,7 @@ be undesired.
|
||||
|
||||
* Deadlocks
|
||||
* Reading data from private fields (`std::repr`)
|
||||
* Leaks due to reference count cycles, even in the global heap
|
||||
* Leaks of memory and other resources
|
||||
* Exiting without calling destructors
|
||||
* Sending signals
|
||||
* Accessing/modifying the file system
|
||||
@ -1418,9 +1418,13 @@ impl<T> Container for Vec<T> {
|
||||
```
|
||||
|
||||
Generic functions may use traits as _bounds_ on their type parameters. This
|
||||
will have two effects: only types that have the trait may instantiate the
|
||||
parameter, and within the generic function, the methods of the trait can be
|
||||
called on values that have the parameter's type. For example:
|
||||
will have two effects:
|
||||
|
||||
- Only types that have the trait may instantiate the parameter.
|
||||
- Within the generic function, the methods of the trait can be
|
||||
called on values that have the parameter's type.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
# type Surface = i32;
|
||||
@ -2831,13 +2835,13 @@ on the right-hand side.
|
||||
An example of an `as` expression:
|
||||
|
||||
```
|
||||
# fn sum(v: &[f64]) -> f64 { 0.0 }
|
||||
# fn len(v: &[f64]) -> i32 { 0 }
|
||||
# fn sum(values: &[f64]) -> f64 { 0.0 }
|
||||
# fn len(values: &[f64]) -> i32 { 0 }
|
||||
|
||||
fn avg(v: &[f64]) -> f64 {
|
||||
let sum: f64 = sum(v);
|
||||
let sz: f64 = len(v) as f64;
|
||||
return sum / sz;
|
||||
fn average(values: &[f64]) -> f64 {
|
||||
let sum: f64 = sum(values);
|
||||
let size: f64 = len(values) as f64;
|
||||
sum / size
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -33,8 +33,8 @@ let plus_two = |x| {
|
||||
assert_eq!(4, plus_two(2));
|
||||
```
|
||||
|
||||
You’ll notice a few things about closures that are a bit different than regular
|
||||
functions defined with `fn`. The first of which is that we did not need to
|
||||
You’ll notice a few things about closures that are a bit different from regular
|
||||
functions defined with `fn`. The first is that we did not need to
|
||||
annotate the types of arguments the closure takes or the values it returns. We
|
||||
can:
|
||||
|
||||
@ -48,10 +48,10 @@ But we don’t have to. Why is this? Basically, it was chosen for ergonomic reas
|
||||
While specifying the full type for named functions is helpful with things like
|
||||
documentation and type inference, the types of closures are rarely documented
|
||||
since they’re anonymous, and they don’t cause the kinds of error-at-a-distance
|
||||
that inferring named function types can.
|
||||
problems that inferring named function types can.
|
||||
|
||||
The second is that the syntax is similar, but a bit different. I’ve added spaces
|
||||
here to make them look a little closer:
|
||||
here for easier comparison:
|
||||
|
||||
```rust
|
||||
fn plus_one_v1 (x: i32) -> i32 { x + 1 }
|
||||
@ -59,7 +59,7 @@ let plus_one_v2 = |x: i32| -> i32 { x + 1 };
|
||||
let plus_one_v3 = |x: i32| x + 1 ;
|
||||
```
|
||||
|
||||
Small differences, but they’re similar in ways.
|
||||
Small differences, but they’re similar.
|
||||
|
||||
# Closures and their environment
|
||||
|
||||
@ -99,7 +99,7 @@ note: previous borrow ends here
|
||||
fn main() {
|
||||
let mut num = 5;
|
||||
let plus_num = |x| x + num;
|
||||
|
||||
|
||||
let y = &mut num;
|
||||
}
|
||||
^
|
||||
@ -161,7 +161,7 @@ of `num`. So what’s the difference?
|
||||
```rust
|
||||
let mut num = 5;
|
||||
|
||||
{
|
||||
{
|
||||
let mut add_num = |x: i32| num += x;
|
||||
|
||||
add_num(5);
|
||||
@ -180,7 +180,7 @@ If we change to a `move` closure, it’s different:
|
||||
```rust
|
||||
let mut num = 5;
|
||||
|
||||
{
|
||||
{
|
||||
let mut add_num = move |x: i32| num += x;
|
||||
|
||||
add_num(5);
|
||||
|
@ -29,6 +29,9 @@ The other kind of comment is a doc comment. Doc comments use `///` instead of
|
||||
/// let five = 5;
|
||||
///
|
||||
/// assert_eq!(6, add_one(5));
|
||||
/// # fn add_one(x: i32) -> i32 {
|
||||
/// # x + 1
|
||||
/// # }
|
||||
/// ```
|
||||
fn add_one(x: i32) -> i32 {
|
||||
x + 1
|
||||
|
@ -432,7 +432,9 @@ an extra annotation, `move`, to indicate that the closure is going to take
|
||||
ownership of the values it’s capturing. Primarily, the `p` variable of the
|
||||
`map` function.
|
||||
|
||||
Inside the thread, all we do is call `eat()` on `p`.
|
||||
Inside the thread, all we do is call `eat()` on `p`. Also note that the call to `thread::spawn` lacks a trailing semicolon, making this an expression. This distinction is important, yielding the correct return value. For more details, read [Expressions vs. Statements][es].
|
||||
|
||||
[es]: functions.html#expressions-vs.-statements
|
||||
|
||||
```rust,ignore
|
||||
}).collect();
|
||||
|
@ -284,7 +284,7 @@ struct Info {
|
||||
}
|
||||
|
||||
fn write_info(info: &Info) -> io::Result<()> {
|
||||
let mut file = try!(File::create("my_best_friends.txt"));
|
||||
let mut file = File::create("my_best_friends.txt").unwrap();
|
||||
|
||||
try!(writeln!(&mut file, "name: {}", info.name));
|
||||
try!(writeln!(&mut file, "age: {}", info.age));
|
||||
|
@ -1,8 +1,8 @@
|
||||
% Generics
|
||||
|
||||
Sometimes, when writing a function or data type, we may want it to work for
|
||||
multiple types of arguments. Luckily, Rust has a feature that gives us a better
|
||||
way: generics. Generics are called ‘parametric polymorphism’ in type theory,
|
||||
multiple types of arguments. In Rust, we can do this with generics.
|
||||
Generics are called ‘parametric polymorphism’ in type theory,
|
||||
which means that they are types or functions that have multiple forms (‘poly’
|
||||
is multiple, ‘morph’ is form) over a given parameter (‘parametric’).
|
||||
|
||||
|
@ -36,7 +36,7 @@ Note that since we're creating an executable, we used `main.rs`. If we
|
||||
want to make a library instead, we should use `lib.rs`. This convention is required
|
||||
for Cargo to successfully compile our projects, but it can be overridden if we wish.
|
||||
Custom file locations for the entry point can be specified
|
||||
with a [`[[lib]]` or `[[bin]]`][crates-custom] key in the TOML file described below.
|
||||
with a [`[lib]` or `[[bin]]`][crates-custom] key in the TOML file.
|
||||
|
||||
[crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target
|
||||
|
||||
|
@ -156,6 +156,46 @@ that, just like a move, when we assign `v` to `v2`, a copy of the data is made.
|
||||
But, unlike a move, we can still use `v` afterward. This is because an `i32`
|
||||
has no pointers to data somewhere else, copying it is a full copy.
|
||||
|
||||
All primitive types implement the `Copy` trait and their ownership is
|
||||
therefore not moved like one would assume, following the ´ownership rules´.
|
||||
To give an example, the two following snippets of code only compile because the
|
||||
`i32` and `bool` types implement the `Copy` trait.
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let a = 5;
|
||||
|
||||
let _y = double(a);
|
||||
println!("{}", a);
|
||||
}
|
||||
|
||||
fn double(x: i32) -> i32 {
|
||||
x * 2
|
||||
}
|
||||
```
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let a = true;
|
||||
|
||||
let _y = change_truth(a);
|
||||
println!("{}", a);
|
||||
}
|
||||
|
||||
fn change_truth(x: bool) -> bool {
|
||||
!x
|
||||
}
|
||||
```
|
||||
|
||||
If we would have used types that do not implement the `Copy` trait,
|
||||
we would have gotten a compile error because we tried to use a moved value.
|
||||
|
||||
```text
|
||||
error: use of moved value: `a`
|
||||
println!("{}", a);
|
||||
^
|
||||
```
|
||||
|
||||
We will discuss how to make your own types `Copy` in the [traits][traits]
|
||||
section.
|
||||
|
||||
|
@ -261,7 +261,7 @@ static Foo_for_String_vtable: FooVtable = FooVtable {
|
||||
```
|
||||
|
||||
The `destructor` field in each vtable points to a function that will clean up
|
||||
any resources of the vtable’s type, for `u8` it is trivial, but for `String` it
|
||||
any resources of the vtable’s type: for `u8` it is trivial, but for `String` it
|
||||
will free the memory. This is necessary for owning trait objects like
|
||||
`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
|
||||
internal type when they go out of scope. The `size` and `align` fields store
|
||||
@ -270,7 +270,7 @@ essentially unused at the moment since the information is embedded in the
|
||||
destructor, but will be used in the future, as trait objects are progressively
|
||||
made more flexible.
|
||||
|
||||
Suppose we’ve got some values that implement `Foo`, then the explicit form of
|
||||
Suppose we’ve got some values that implement `Foo`. The explicit form of
|
||||
construction and use of `Foo` trait objects might look a bit like (ignoring the
|
||||
type mismatches: they’re all just pointers anyway):
|
||||
|
||||
|
@ -45,7 +45,7 @@ but we don’t define a body, just a type signature. When we `impl` a trait,
|
||||
we use `impl Trait for Item`, rather than just `impl Item`.
|
||||
|
||||
We can use traits to constrain our generics. Consider this function, which
|
||||
does not compile, and gives us a similar error:
|
||||
does not compile:
|
||||
|
||||
```rust,ignore
|
||||
fn print_area<T>(shape: T) {
|
||||
@ -56,7 +56,7 @@ fn print_area<T>(shape: T) {
|
||||
Rust complains:
|
||||
|
||||
```text
|
||||
error: type `T` does not implement any method in scope named `area`
|
||||
error: no method named `area` found for type `T` in the current scope
|
||||
```
|
||||
|
||||
Because `T` can be any type, we can’t be sure that it implements the `area`
|
||||
@ -212,10 +212,10 @@ This will compile without error.
|
||||
This means that even if someone does something bad like add methods to `i32`,
|
||||
it won’t affect you, unless you `use` that trait.
|
||||
|
||||
There’s one more restriction on implementing traits. Either the trait or the
|
||||
type you’re writing the `impl` for must be defined by you. So, we could
|
||||
There’s one more restriction on implementing traits: either the trait, or the
|
||||
type you’re writing the `impl` for, must be defined by you. So, we could
|
||||
implement the `HasArea` type for `i32`, because `HasArea` is in our code. But
|
||||
if we tried to implement `Float`, a trait provided by Rust, for `i32`, we could
|
||||
if we tried to implement `ToString`, a trait provided by Rust, for `i32`, we could
|
||||
not, because neither the trait nor the type are in our code.
|
||||
|
||||
One last thing about traits: generic functions with a trait bound use
|
||||
|
@ -1663,11 +1663,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
ty::ty_vec(element_ty, ref len) => {
|
||||
// [T, ..n] and [T]
|
||||
// [T; n] and [T]
|
||||
match bound {
|
||||
ty::BoundCopy => {
|
||||
match *len {
|
||||
// [T, ..n] is copy iff T is copy
|
||||
// [T; n] is copy iff T is copy
|
||||
Some(_) => ok_if(vec![element_ty]),
|
||||
|
||||
// [T] is unsized and hence affine
|
||||
|
@ -234,8 +234,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
}
|
||||
|
||||
|
||||
// &[T, ..n] or &mut [T, ..n] -> &[T]
|
||||
// or &mut [T, ..n] -> &mut [T]
|
||||
// &[T; n] or &mut [T; n] -> &[T]
|
||||
// or &mut [T; n] -> &mut [T]
|
||||
// or &Concrete -> &Trait, etc.
|
||||
fn coerce_unsized(&self,
|
||||
source: Ty<'tcx>,
|
||||
|
@ -18,7 +18,7 @@ into a more explicit UFCS form:
|
||||
Here `ADJ` is some kind of adjustment, which is typically a series of
|
||||
autoderefs and then possibly an autoref (e.g., `&**receiver`). However
|
||||
we sometimes do other adjustments and coercions along the way, in
|
||||
particular unsizing (e.g., converting from `[T, ..n]` to `[T]`).
|
||||
particular unsizing (e.g., converting from `[T; n]` to `[T]`).
|
||||
|
||||
## The Two Phases
|
||||
|
||||
|
@ -2085,7 +2085,7 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
return final_mt;
|
||||
}
|
||||
|
||||
// After we have fully autoderef'd, if the resulting type is [T, ..n], then
|
||||
// After we have fully autoderef'd, if the resulting type is [T; n], then
|
||||
// do a final unsized coercion to yield [T].
|
||||
if let ty::ty_vec(element_ty, Some(_)) = ty.sty {
|
||||
let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
|
||||
|
Loading…
x
Reference in New Issue
Block a user