Skip to content

Commit b3c4630

Browse files
committed
---
yaml --- r: 236025 b: refs/heads/stable c: 8f531d9 h: refs/heads/master i: 236023: cefe885 v: v3
1 parent c859010 commit b3c4630

File tree

5 files changed

+594
-86
lines changed

5 files changed

+594
-86
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ refs/heads/tmp: afae2ff723393b3ab4ccffef6ac7c6d1809e2da0
2929
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f
3030
refs/tags/homu-tmp: f859507de8c410b648d934d8f5ec1c52daac971d
3131
refs/tags/1.0.0-beta: 8cbb92b53468ee2b0c2d3eeb8567005953d40828
32-
refs/heads/stable: edb29ec53db18b8f119154a1b51009f35eeeeeb2
32+
refs/heads/stable: 8f531d9d7e058222cb13a9987a80431906d524b9
3333
refs/tags/1.0.0: 55bd4f8ff2b323f317ae89e254ce87162d52a375
3434
refs/tags/1.1.0: bc3c16f09287e5545c1d3f76b7abd54f2eca868b
3535
refs/tags/1.2.0: f557861f822c34f07270347b94b5280de20a597e

branches/stable/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
# turpl
1+
# The Unsafe Rust Programming Language (Book)
2+
3+
[Start at the intro](http://www.cglab.ca/~abeinges/blah/turpl/intro.html)

branches/stable/conversions.md

Lines changed: 174 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ are just there to help us use those bits right. Needing to reinterpret those pil
55
of bits as different types is a common problem and Rust consequently gives you
66
several ways to do that.
77

8-
# Safe Rust
9-
108
First we'll look at the ways that *Safe Rust* gives you to reinterpret values. The
119
most trivial way to do this is to just destructure a value into its constituent
1210
parts and then build a new type out of them. e.g.
@@ -31,42 +29,191 @@ fn reinterpret(foo: Foo) -> Bar {
3129
But this is, at best, annoying to do. For common conversions, rust provides
3230
more ergonomic alternatives.
3331

34-
## Auto-Deref
32+
33+
34+
35+
# Auto-Deref
36+
37+
(Maybe nix this in favour of receiver coercions)
3538

3639
Deref is a trait that allows you to overload the unary `*` to specify a type
3740
you dereference to. This is largely only intended to be implemented by pointer
3841
types like `&`, `Box`, and `Rc`. The dot operator will automatically perform
39-
automatic dereferencing, so that foo.bar() will work uniformly on `Foo`, `&Foo`, `&&Foo`,
40-
`&Rc<Box<&mut&Box<Foo>>>` and so-on. Search bottoms out on the *first* match,
42+
automatic dereferencing, so that foo.bar() will work uniformly on `Foo`, `&Foo`, `
43+
&&Foo`, `&Rc<Box<&mut&Box<Foo>>>` and so-on. Search bottoms out on the *first* match,
4144
so implementing methods on pointers is generally to be avoided, as it will shadow
4245
"actual" methods.
4346

44-
## Coercions
4547

46-
Types can implicitly be coerced to change in certain contexts. These changes are generally
47-
just *weakening* of types, largely focused around pointers. They mostly exist to make
48-
Rust "just work" in more cases. For instance
49-
`&mut T` coerces to `&T`, and `&T` coerces to `*const T`. The most useful coercion you will
50-
actually think about it is probably the general *Deref Coercion*: `&T` coerces to `&U` when
51-
`T: Deref<U>`. This enables us to pass an `&String` where an `&str` is expected, for instance.
5248

53-
## Casts
5449

55-
Casts are a superset of coercions: every coercion can be explicitly invoked via a cast,
56-
but some changes require a cast. These "true casts" are generally regarded as dangerous or
57-
problematic actions. True casts revolves around raw pointers and the primitive numeric
58-
types. Here's an exhaustive list of all the true casts:
50+
# Coercions
51+
52+
Types can implicitly be coerced to change in certain contexts. These changes are
53+
generally just *weakening* of types, largely focused around pointers and lifetimes.
54+
They mostly exist to make Rust "just work" in more cases, and are largely harmless.
55+
56+
Here's all the kinds of coercion:
57+
58+
59+
Coercion is allowed between the following types:
60+
61+
* `T` to `U` if `T` is a [subtype](lifetimes.html#subtyping-and-variance)
62+
of `U` (the 'identity' case);
63+
64+
* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3`
65+
(transitivity case);
66+
67+
* `&mut T` to `&T`;
68+
69+
* `*mut T` to `*const T`;
70+
71+
* `&T` to `*const T`;
72+
73+
* `&mut T` to `*mut T`;
74+
75+
* `T` to `U` if `T` implements `CoerceUnsized<U>` (see below) and `T = Foo<...>`
76+
and `U = Foo<...>`;
77+
78+
* From TyCtor(`T`) to TyCtor(coerce_inner(`T`));
79+
80+
where TyCtor(`T`) is one of `&T`, `&mut T`, `*const T`, `*mut T`, or `Box<T>`.
81+
And where coerce_inner is defined as
82+
83+
* coerce_inner(`[T, ..n]`) = `[T]`;
84+
85+
* coerce_inner(`T`) = `U` where `T` is a concrete type which implements the
86+
trait `U`;
87+
88+
* coerce_inner(`T`) = `U` where `T` is a sub-trait of `U`;
89+
90+
* coerce_inner(`Foo<..., T, ...>`) = `Foo<..., coerce_inner(T), ...>` where
91+
`Foo` is a struct and only the last field has type `T` and `T` is not part of
92+
the type of any other fields;
93+
94+
* coerce_inner(`(..., T)`) = `(..., coerce_inner(T))`.
95+
96+
Coercions only occur at a *coercion site*. Exhaustively, the coercion sites
97+
are:
98+
99+
* In `let` statements where an explicit type is given: in `let _: U = e;`, `e`
100+
is coerced to to have type `U`;
101+
102+
* In statics and consts, similarly to `let` statements;
103+
104+
* In argument position for function calls. The value being coerced is the actual
105+
parameter and it is coerced to the type of the formal parameter. For example,
106+
where `foo` is defined as `fn foo(x: U) { ... }` and is called with `foo(e);`,
107+
`e` is coerced to have type `U`;
108+
109+
* Where a field of a struct or variant is instantiated. E.g., where `struct Foo
110+
{ x: U }` and the instantiation is `Foo { x: e }`, `e` is coerced to to have
111+
type `U`;
112+
113+
* The result of a function, either the final line of a block if it is not semi-
114+
colon terminated or any expression in a `return` statement. For example, for
115+
`fn foo() -> U { e }`, `e` is coerced to to have type `U`;
59116

60-
TODO: gank the RFC for sweet casts
117+
If the expression in one of these coercion sites is a coercion-propagating
118+
expression, then the relevant sub-expressions in that expression are also
119+
coercion sites. Propagation recurses from these new coercion sites. Propagating
120+
expressions and their relevant sub-expressions are:
61121

62-
For number -> number casts, there are quite a few cases to consider:
122+
* array literals, where the array has type `[U, ..n]`, each sub-expression in
123+
the array literal is a coercion site for coercion to type `U`;
124+
125+
* array literals with repeating syntax, where the array has type `[U, ..n]`, the
126+
repeated sub-expression is a coercion site for coercion to type `U`;
127+
128+
* tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`, each
129+
sub-expression is a coercion site for the respective type, e.g., the zero-th
130+
sub-expression is a coercion site to `U_0`;
131+
132+
* the box expression, if the expression has type `Box<U>`, the sub-expression is
133+
a coercion site to `U`;
134+
135+
* parenthesised sub-expressions (`(e)`), if the expression has type `U`, then
136+
the sub-expression is a coercion site to `U`;
137+
138+
* blocks, if a block has type `U`, then the last expression in the block (if it
139+
is not semicolon-terminated) is a coercion site to `U`. This includes blocks
140+
which are part of control flow statements, such as `if`/`else`, if the block
141+
has a known type.
142+
143+
144+
Note that we do not perform coercions when matching traits (except for
145+
receivers, see below). If there is an impl for some type `U` and `T` coerces to
146+
`U`, that does not constitute an implementation for `T`. For example, the
147+
following will not type check, even though it is OK to coerce `t` to `&T` and
148+
there is an impl for `&T`:
149+
150+
```
151+
struct T;
152+
trait Trait {}
153+
154+
fn foo<X: Trait>(t: X) {}
155+
156+
impl<'a> Trait for &'a T {}
157+
158+
159+
fn main() {
160+
let t: &mut T = &mut T;
161+
foo(t); //~ ERROR failed to find an implementation of trait Trait for &mut T
162+
}
163+
```
164+
165+
In a cast expression, `e as U`, the compiler will first attempt to coerce `e` to
166+
`U`, only if that fails will the conversion rules for casts (see below) be
167+
applied.
168+
169+
170+
171+
172+
# Casts
173+
174+
Casts are a superset of coercions: every coercion can be explicitly invoked via a
175+
cast, but some conversions *require* a cast. These "true casts" are generally regarded
176+
as dangerous or problematic actions. True casts revolve around raw pointers and
177+
the primitive numeric types. True casts aren't checked.
178+
179+
Here's an exhaustive list of all the true casts:
180+
181+
* `e` has type `T` and `T` coerces to `U`; *coercion-cast*
182+
* `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or
183+
unsize_kind(`T`) = unsize_kind(`U_0`); *ptr-ptr-cast*
184+
* `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast*
185+
* `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
186+
* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
187+
* `e` is a C-like enum and `U` is an integer type; *enum-cast*
188+
* `e` has type `bool` or `char` and `U` is an integer; *prim-int-cast*
189+
* `e` has type `u8` and `U` is `char`; *u8-char-cast*
190+
* `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast*
191+
* `e` is a function pointer type and `U` has type `*T`,
192+
while `T: Sized`; *fptr-ptr-cast*
193+
* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast*
194+
195+
where `&.T` and `*T` are references of either mutability,
196+
and where unsize_kind(`T`) is the kind of the unsize info
197+
in `T` - the vtable for a trait definition (e.g. `fmt::Display` or
198+
`Iterator`, not `Iterator<Item=u8>`) or a length (or `()` if `T: Sized`).
199+
200+
Note that lengths are not adjusted when casting raw slices -
201+
`T: *const [u16] as *const [u8]` creates a slice that only includes
202+
half of the original memory.
203+
204+
Casting is not transitive, that is, even if `e as U1 as U2` is a valid
205+
expression, `e as U2` is not necessarily so (in fact it will only be valid if
206+
`U1` coerces to `U2`).
207+
208+
For numeric casts, there are quite a few cases to consider:
63209

64210
* casting between two integers of the same size (e.g. i32 -> u32) is a no-op
65211
* casting from a smaller integer to a bigger integer (e.g. u32 -> u8) will truncate
66212
* casting from a larger integer to a smaller integer (e.g. u8 -> u32) will
67-
* zero-extend if unsigned
68-
* sign-extend if signed
69-
* casting from a float to an integer will round the float towards zero.
213+
* zero-extend if the target is unsigned
214+
* sign-extend if the target is signed
215+
* casting from a float to an integer will:
216+
* round the float towards zero if finite
70217
* **NOTE: currently this will cause Undefined Behaviour if the rounded
71218
value cannot be represented by the target integer type**. This is a bug
72219
and will be fixed.
@@ -86,18 +233,14 @@ well as interpret integers as addresses. However it is impossible to actually
86233
`unsafe`.
87234

88235

89-
## Conversion Traits
90236

91-
For full formal specification of all the kinds of coercions and coercion sites, see:
92-
https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
237+
238+
# Conversion Traits
239+
240+
TODO
93241

94242

95243

96-
* Coercions
97-
* Casts
98-
* Conversion Traits (Into/As/...)
99244

100-
# Unsafe Rust
245+
# Transmuting Types
101246

102-
* raw ptr casts
103-
* mem::transmute

0 commit comments

Comments
 (0)