@@ -84,7 +84,7 @@ inlining and hence usually higher performance. It also has some downsides:
84
84
causing code bloat due to many copies of the same function existing in the
85
85
binary, one for each type.
86
86
87
- Furthermore, compilers aren’t perfect and may “optimise ” code to become slower.
87
+ Furthermore, compilers aren’t perfect and may “optimize ” code to become slower.
88
88
For example, functions inlined too eagerly will bloat the instruction cache
89
89
(cache rules everything around us). This is part of the reason that ` #[inline] `
90
90
and ` #[inline(always)] ` should be used carefully, and one reason why using a
@@ -104,15 +104,15 @@ objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
104
104
known at runtime. The methods of the trait can be called on a trait object via
105
105
a special record of function pointers (created and managed by the compiler).
106
106
107
- A function that takes a trait object is not specialised to each of the types
107
+ A function that takes a trait object is not specialized to each of the types
108
108
that implements ` Foo ` : only one copy is generated, often (but not always)
109
109
resulting in less code bloat. However, this comes at the cost of requiring
110
110
slower virtual function calls, and effectively inhibiting any chance of
111
111
inlining and related optimisations from occurring.
112
112
113
113
Trait objects are both simple and complicated: their core representation and
114
114
layout is quite straight-forward, but there are some curly error messages and
115
- surprising behaviours to discover.
115
+ surprising behaviors to discover.
116
116
117
117
### Obtaining a trait object
118
118
@@ -140,13 +140,13 @@ and casts are identical.
140
140
141
141
This operation can be seen as "erasing" the compiler's knowledge about the
142
142
specific type of the pointer, and hence trait objects are sometimes referred to
143
- "type erasure".
143
+ as "type erasure".
144
144
145
145
### Representation
146
146
147
147
Let's start simple, with the runtime representation of a trait object. The
148
148
` std::raw ` module contains structs with layouts that are the same as the
149
- complicated build -in types, [ including trait objects] [ stdraw ] :
149
+ complicated built -in types, [ including trait objects] [ stdraw ] :
150
150
151
151
``` rust
152
152
# mod foo {
@@ -223,14 +223,14 @@ static Foo_for_String_vtable: FooVtable = FooVtable {
223
223
The ` destructor ` field in each vtable points to a function that will clean up
224
224
any resources of the vtable's type, for ` u8 ` it is trivial, but for ` String ` it
225
225
will free the memory. This is necessary for owning trait objects like
226
- ` Box<Foo> ` , which need to clean-up both the ` Box ` allocation and as well as the
226
+ ` Box<Foo> ` , which need to clean-up both the ` Box ` allocation as well as the
227
227
internal type when they go out of scope. The ` size ` and ` align ` fields store
228
228
the size of the erased type, and its alignment requirements; these are
229
229
essentially unused at the moment since the information is embedded in the
230
- destructor, but will be used in future, as trait objects are progressively made
231
- more flexible.
230
+ destructor, but will be used in the future, as trait objects are progressively
231
+ made more flexible.
232
232
233
- Suppose we've got some values that implement ` Foo ` , the explicit form of
233
+ Suppose we've got some values that implement ` Foo ` , then the explicit form of
234
234
construction and use of ` Foo ` trait objects might look a bit like (ignoring the
235
235
type mismatches: they're all just pointers anyway):
236
236
0 commit comments