]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/tyencode.rs
Auto merge of #28869 - alexcrichton:allocator-dox, r=steveklabnik
[rust.git] / src / librustc / metadata / tyencode.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // Type encoding
12
13 #![allow(unused_must_use)] // as with encoding, everything is a no-fail MemWriter
14 #![allow(non_camel_case_types)]
15
16 use std::cell::RefCell;
17 use std::io::Cursor;
18 use std::io::prelude::*;
19
20 use middle::def_id::DefId;
21 use middle::region;
22 use middle::subst;
23 use middle::subst::VecPerParamSpace;
24 use middle::ty::ParamTy;
25 use middle::ty::{self, Ty};
26 use util::nodemap::FnvHashMap;
27
28 use rustc_front::hir;
29
30 use syntax::abi::Abi;
31 use syntax::ast;
32 use syntax::diagnostic::SpanHandler;
33
34 use rbml::writer::{self, Encoder};
35
36 macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) }
37
38 pub struct ctxt<'a, 'tcx: 'a> {
39     pub diag: &'a SpanHandler,
40     // Def -> str Callback:
41     pub ds: fn(DefId) -> String,
42     // The type context.
43     pub tcx: &'a ty::ctxt<'tcx>,
44     pub abbrevs: &'a abbrev_map<'tcx>
45 }
46
47 // Compact string representation for Ty values. API TyStr & parse_from_str.
48 // Extra parameters are for converting to/from def_ids in the string rep.
49 // Whatever format you choose should not contain pipe characters.
50 pub struct ty_abbrev {
51     s: Vec<u8>
52 }
53
54 pub type abbrev_map<'tcx> = RefCell<FnvHashMap<Ty<'tcx>, ty_abbrev>>;
55
56 pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
57     match cx.abbrevs.borrow_mut().get(&t) {
58         Some(a) => { w.writer.write_all(&a.s); return; }
59         None => {}
60     }
61
62     // type abbreviations needs a stable position
63     let pos = w.mark_stable_position();
64
65     match t.sty {
66         ty::TyBool => mywrite!(w, "b"),
67         ty::TyChar => mywrite!(w, "c"),
68         ty::TyInt(t) => {
69             match t {
70                 ast::TyIs => mywrite!(w, "is"),
71                 ast::TyI8 => mywrite!(w, "MB"),
72                 ast::TyI16 => mywrite!(w, "MW"),
73                 ast::TyI32 => mywrite!(w, "ML"),
74                 ast::TyI64 => mywrite!(w, "MD")
75             }
76         }
77         ty::TyUint(t) => {
78             match t {
79                 ast::TyUs => mywrite!(w, "us"),
80                 ast::TyU8 => mywrite!(w, "Mb"),
81                 ast::TyU16 => mywrite!(w, "Mw"),
82                 ast::TyU32 => mywrite!(w, "Ml"),
83                 ast::TyU64 => mywrite!(w, "Md")
84             }
85         }
86         ty::TyFloat(t) => {
87             match t {
88                 ast::TyF32 => mywrite!(w, "Mf"),
89                 ast::TyF64 => mywrite!(w, "MF"),
90             }
91         }
92         ty::TyEnum(def, substs) => {
93             mywrite!(w, "t[{}|", (cx.ds)(def.did));
94             enc_substs(w, cx, substs);
95             mywrite!(w, "]");
96         }
97         ty::TyTrait(box ty::TraitTy { ref principal,
98                                        ref bounds }) => {
99             mywrite!(w, "x[");
100             enc_trait_ref(w, cx, principal.0);
101             enc_existential_bounds(w, cx, bounds);
102             mywrite!(w, "]");
103         }
104         ty::TyTuple(ref ts) => {
105             mywrite!(w, "T[");
106             for t in ts { enc_ty(w, cx, *t); }
107             mywrite!(w, "]");
108         }
109         ty::TyBox(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
110         ty::TyRawPtr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
111         ty::TyRef(r, mt) => {
112             mywrite!(w, "&");
113             enc_region(w, cx, *r);
114             enc_mt(w, cx, mt);
115         }
116         ty::TyArray(t, sz) => {
117             mywrite!(w, "V");
118             enc_ty(w, cx, t);
119             mywrite!(w, "/{}|", sz);
120         }
121         ty::TySlice(t) => {
122             mywrite!(w, "V");
123             enc_ty(w, cx, t);
124             mywrite!(w, "/|");
125         }
126         ty::TyStr => {
127             mywrite!(w, "v");
128         }
129         ty::TyBareFn(Some(def_id), f) => {
130             mywrite!(w, "F");
131             mywrite!(w, "{}|", (cx.ds)(def_id));
132             enc_bare_fn_ty(w, cx, f);
133         }
134         ty::TyBareFn(None, f) => {
135             mywrite!(w, "G");
136             enc_bare_fn_ty(w, cx, f);
137         }
138         ty::TyInfer(_) => {
139             cx.diag.handler().bug("cannot encode inference variable types");
140         }
141         ty::TyParam(ParamTy {space, idx, name}) => {
142             mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), name)
143         }
144         ty::TyStruct(def, substs) => {
145             mywrite!(w, "a[{}|", (cx.ds)(def.did));
146             enc_substs(w, cx, substs);
147             mywrite!(w, "]");
148         }
149         ty::TyClosure(def, ref substs) => {
150             mywrite!(w, "k[{}|", (cx.ds)(def));
151             enc_substs(w, cx, &substs.func_substs);
152             for ty in &substs.upvar_tys {
153                 enc_ty(w, cx, ty);
154             }
155             mywrite!(w, ".");
156             mywrite!(w, "]");
157         }
158         ty::TyProjection(ref data) => {
159             mywrite!(w, "P[");
160             enc_trait_ref(w, cx, data.trait_ref);
161             mywrite!(w, "{}]", data.item_name);
162         }
163         ty::TyError => {
164             mywrite!(w, "e");
165         }
166     }
167
168     let end = w.mark_stable_position();
169     let len = end - pos;
170
171     let buf: &mut [u8] = &mut [0; 16]; // vuint < 15 bytes
172     let mut abbrev = Cursor::new(buf);
173     abbrev.write_all(b"#");
174     writer::write_vuint(&mut abbrev, pos as usize);
175
176     cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
177         s: if abbrev.position() < len {
178             abbrev.get_ref()[..abbrev.position() as usize].to_owned()
179         } else {
180             // if the abbreviation is longer than the real type,
181             // don't use #-notation. However, insert it here so
182             // other won't have to `mark_stable_position`
183             w.writer.get_ref()[pos as usize..end as usize].to_owned()
184         }
185     });
186 }
187
188 fn enc_mutability(w: &mut Encoder, mt: hir::Mutability) {
189     match mt {
190         hir::MutImmutable => (),
191         hir::MutMutable => mywrite!(w, "m"),
192     }
193 }
194
195 fn enc_mt<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
196                     mt: ty::TypeAndMut<'tcx>) {
197     enc_mutability(w, mt.mutbl);
198     enc_ty(w, cx, mt.ty);
199 }
200
201 fn enc_opt<T, F>(w: &mut Encoder, t: Option<T>, enc_f: F) where
202     F: FnOnce(&mut Encoder, T),
203 {
204     match t {
205         None => mywrite!(w, "n"),
206         Some(v) => {
207             mywrite!(w, "s");
208             enc_f(w, v);
209         }
210     }
211 }
212
213 fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Encoder,
214                                            cx: &ctxt<'a, 'tcx>,
215                                            v: &VecPerParamSpace<T>,
216                                            mut op: F) where
217     F: FnMut(&mut Encoder, &ctxt<'a, 'tcx>, &T),
218 {
219     for &space in &subst::ParamSpace::all() {
220         mywrite!(w, "[");
221         for t in v.get_slice(space) {
222             op(w, cx, t);
223         }
224         mywrite!(w, "]");
225     }
226 }
227
228 pub fn enc_substs<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
229                             substs: &subst::Substs<'tcx>) {
230     enc_region_substs(w, cx, &substs.regions);
231     enc_vec_per_param_space(w, cx, &substs.types,
232                             |w, cx, &ty| enc_ty(w, cx, ty));
233 }
234
235 fn enc_region_substs(w: &mut Encoder, cx: &ctxt, substs: &subst::RegionSubsts) {
236     match *substs {
237         subst::ErasedRegions => {
238             mywrite!(w, "e");
239         }
240         subst::NonerasedRegions(ref regions) => {
241             mywrite!(w, "n");
242             enc_vec_per_param_space(w, cx, regions,
243                                     |w, cx, &r| enc_region(w, cx, r));
244         }
245     }
246 }
247
248 pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) {
249     match r {
250         ty::ReLateBound(id, br) => {
251             mywrite!(w, "b[{}|", id.depth);
252             enc_bound_region(w, cx, br);
253             mywrite!(w, "]");
254         }
255         ty::ReEarlyBound(ref data) => {
256             mywrite!(w, "B[{}|{}|{}|{}]",
257                      (cx.ds)(data.def_id),
258                      data.space.to_uint(),
259                      data.index,
260                      data.name);
261         }
262         ty::ReFree(ref fr) => {
263             mywrite!(w, "f[");
264             enc_scope(w, cx, fr.scope);
265             mywrite!(w, "|");
266             enc_bound_region(w, cx, fr.bound_region);
267             mywrite!(w, "]");
268         }
269         ty::ReScope(scope) => {
270             mywrite!(w, "s");
271             enc_scope(w, cx, scope);
272             mywrite!(w, "|");
273         }
274         ty::ReStatic => {
275             mywrite!(w, "t");
276         }
277         ty::ReEmpty => {
278             mywrite!(w, "e");
279         }
280         ty::ReVar(_) | ty::ReSkolemized(..) => {
281             // these should not crop up after typeck
282             cx.diag.handler().bug("cannot encode region variables");
283         }
284     }
285 }
286
287 fn enc_scope(w: &mut Encoder, cx: &ctxt, scope: region::CodeExtent) {
288     match cx.tcx.region_maps.code_extent_data(scope) {
289         region::CodeExtentData::ParameterScope {
290             fn_id, body_id } => mywrite!(w, "P[{}|{}]", fn_id, body_id),
291         region::CodeExtentData::Misc(node_id) => mywrite!(w, "M{}", node_id),
292         region::CodeExtentData::Remainder(region::BlockRemainder {
293             block: b, first_statement_index: i }) => mywrite!(w, "B[{}|{}]", b, i),
294         region::CodeExtentData::DestructionScope(node_id) => mywrite!(w, "D{}", node_id),
295     }
296 }
297
298 fn enc_bound_region(w: &mut Encoder, cx: &ctxt, br: ty::BoundRegion) {
299     match br {
300         ty::BrAnon(idx) => {
301             mywrite!(w, "a{}|", idx);
302         }
303         ty::BrNamed(d, name) => {
304             mywrite!(w, "[{}|{}]",
305                      (cx.ds)(d),
306                      name);
307         }
308         ty::BrFresh(id) => {
309             mywrite!(w, "f{}|", id);
310         }
311         ty::BrEnv => {
312             mywrite!(w, "e|");
313         }
314     }
315 }
316
317 pub fn enc_trait_ref<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
318                                s: ty::TraitRef<'tcx>) {
319     mywrite!(w, "{}|", (cx.ds)(s.def_id));
320     enc_substs(w, cx, s.substs);
321 }
322
323 fn enc_unsafety(w: &mut Encoder, p: hir::Unsafety) {
324     match p {
325         hir::Unsafety::Normal => mywrite!(w, "n"),
326         hir::Unsafety::Unsafe => mywrite!(w, "u"),
327     }
328 }
329
330 fn enc_abi(w: &mut Encoder, abi: Abi) {
331     mywrite!(w, "[");
332     mywrite!(w, "{}", abi.name());
333     mywrite!(w, "]")
334 }
335
336 pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
337                                 ft: &ty::BareFnTy<'tcx>) {
338     enc_unsafety(w, ft.unsafety);
339     enc_abi(w, ft.abi);
340     enc_fn_sig(w, cx, &ft.sig);
341 }
342
343 pub fn enc_closure_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
344                                 ft: &ty::ClosureTy<'tcx>) {
345     enc_unsafety(w, ft.unsafety);
346     enc_fn_sig(w, cx, &ft.sig);
347     enc_abi(w, ft.abi);
348 }
349
350 fn enc_fn_sig<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
351                         fsig: &ty::PolyFnSig<'tcx>) {
352     mywrite!(w, "[");
353     for ty in &fsig.0.inputs {
354         enc_ty(w, cx, *ty);
355     }
356     mywrite!(w, "]");
357     if fsig.0.variadic {
358         mywrite!(w, "V");
359     } else {
360         mywrite!(w, "N");
361     }
362     match fsig.0.output {
363         ty::FnConverging(result_type) => {
364             enc_ty(w, cx, result_type);
365         }
366         ty::FnDiverging => {
367             mywrite!(w, "z");
368         }
369     }
370 }
371
372 pub fn enc_builtin_bounds(w: &mut Encoder, _cx: &ctxt, bs: &ty::BuiltinBounds) {
373     for bound in bs {
374         match bound {
375             ty::BoundSend => mywrite!(w, "S"),
376             ty::BoundSized => mywrite!(w, "Z"),
377             ty::BoundCopy => mywrite!(w, "P"),
378             ty::BoundSync => mywrite!(w, "T"),
379         }
380     }
381
382     mywrite!(w, ".");
383 }
384
385 pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder,
386                                        cx: &ctxt<'a,'tcx>,
387                                        bs: &ty::ExistentialBounds<'tcx>) {
388     enc_builtin_bounds(w, cx, &bs.builtin_bounds);
389
390     enc_region(w, cx, bs.region_bound);
391
392     for tp in &bs.projection_bounds {
393         mywrite!(w, "P");
394         enc_projection_predicate(w, cx, &tp.0);
395     }
396
397     mywrite!(w, ".");
398 }
399
400 pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
401                                     v: &ty::TypeParameterDef<'tcx>) {
402     mywrite!(w, "{}:{}|{}|{}|{}|",
403              v.name, (cx.ds)(v.def_id),
404              v.space.to_uint(), v.index, (cx.ds)(v.default_def_id));
405     enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
406     enc_object_lifetime_default(w, cx, v.object_lifetime_default);
407 }
408
409 pub fn enc_region_param_def(w: &mut Encoder, cx: &ctxt,
410                             v: &ty::RegionParameterDef) {
411     mywrite!(w, "{}:{}|{}|{}|",
412              v.name, (cx.ds)(v.def_id),
413              v.space.to_uint(), v.index);
414     for &r in &v.bounds {
415         mywrite!(w, "R");
416         enc_region(w, cx, r);
417     }
418     mywrite!(w, ".");
419 }
420
421 fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Encoder,
422                                          cx: &ctxt<'a, 'tcx>,
423                                          default: ty::ObjectLifetimeDefault)
424 {
425     match default {
426         ty::ObjectLifetimeDefault::Ambiguous => mywrite!(w, "a"),
427         ty::ObjectLifetimeDefault::BaseDefault => mywrite!(w, "b"),
428         ty::ObjectLifetimeDefault::Specific(r) => {
429             mywrite!(w, "s");
430             enc_region(w, cx, r);
431         }
432     }
433 }
434
435 pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder,
436                                cx: &ctxt<'a, 'tcx>,
437                                p: &ty::Predicate<'tcx>)
438 {
439     match *p {
440         ty::Predicate::Trait(ref trait_ref) => {
441             mywrite!(w, "t");
442             enc_trait_ref(w, cx, trait_ref.0.trait_ref);
443         }
444         ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
445             mywrite!(w, "e");
446             enc_ty(w, cx, a);
447             enc_ty(w, cx, b);
448         }
449         ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
450             mywrite!(w, "r");
451             enc_region(w, cx, a);
452             enc_region(w, cx, b);
453         }
454         ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
455             mywrite!(w, "o");
456             enc_ty(w, cx, a);
457             enc_region(w, cx, b);
458         }
459         ty::Predicate::Projection(ty::Binder(ref data)) => {
460             mywrite!(w, "p");
461             enc_projection_predicate(w, cx, data)
462         }
463         ty::Predicate::WellFormed(data) => {
464             mywrite!(w, "w");
465             enc_ty(w, cx, data);
466         }
467         ty::Predicate::ObjectSafe(trait_def_id) => {
468             mywrite!(w, "O{}|", (cx.ds)(trait_def_id));
469         }
470     }
471 }
472
473 fn enc_projection_predicate<'a, 'tcx>(w: &mut Encoder,
474                                       cx: &ctxt<'a, 'tcx>,
475                                       data: &ty::ProjectionPredicate<'tcx>) {
476     enc_trait_ref(w, cx, data.projection_ty.trait_ref);
477     mywrite!(w, "{}|", data.projection_ty.item_name);
478     enc_ty(w, cx, data.ty);
479 }