Skip to content
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

Minor improvements #129

Merged
merged 1 commit into from
Apr 13, 2019
Merged
Show file tree
Hide file tree
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
10 changes: 8 additions & 2 deletions src/borrow-splitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ println!("{} {} {} {}", a, b, c, c2);
However borrowck doesn't understand arrays or slices in any way, so this doesn't
work:

```rust,ignore
```rust,compile_fail
let mut x = [1, 2, 3];
let a = &mut x[0];
let b = &mut x[1];
Expand Down Expand Up @@ -60,7 +60,12 @@ the left of the index, and one for everything to the right. Intuitively we know
this is safe because the slices don't overlap, and therefore alias. However
the implementation requires some unsafety:

```rust,ignore
```rust
# use std::slice::from_raw_parts_mut;
# struct FakeSlice<T>(T);
# impl<T> FakeSlice<T> {
# fn len(&self) -> usize { unimplemented!() }
# fn as_mut_ptr(&mut self) -> *mut T { unimplemented!() }
fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
let len = self.len();
let ptr = self.as_mut_ptr();
Expand All @@ -70,6 +75,7 @@ fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
}
}
# }
```

This is actually a bit subtle. So as to avoid ever making two `&mut`'s to the
Expand Down
4 changes: 2 additions & 2 deletions src/checked-uninit.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Like C, all stack variables in Rust are uninitialized until a value is
explicitly assigned to them. Unlike C, Rust statically prevents you from ever
reading them until you do:

```rust,ignore
```rust,compile_fail
fn main() {
let x: i32;
println!("{}", x);
Expand Down Expand Up @@ -39,7 +39,7 @@ fn main() {

but this doesn't:

```rust,ignore
```rust,compile_fail
fn main() {
let x: i32;
if true {
Expand Down
2 changes: 1 addition & 1 deletion src/phantom-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ types or lifetimes are logically associated with a struct, but not actually
part of a field. This most commonly occurs with lifetimes. For instance, the
`Iter` for `&'a [T]` is (approximately) defined as follows:

```rust,ignore
```rust,compile_fail
struct Iter<'a, T: 'a> {
ptr: *const T,
end: *const T,
Expand Down
18 changes: 11 additions & 7 deletions src/transmutes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ really can't emphasize that you should deeply think about finding Another Way
than the operations covered in this section. This is really, truly, the most
horribly unsafe thing you can do in Rust. The railguards here are dental floss.

`mem::transmute<T, U>` takes a value of type `T` and reinterprets it to have
type `U`. The only restriction is that the `T` and `U` are verified to have the
same size. The ways to cause Undefined Behavior with this are mind boggling.
[`mem::transmute<T, U>`][transmute] takes a value of type `T` and reinterprets
it to have type `U`. The only restriction is that the `T` and `U` are verified
to have the same size. The ways to cause Undefined Behavior with this are mind
boggling.

* First and foremost, creating an instance of *any* type with an invalid state
is going to cause arbitrary chaos that can't really be predicted.
Expand All @@ -23,13 +24,16 @@ same size. The ways to cause Undefined Behavior with this are mind boggling.
* Transmuting to a reference without an explicitly provided lifetime
produces an [unbounded lifetime]

`mem::transmute_copy<T, U>` somehow manages to be *even more* wildly unsafe than
this. It copies `size_of<U>` bytes out of an `&T` and interprets them as a `U`.
The size check that `mem::transmute` has is gone (as it may be valid to copy
out a prefix), though it is Undefined Behavior for `U` to be larger than `T`.
[`mem::transmute_copy<T, U>`][transmute_copy] somehow manages to be *even more*
wildly unsafe than this. It copies `size_of<U>` bytes out of an `&T` and
interprets them as a `U`. The size check that `mem::transmute` has is gone (as
it may be valid to copy out a prefix), though it is Undefined Behavior for `U`
to be larger than `T`.

Also of course you can get most of the functionality of these functions using
pointer casts.


[unbounded lifetime]: unbounded-lifetimes.html
[transmute]: ../std/mem/fn.transmute.html
[transmute_copy]: ../std/mem/fn.transmute.html