@@ -119,12 +119,41 @@ field of type [`TyKind`][tykind], which represents the key type information. `Ty
119
119
which represents different kinds of types (e.g. primitives, references, abstract data types,
120
120
generics, lifetimes, etc). ` TyS ` also has 2 more fields, ` flags ` and ` outer_exclusive_binder ` . They
121
121
are convenient hacks for efficiency and summarize information about the type that we may want to
122
- know, but they don’t come into the picture as much here.
122
+ know, but they don’t come into the picture as much here. Finally, ` ty::TyS ` s
123
+ are [ interned] ( ./memory.md ) , so that the ` ty::Ty ` can be a thin pointer-like
124
+ type. This allows us to do cheap comparisons for equality, along with the other
125
+ benefits of interning.
123
126
124
127
[ tys ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TyS.html
125
128
[ kind ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TyS.html#structfield.kind
126
129
[ tykind ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/enum.TyKind.html
127
130
131
+ ## Allocating and working with types
132
+
133
+ To allocate a new type, you can use the various ` mk_ ` methods defined on the ` tcx ` . These have names
134
+ that correspond mostly to the various kinds of types. For example:
135
+
136
+ ``` rust,ignore
137
+ let array_ty = tcx.mk_array(elem_ty, len * 2);
138
+ ```
139
+
140
+ These methods all return a ` Ty<'tcx> ` – note that the lifetime you get back is the lifetime of the
141
+ arena that this ` tcx ` has access to. Types are always canonicalized and interned (so we never
142
+ allocate exactly the same type twice).
143
+
144
+ > NB. Because types are interned, it is possible to compare them for equality efficiently using ` == `
145
+ > – however, this is almost never what you want to do unless you happen to be hashing and looking
146
+ > for duplicates. This is because often in Rust there are multiple ways to represent the same type,
147
+ > particularly once inference is involved. If you are going to be testing for type equality, you
148
+ > probably need to start looking into the inference code to do it right.
149
+
150
+ You can also find various common types in the ` tcx ` itself by accessing ` tcx.types.bool ` ,
151
+ ` tcx.types.char ` , etc (see [ ` CommonTypes ` ] for more).
152
+
153
+ [ `CommonTypes` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/context/struct.CommonTypes.html
154
+
155
+ ## ` ty::TyKind ` Variants
156
+
128
157
Note: ` TyKind ` is ** NOT** the functional programming concept of * Kind* .
129
158
130
159
Whenever working with a ` Ty ` in the compiler, it is common to match on the kind of type:
@@ -147,8 +176,6 @@ types in the compiler.
147
176
There are a lot of related types, and we’ll cover them in time (e.g regions/lifetimes,
148
177
“substitutions”, etc).
149
178
150
- ## ` ty::TyKind ` Variants
151
-
152
179
There are a bunch of variants on the ` TyKind ` enum, which you can see by looking at the rustdocs.
153
180
Here is a sampling:
154
181
@@ -191,90 +218,6 @@ will discuss this more later.
191
218
[ kinderr ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/enum.TyKind.html#variant.Error
192
219
[ kindvars ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/enum.TyKind.html#variants
193
220
194
- ## Interning
195
-
196
- We create a LOT of types during compilation. For performance reasons, we allocate them from a global
197
- memory pool, they are each allocated once from a long-lived * arena* . This is called _ arena
198
- allocation_ . This system reduces allocations/deallocations of memory. It also allows for easy
199
- comparison of types for equality: we implemented [ ` PartialEq for TyS ` ] [ peqimpl ] , so we can just
200
- compare pointers. The [ ` CtxtInterners ` ] type contains a bunch of maps of interned types and the
201
- arena itself.
202
-
203
- [ peqimpl ] : https://github.com/rust-lang/rust/blob/3ee936378662bd2e74be951d6a7011a95a6bd84d/src/librustc/ty/mod.rs#L528-L534
204
- [ `CtxtInterners` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.CtxtInterners.html#structfield.arena
205
-
206
- Each time we want to construct a type, the compiler doesn’t naively allocate from the buffer.
207
- Instead, we check if that type was already constructed. If it was, we just get the same pointer we
208
- had before, otherwise we make a fresh pointer. With this schema if we want to know if two types are
209
- the same, all we need to do is compare the pointers which is efficient. ` TyS ` which represents types
210
- is carefully setup so you never construct them on the stack. You always allocate them from this
211
- arena and you always intern them so they are unique.
212
-
213
- At the beginning of the compilation we make a buffer and each time we need to allocate a type we use
214
- some of this memory buffer. If we run out of space we get another one. The lifetime of that buffer
215
- is ` 'tcx ` . Our types are tied to that lifetime, so when compilation finishes all the memory related
216
- to that buffer is freed and our ` 'tcx ` references would be invalid.
217
-
218
-
219
- ## The tcx and how it uses lifetimes
220
-
221
- The ` tcx ` ("typing context") is the central data structure in the compiler. It is the context that
222
- you use to perform all manner of queries. The struct ` TyCtxt ` defines a reference to this shared
223
- context:
224
-
225
- ``` rust,ignore
226
- tcx: TyCtxt<'tcx>
227
- // ----
228
- // |
229
- // arena lifetime
230
- ```
231
-
232
- As you can see, the ` TyCtxt ` type takes a lifetime parameter. When you see a reference with a
233
- lifetime like ` 'tcx ` , you know that it refers to arena-allocated data (or data that lives as long as
234
- the arenas, anyhow).
235
-
236
- ## Allocating and working with types
237
-
238
- To allocate a new type, you can use the various ` mk_ ` methods defined on the ` tcx ` . These have names
239
- that correspond mostly to the various kinds of types. For example:
240
-
241
- ``` rust,ignore
242
- let array_ty = tcx.mk_array(elem_ty, len * 2);
243
- ```
244
-
245
- These methods all return a ` Ty<'tcx> ` – note that the lifetime you get back is the lifetime of the
246
- arena that this ` tcx ` has access to. Types are always canonicalized and interned (so we never
247
- allocate exactly the same type twice).
248
-
249
- > NB. Because types are interned, it is possible to compare them for equality efficiently using ` == `
250
- > – however, this is almost never what you want to do unless you happen to be hashing and looking
251
- > for duplicates. This is because often in Rust there are multiple ways to represent the same type,
252
- > particularly once inference is involved. If you are going to be testing for type equality, you
253
- > probably need to start looking into the inference code to do it right.
254
-
255
- You can also find various common types in the ` tcx ` itself by accessing ` tcx.types.bool ` ,
256
- ` tcx.types.char ` , etc (see [ ` CommonTypes ` ] for more).
257
-
258
- [ `CommonTypes` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/context/struct.CommonTypes.html
259
-
260
- ## Beyond types: other kinds of arena-allocated data structures
261
-
262
- In addition to types, there are a number of other arena-allocated data structures that you can
263
- allocate, and which are found in this module. Here are a few examples:
264
-
265
- - [ ` Substs ` ] [ subst ] , allocated with ` mk_substs ` – this will intern a slice of types, often used to
266
- specify the values to be substituted for generics (e.g. ` HashMap<i32, u32> ` would be represented
267
- as a slice ` &'tcx [tcx.types.i32, tcx.types.u32] ` ).
268
- - [ ` TraitRef ` ] , typically passed by value – a ** trait reference** consists of a reference to a trait
269
- along with its various type parameters (including ` Self ` ), like ` i32: Display ` (here, the def-id
270
- would reference the ` Display ` trait, and the substs would contain ` i32 ` ). Note that ` def-id ` is
271
- defined and discussed in depth in the ` AdtDef and DefId ` section.
272
- - [ ` Predicate ` ] defines something the trait system has to prove (see ` traits ` module).
273
-
274
- [ subst ] : ./generic_arguments.html#subst
275
- [ `TraitRef` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TraitRef.html
276
- [ `Predicate` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/enum.Predicate.html
277
-
278
221
## Import conventions
279
222
280
223
Although there is no hard and fast rule, the ` ty ` module tends to be used like so:
0 commit comments