Skip to content

Commit e516cf8

Browse files
committed
---
yaml --- r: 228979 b: refs/heads/try c: 65a0c17 h: refs/heads/master i: 228977: 2ffc55b 228975: 67425d9 v: v3
1 parent 8a68f0a commit e516cf8

File tree

3 files changed

+101
-143
lines changed

3 files changed

+101
-143
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: aca2057ed5fb7af3f8905b2bc01f72fa001c35c8
33
refs/heads/snap-stage3: 1af31d4974e33027a68126fa5a5a3c2c6491824f
4-
refs/heads/try: a1f6bbc67ae532be0f1bfbe7a631ae39c230c717
4+
refs/heads/try: 65a0c1753e7eaa2ee1a77a4591d328afc85766be
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
66
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
77
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try/conversions.md

Lines changed: 64 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,6 @@ more ergonomic alternatives.
3232

3333

3434

35-
# Auto-Deref
36-
37-
(Maybe nix this in favour of receiver coercions)
38-
39-
Deref is a trait that allows you to overload the unary `*` to specify a type
40-
you dereference to. This is largely only intended to be implemented by pointer
41-
types like `&`, `Box`, and `Rc`. The dot operator will automatically perform
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,
44-
so implementing methods on pointers is generally to be avoided, as it will shadow
45-
"actual" methods.
46-
47-
48-
49-
5035
# Coercions
5136

5237
Types can implicitly be coerced to change in certain contexts. These changes are
@@ -58,118 +43,75 @@ Here's all the kinds of coercion:
5843

5944
Coercion is allowed between the following types:
6045

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`;
116-
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:
121-
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-
46+
* Subtyping: `T` to `U` if `T` is a [subtype](lifetimes.html#subtyping-and-variance)
47+
of `U`
48+
* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3`
49+
* Pointer Weakening:
50+
* `&mut T` to `&T`
51+
* `*mut T` to `*const T`
52+
* `&T` to `*const T`
53+
* `&mut T` to `*mut T`
54+
* Unsizing: `T` to `U` if `T` implements `CoerceUnsized<U>`
55+
56+
`CoerceUnsized<Pointer<U>> for Pointer<T>` where T: Unsize<U> is implemented
57+
for all pointer types (including smart pointers like Box and Rc). Unsize is
58+
only implemented automatically, and enables the following transformations:
59+
60+
* `[T, ..n]` => `[T]`
61+
* `T` => `Trait` where `T: Trait`
62+
* `SubTrait` => `Trait` where `SubTrait: Trait` (TODO: is this now implied by the previous?)
63+
* `Foo<..., T, ...>` => `Foo<..., U, ...>` where:
64+
* T: Unsize<U>
65+
* `Foo` is a struct
66+
* Only the last field has type `T`
67+
* `T` is not part of the type of any other fields
68+
(note that this also applies to to tuples as an anonymous struct `Tuple3<T, U, V>`)
69+
70+
Coercions occur at a *coercion site*. Any location that is explicitly typed
71+
will cause a coercion to its type. If inference is necessary, the coercion will
72+
not be performed. Exhaustively, the coercion sites for an expression `e` to
73+
type `U` are:
74+
75+
* let statements, statics, and consts: `let x: U = e`
76+
* Arguments to functions: `takes_a_U(e)`
77+
* Any expression that will be returned: `fn foo() -> U { e }`
78+
* Struct literals: `Foo { some_u: e }`
79+
* Array literals: `let x: [U; 10] = [e, ..]`
80+
* Tuple literals: `let x: (U, ..) = (e, ..)`
81+
* The last expression in a block: `let x: U = { ..; e }`
14382

14483
Note that we do not perform coercions when matching traits (except for
14584
receivers, see below). If there is an impl for some type `U` and `T` coerces to
14685
`U`, that does not constitute an implementation for `T`. For example, the
14786
following will not type check, even though it is OK to coerce `t` to `&T` and
14887
there is an impl for `&T`:
14988

150-
```
151-
struct T;
89+
```rust
15290
trait Trait {}
15391

15492
fn foo<X: Trait>(t: X) {}
15593

156-
impl<'a> Trait for &'a T {}
94+
impl<'a> Trait for &'a i32 {}
15795

15896

