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