Skip to content

Rollup of 7 pull requests #31739

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 19 commits into from
Feb 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
62b3b40
Clarified move semantics in "the details" section.
sandeep-datta Feb 11, 2016
50d179e
Explained the data race with an example.
sandeep-datta Feb 11, 2016
a8fd1bb
Minor change.
sandeep-datta Feb 11, 2016
a6fedc8
Minor change.
sandeep-datta Feb 11, 2016
37a952a
Fixed build error as per steveklabnik's suggestion and expanded on th…
sandeep-datta Feb 13, 2016
1c87667
Global error explanations improvements
GuillaumeGomez Feb 15, 2016
071b4b6
correct the primitive char doc's use of bytes and code points
oconnor663 Feb 16, 2016
2cac9d7
clarify how insert() doesn't update keys
oconnor663 Jan 30, 2016
4a1ddff
Fix links in release notes 1.7.0
WiSaGaN Feb 16, 2016
8f13f87
Improve 'std::mem::transmute_copy' doc example.
frewsxcv Feb 17, 2016
1536195
Made v2 mutable so that we can actually truncate it.
sandeep-datta Feb 17, 2016
f82c984
Update `Path::strip_prefix` doc
gkoz Feb 17, 2016
9f0e39b
Rollup merge of #31565 - SDX2000:docfixes4, r=steveklabnik
steveklabnik Feb 17, 2016
0a88c8f
Rollup merge of #31679 - GuillaumeGomez:long_error_explanation, r=Man…
steveklabnik Feb 17, 2016
27ef9df
Rollup merge of #31694 - oconnor663:insertdocs, r=steveklabnik
steveklabnik Feb 17, 2016
96c8a67
Rollup merge of #31695 - oconnor663:chardocs, r=alexcrichton
steveklabnik Feb 17, 2016
216081d
Rollup merge of #31703 - WiSaGaN:bugfix/fix-link-in-release-notes, r=…
steveklabnik Feb 17, 2016
b85033a
Rollup merge of #31720 - frewsxcv:std-mem-transmute-copy-example, r=s…
steveklabnik Feb 17, 2016
27ede43
Rollup merge of #31733 - gkoz:strip_prefix_docs, r=alexcrichton
steveklabnik Feb 17, 2016
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
8 changes: 4 additions & 4 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ Misc
the `-Z unstable-options` flag.
* [When running tests with `--test`, rustdoc will pass `--cfg`
arguments to the compiler][1.7dt].
* [The compiler is built with RPATH information by default][1.7rp].
* [The compiler is built with RPATH information by default][1.7rpa].
This means that it will be possible to run `rustc` when installed in
unusual configurations without configuring the dynamic linker search
path explicitly.
* [`rustc` passes `--enable-new-dtags` to GNU ld][1.7dt]. This makes
* [`rustc` passes `--enable-new-dtags` to GNU ld][1.7dta]. This makes
any RPATH entries (emitted with `-C rpath`) *not* take precedence
over `LD_LIBRARY_PATH`.

Expand Down Expand Up @@ -132,15 +132,15 @@ Compatibility Notes
[1.7cp]: https://github.com/rust-lang/cargo/pull/2224
[1.7d]: https://github.com/rust-lang/rust/pull/30724
[1.7dt]: https://github.com/rust-lang/rust/pull/30372
[1.7dt]: https://github.com/rust-lang/rust/pull/30394
[1.7dta]: https://github.com/rust-lang/rust/pull/30394
[1.7f]: https://github.com/rust-lang/rust/pull/30672
[1.7h]: https://github.com/rust-lang/rust/pull/30818
[1.7j]: https://github.com/rust-lang/rust/pull/30711
[1.7ll]: https://github.com/rust-lang/rust/pull/30663
[1.7m]: https://github.com/rust-lang/rust/pull/30381
[1.7p]: https://github.com/rust-lang/rust/pull/30681
[1.7rp]: https://github.com/rust-lang/rust/pull/29498
[1.7rp]: https://github.com/rust-lang/rust/pull/30353
[1.7rpa]: https://github.com/rust-lang/rust/pull/30353
[1.7rr]: https://github.com/rust-lang/cargo/pull/2279
[1.7sf]: https://github.com/rust-lang/rust/pull/30389
[1.7utf8]: https://github.com/rust-lang/rust/pull/30740
Expand Down
62 changes: 53 additions & 9 deletions src/doc/book/ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,21 +124,65 @@ special annotation here, it’s the default thing that Rust does.
## The details