15997
fn main() {
160-
let t: &mut T = &mut T;
161-
foo(t); //~ ERROR failed to find an implementation of trait Trait for &mut T
98+
let t: &mut i32 = &mut 0;
99+
foo(t);
162100
}
163101
```
164102

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-
103+
```text
104+
<anon>:10:5: 10:8 error: the trait `Trait` is not implemented for the type `&mut i32` [E0277]
105+
<anon>:10 foo(t);
106+
^~~
107+
```
169108

109+
# The Dot Operator
170110

171-
TODO: receiver coercions?
111+
The dot operator will perform a lot of magic to convert types. It will perform
112+
auto-referencing, auto-dereferencing, and coercion until types match.
172113

114+
TODO: steal information from http://stackoverflow.com/questions/28519997/what-are-rusts-exact-auto-dereferencing-rules/28552082#28552082
173115

174116
# Casts
175117

@@ -178,21 +120,21 @@ cast, but some conversions *require* a cast. These "true casts" are generally re
178120
as dangerous or problematic actions. True casts revolve around raw pointers and
179121
the primitive numeric types. True casts aren't checked.
180122

181-
Here's an exhaustive list of all the true casts:
182-
183-
* `e` has type `T` and `T` coerces to `U`; *coercion-cast*
184-
* `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or
185-
unsize_kind(`T`) = unsize_kind(`U_0`); *ptr-ptr-cast*
186-
* `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast*
187-
* `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
188-
* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
189-
* `e` is a C-like enum and `U` is an integer type; *enum-cast*
190-
* `e` has type `bool` or `char` and `U` is an integer; *prim-int-cast*
191-
* `e` has type `u8` and `U` is `char`; *u8-char-cast*
192-
* `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast*
193-
* `e` is a function pointer type and `U` has type `*T`,
194-
while `T: Sized`; *fptr-ptr-cast*
195-
* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast*
123+
Here's an exhaustive list of all the true casts. For brevity, we will use `*`
124+
to denote either a `*const` or `*mut`, and `integer` to denote any integral primitive:
125+
126+
* `*T as *U` where `T, U: Sized`
127+
* `*T as *U` TODO: explain unsized situation
128+
* `*T as integer`
129+
* `integer as *T`
130+
* `number as number`
131+
* `C-like-enum as integer`
132+
* `bool as integer`
133+
* `char as integer`
134+
* `u8 as char`
135+
* `&[T; n] as *const T`
136+
* `fn as *T` where `T: Sized`
137+
* `fn as integer`
196138

197139
where `&.T` and `*T` are references of either mutability,
198140
and where unsize_kind(`T`) is the kind of the unsize info

branches/try/data.md

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ represented in Rust.
77

88

99

10-
# The rust repr
10+
# The Rust repr
1111

1212
Rust gives you the following ways to lay out composite data:
1313

@@ -16,12 +16,14 @@ Rust gives you the following ways to lay out composite data:
1616
* arrays (homogeneous product types)
1717
* enums (named sum types -- tagged unions)
1818

19-
For all these, individual fields are aligned to their preferred alignment.
20-
For primitives this is equal to
21-
their size. For instance, a u32 will be aligned to a multiple of 32 bits, and a u16 will
22-
be aligned to a multiple of 16 bits. Composite structures will have their size rounded
23-
up to be a multiple of the highest alignment required by their fields, and an alignment
24-
requirement equal to the highest alignment required by their fields. So for instance,
19+
An enum is said to be *C-like* if none of its variants have associated data.
20+
21+
For all these, individual fields are aligned to their preferred alignment. For
22+
primitives this is usually equal to their size. For instance, a u32 will be
23+
aligned to a multiple of 32 bits, and a u16 will be aligned to a multiple of 16
24+
bits. Composite structures will have their size rounded up to be a multiple of
25+
the highest alignment required by their fields, and an alignment requirement
26+
equal to the highest alignment required by their fields. So for instance,
2527

2628
```rust
2729
struct A {
@@ -127,6 +129,9 @@ In principle enums can use fairly elaborate algorithms to cache bits throughout
127129
with special constrained representations. As such it is *especially* desirable that we leave
128130
enum layout unspecified today.
129131

132+
133+
134+
130135
# Dynamically Sized Types (DSTs)
131136

132137
Rust also supports types without a statically known size. On the surface,
@@ -219,15 +224,14 @@ struct Foo {
219224
```
220225

221226
For details as to *why* this is done, and how to make it not happen, check out
222-
[SOME OTHER SECTION].
227+
[TODO: SOME OTHER SECTION].
223228

224229

225230

226231

227232
# Alternative representations
228233

229-
Rust allows you to specify alternative data layout strategies from the default Rust
230-
one.
234+
Rust allows you to specify alternative data layout strategies from the default.
231235

232236

233237

@@ -241,32 +245,44 @@ to soundly do more elaborate tricks with data layout such as reintepretting valu
241245
as a different type.
242246

243247
However, the interaction with Rust's more exotic data layout features must be kept
244-
in mind. Due to its dual purpose as a "for FFI" and "for layout control", repr(C)
248+
in mind. Due to its dual purpose as "for FFI" and "for layout control", `repr(C)`
245249
can be applied to types that will be nonsensical or problematic if passed through
246250
the FFI boundary.
247251

248252
* ZSTs are still zero-sized, even though this is not a standard behaviour
249-
in C, and is explicitly contrary to the behaviour of an empty type in C++, which
250-
still consumes a byte of space.
253+
in C, and is explicitly contrary to the behaviour of an empty type in C++, which
254+
still consumes a byte of space.
251255

252-
* DSTs are not a concept in C
256+
* DSTs, tuples, and tagged unions are not a concept in C and as such are never
257+
FFI safe.
253258

254259
* **The drop flag will still be added**
255260

256-
* This is equivalent to repr(u32) for enums (see below)
261+
* This is equivalent to `repr(u32)` for enums (see below)
257262

258263

259264

260265
## repr(packed)
261266

262-
`repr(packed)` forces rust to strip any padding it would normally apply.
263-
This may improve the memory footprint of a type, but will have negative
264-
side-effects from "field access is heavily penalized" to "completely breaks
265-
everything" based on target platform.
267+
`repr(packed)` forces rust to strip any padding, and only align the type to a
268+
byte. This may improve the memory footprint, but will likely have other
269+
negative side-effects.
270+
271+
In particular, most architectures *strongly* prefer values to be aligned. This
272+
may mean the unaligned loads are penalized (x86), or even fault (ARM). In
273+
particular, the compiler may have trouble with references to unaligned fields.
274+
275+
`repr(packed)` is not to be used lightly. Unless you have extreme requirements,
276+
this should not be used.
266277

278+
This repr is a modifier on `repr(C)` and `repr(rust)`.
267279

268280

269281
## repr(u8), repr(u16), repr(u32), repr(u64)
270282

271-
These specify the size to make a c-like enum (one which has no values in its variants).
283+
These specify the size to make a C-like enum. If the discriminant overflows the
284+
integer it has to fit in, it will be an error. You can manually ask Rust to
285+
allow this by setting the overflowing element to explicitly be 0. However Rust
286+
will not allow you to create an enum where two variants.
272287

288+
These reprs have no affect on struct or non-C-like enum.

0 commit comments

Comments
 (0)