The reason that we cannot use a binding after we’ve moved it is subtle, but
important. When we write code like this:
important.

When we write code like this:

```rust
let x = 10;
```

Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit
pattern representing the value of 10 to the allocated memory and binds the
variable name x to this memory region for future reference.

Now consider the following code fragment:

```rust
let v = vec![1, 2, 3];

let v2 = v;
let mut v2 = v;
```

The first line allocates memory for the vector object `v` on the stack like
it does for `x` above. But in addition to that it also allocates some memory
on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address
of this heap allocation to an internal pointer, which is part of the vector
object placed on the stack (let's call it the data pointer).

It is worth pointing out (even at the risk of stating the obvious) that the
vector object and its data live in separate memory regions instead of being a
single contiguous memory allocation (due to reasons we will not go into at
this point of time). These two parts of the vector (the one on the stack and
one on the heap) must agree with each other at all times with regards to
things like the length, capacity etc.

When we move `v` to `v2`, rust actually does a bitwise copy of the vector
object `v` into the stack allocation represented by `v2`. This shallow copy
does not create a copy of the heap allocation containing the actual data.
Which means that there would be two pointers to the contents of the vector
both pointing to the same memory allocation on the heap. It would violate
Rust’s safety guarantees by introducing a data race if one could access both
`v` and `v2` at the same time.

For example if we truncated the vector to just two elements through `v2`:

```rust
# let v = vec![1, 2, 3];
# let mut v2 = v;
v2.truncate(2);
```

The first line allocates memory for the vector object, `v`, and for the data it
contains. The vector object is stored on the [stack][sh] and contains a pointer
to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`,
it creates a copy of that pointer, for `v2`. Which means that there would be two
pointers to the content of the vector on the heap. It would violate Rust’s
safety guarantees by introducing a data race. Therefore, Rust forbids using `v`
after we’ve done the move.
and `v1` were still accessible we'd end up with an invalid vector since `v1`
would not know that the heap data has been truncated. Now, the part of the
vector `v1` on the stack does not agree with the corresponding part on the
heap. `v1` still thinks there are three elements in the vector and will
happily let us access the non existent element `v1[2]` but as you might
already know this is a recipe for disaster. Especially because it might lead
to a segmentation fault or worse allow an unauthorized user to read from
memory to which they don't have access.

This is why Rust forbids using `v` after we’ve done the move.

[sh]: the-stack-and-the-heap.html

Expand Down
7 changes: 4 additions & 3 deletions src/libcollections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// If the map did not have this key present, `None` is returned.
///
/// If the map did have this key present, the key is not updated, the
/// value is updated and the old value is returned.
/// See the [module-level documentation] for more.
/// If the map did have this key present, the value is updated, and the old
/// value is returned. The key is not updated, though; this matters for
/// types that can be `==` without being identical. See the [module-level
/// documentation] for more.
///
/// [module-level documentation]: index.html#insert-and-complex-keys
///
Expand Down
20 changes: 18 additions & 2 deletions src/libcore/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,9 +571,25 @@ pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize;
/// ```
/// use std::mem;
///
/// let one = unsafe { mem::transmute_copy(&1) };
/// #[repr(packed)]
/// struct Foo {
/// bar: u8,
/// }
///
/// let foo_slice = [10u8];
///
/// unsafe {
/// // Copy the data from 'foo_slice' and treat it as a 'Foo'
/// let mut foo_struct: Foo = mem::transmute_copy(&foo_slice);
/// assert_eq!(foo_struct.bar, 10);
///
/// // Modify the copied data
/// foo_struct.bar = 20;
/// assert_eq!(foo_struct.bar, 20);
/// }
///
/// assert_eq!(1, one);
/// // The contents of 'foo_slice' should not have changed
/// assert_eq!(foo_slice, [10]);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
Loading