]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/tyencode.rs
auto merge of #14831 : alexcrichton/rust/format-intl, r=brson
[rust.git] / src / librustc / metadata / tyencode.rs
1 // Copyright 2012-2014 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::collections::HashMap;
18 use std::io::MemWriter;
19
20 use middle::subst;
21 use middle::ty::param_ty;
22 use middle::ty;
23
24 use syntax::abi::Abi;
25 use syntax::ast;
26 use syntax::ast::*;
27 use syntax::diagnostic::SpanHandler;
28 use syntax::parse::token;
29
30 macro_rules! mywrite( ($($arg:tt)*) => ({ write!($($arg)*); }) )
31
32 pub struct ctxt<'a> {
33     pub diag: &'a SpanHandler,
34     // Def -> str Callback:
35     pub ds: fn(DefId) -> String,
36     // The type context.
37     pub tcx: &'a ty::ctxt,
38     pub abbrevs: &'a abbrev_map
39 }
40
41 // Compact string representation for ty.t values. API ty_str & parse_from_str.
42 // Extra parameters are for converting to/from def_ids in the string rep.
43 // Whatever format you choose should not contain pipe characters.
44 pub struct ty_abbrev {
45     s: String
46 }
47
48 pub type abbrev_map = RefCell<HashMap<ty::t, ty_abbrev>>;
49
50 #[cfg(stage0)]
51 pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
52     match cx.abbrevs.borrow_mut().find(&t) {
53         Some(a) => { w.write(a.s.as_bytes()); return; }
54         None => {}
55     }
56     let pos = w.tell().unwrap();
57     enc_sty(w, cx, &ty::get(t).sty);
58     let end = w.tell().unwrap();
59     let len = end - pos;
60     fn estimate_sz(u: u64) -> u64 {
61         let mut n = u;
62         let mut len = 0;
63         while n != 0 { len += 1; n = n >> 4; }
64         return len;
65     }
66     let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
67     if abbrev_len < len {
68         // I.e. it's actually an abbreviation.
69         cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
70             s: format!("\\#{:x}:{:x}\\#", pos, len)
71         });
72     }
73 }
74 #[cfg(not(stage0))]
75 pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
76     match cx.abbrevs.borrow_mut().find(&t) {
77         Some(a) => { w.write(a.s.as_bytes()); return; }
78         None => {}
79     }
80     let pos = w.tell().unwrap();
81     enc_sty(w, cx, &ty::get(t).sty);
82     let end = w.tell().unwrap();
83     let len = end - pos;
84     fn estimate_sz(u: u64) -> u64 {
85         let mut n = u;
86         let mut len = 0;
87         while n != 0 { len += 1; n = n >> 4; }
88         return len;
89     }
90     let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
91     if abbrev_len < len {
92         // I.e. it's actually an abbreviation.
93         cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
94             s: format!("#{:x}:{:x}#", pos, len)
95         });
96     }
97 }
98
99 fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) {
100     match mt {
101         MutImmutable => (),
102         MutMutable => mywrite!(w, "m"),
103     }
104 }
105
106 fn enc_mt(w: &mut MemWriter, cx: &ctxt, mt: ty::mt) {
107     enc_mutability(w, mt.mutbl);
108     enc_ty(w, cx, mt.ty);
109 }
110
111 fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
112     match t {
113         None => mywrite!(w, "n"),
114         Some(v) => {
115             mywrite!(w, "s");
116             enc_f(w, v);
117         }
118     }
119 }
120
121 pub fn enc_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::Substs) {
122     enc_region_substs(w, cx, &substs.regions);
123     enc_opt(w, substs.self_ty, |w, t| enc_ty(w, cx, t));
124     mywrite!(w, "[");
125     for t in substs.tps.iter() { enc_ty(w, cx, *t); }
126     mywrite!(w, "]");
127 }
128
129 fn enc_region_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
130     match *substs {
131         subst::ErasedRegions => {
132             mywrite!(w, "e");
133         }
134         subst::NonerasedRegions(ref regions) => {
135             mywrite!(w, "n");
136             for &r in regions.iter() {
137                 enc_region(w, cx, r);
138             }
139             mywrite!(w, ".");
140         }
141     }
142 }
143
144 fn enc_region(w: &mut MemWriter, cx: &ctxt, r: ty::Region) {
145     match r {
146         ty::ReLateBound(id, br) => {
147             mywrite!(w, "b[{}|", id);
148             enc_bound_region(w, cx, br);
149             mywrite!(w, "]");
150         }
151         ty::ReEarlyBound(node_id, index, name) => {
152             mywrite!(w, "B[{}|{}|{}]",
153                      node_id,
154                      index,
155                      token::get_name(name));
156         }
157         ty::ReFree(ref fr) => {
158             mywrite!(w, "f[{}|", fr.scope_id);
159             enc_bound_region(w, cx, fr.bound_region);
160             mywrite!(w, "]");
161         }
162         ty::ReScope(nid) => {
163             mywrite!(w, "s{}|", nid);
164         }
165         ty::ReStatic => {
166             mywrite!(w, "t");
167         }
168         ty::ReEmpty => {
169             mywrite!(w, "e");
170         }
171         ty::ReInfer(_) => {
172             // these should not crop up after typeck
173             cx.diag.handler().bug("cannot encode region variables");
174         }
175     }
176 }
177
178 fn enc_bound_region(w: &mut MemWriter, cx: &ctxt, br: ty::BoundRegion) {
179     match br {
180         ty::BrAnon(idx) => {
181             mywrite!(w, "a{}|", idx);
182         }
183         ty::BrNamed(d, name) => {
184             mywrite!(w, "[{}|{}]",
185                      (cx.ds)(d),
186                      token::get_name(name));
187         }
188         ty::BrFresh(id) => {
189             mywrite!(w, "f{}|", id);
190         }
191     }
192 }
193
194 pub fn enc_trait_ref(w: &mut MemWriter, cx: &ctxt, s: &ty::TraitRef) {
195     mywrite!(w, "{}|", (cx.ds)(s.def_id));
196     enc_substs(w, cx, &s.substs);
197 }
198
199 pub fn enc_trait_store(w: &mut MemWriter, cx: &ctxt, s: ty::TraitStore) {
200     match s {
201         ty::UniqTraitStore => mywrite!(w, "~"),
202         ty::RegionTraitStore(re, m) => {
203             mywrite!(w, "&");
204             enc_region(w, cx, re);
205             enc_mutability(w, m);
206         }
207     }
208 }
209
210 fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
211     match *st {
212         ty::ty_nil => mywrite!(w, "n"),
213         ty::ty_bot => mywrite!(w, "z"),
214         ty::ty_bool => mywrite!(w, "b"),
215         ty::ty_char => mywrite!(w, "c"),
216         ty::ty_int(t) => {
217             match t {
218                 TyI => mywrite!(w, "i"),
219                 TyI8 => mywrite!(w, "MB"),
220                 TyI16 => mywrite!(w, "MW"),
221                 TyI32 => mywrite!(w, "ML"),
222                 TyI64 => mywrite!(w, "MD")
223             }
224         }
225         ty::ty_uint(t) => {
226             match t {
227                 TyU => mywrite!(w, "u"),
228                 TyU8 => mywrite!(w, "Mb"),
229                 TyU16 => mywrite!(w, "Mw"),
230                 TyU32 => mywrite!(w, "Ml"),
231                 TyU64 => mywrite!(w, "Md")
232             }
233         }
234         ty::ty_float(t) => {
235             match t {
236                 TyF32 => mywrite!(w, "Mf"),
237                 TyF64 => mywrite!(w, "MF"),
238                 TyF128 => mywrite!(w, "MQ")
239             }
240         }
241         ty::ty_enum(def, ref substs) => {
242             mywrite!(w, "t[{}|", (cx.ds)(def));
243             enc_substs(w, cx, substs);
244             mywrite!(w, "]");
245         }
246         ty::ty_trait(box ty::TyTrait {
247                 def_id,
248                 ref substs,
249                 store,
250                 bounds
251             }) => {
252             mywrite!(w, "x[{}|", (cx.ds)(def_id));
253             enc_substs(w, cx, substs);
254             enc_trait_store(w, cx, store);
255             let bounds = ty::ParamBounds {builtin_bounds: bounds,
256                                           trait_bounds: Vec::new()};
257             enc_bounds(w, cx, &bounds);
258             mywrite!(w, "]");
259         }
260         ty::ty_tup(ref ts) => {
261             mywrite!(w, "T[");
262             for t in ts.iter() { enc_ty(w, cx, *t); }
263             mywrite!(w, "]");
264         }
265         ty::ty_box(typ) => { mywrite!(w, "@"); enc_ty(w, cx, typ); }
266         ty::ty_uniq(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
267         ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
268         ty::ty_rptr(r, mt) => {
269             mywrite!(w, "&");
270             enc_region(w, cx, r);
271             enc_mt(w, cx, mt);
272         }
273         ty::ty_vec(mt, sz) => {
274             mywrite!(w, "V");
275             enc_mt(w, cx, mt);
276             mywrite!(w, "/");
277             match sz {
278                 Some(n) => mywrite!(w, "{}|", n),
279                 None => mywrite!(w, "|"),
280             }
281         }
282         ty::ty_str => {
283             mywrite!(w, "v");
284         }
285         ty::ty_closure(ref f) => {
286             mywrite!(w, "f");
287             enc_closure_ty(w, cx, *f);
288         }
289         ty::ty_bare_fn(ref f) => {
290             mywrite!(w, "F");
291             enc_bare_fn_ty(w, cx, f);
292         }
293         ty::ty_infer(_) => {
294             cx.diag.handler().bug("cannot encode inference variable types");
295         }
296         ty::ty_param(param_ty {idx: id, def_id: did}) => {
297             mywrite!(w, "p{}|{}", (cx.ds)(did), id);
298         }
299         ty::ty_self(did) => {
300             mywrite!(w, "s{}|", (cx.ds)(did));
301         }
302         ty::ty_struct(def, ref substs) => {
303             mywrite!(w, "a[{}|", (cx.ds)(def));
304             enc_substs(w, cx, substs);
305             mywrite!(w, "]");
306         }
307         ty::ty_err => fail!("shouldn't encode error type")
308     }
309 }
310
311 fn enc_fn_style(w: &mut MemWriter, p: FnStyle) {
312     match p {
313         NormalFn => mywrite!(w, "n"),
314         UnsafeFn => mywrite!(w, "u"),
315     }
316 }
317
318 fn enc_abi(w: &mut MemWriter, abi: Abi) {
319     mywrite!(w, "[");
320     mywrite!(w, "{}", abi.name());
321     mywrite!(w, "]")
322 }
323
324 fn enc_onceness(w: &mut MemWriter, o: Onceness) {
325     match o {
326         Once => mywrite!(w, "o"),
327         Many => mywrite!(w, "m")
328     }
329 }
330
331 pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
332     enc_fn_style(w, ft.fn_style);
333     enc_abi(w, ft.abi);
334     enc_fn_sig(w, cx, &ft.sig);
335 }
336
337 fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
338     enc_fn_style(w, ft.fn_style);
339     enc_onceness(w, ft.onceness);
340     enc_trait_store(w, cx, ft.store);
341     let bounds = ty::ParamBounds {builtin_bounds: ft.bounds,
342                                   trait_bounds: Vec::new()};
343     enc_bounds(w, cx, &bounds);
344     enc_fn_sig(w, cx, &ft.sig);
345 }
346
347 fn enc_fn_sig(w: &mut MemWriter, cx: &ctxt, fsig: &ty::FnSig) {
348     mywrite!(w, "[{}|", fsig.binder_id);
349     for ty in fsig.inputs.iter() {
350         enc_ty(w, cx, *ty);
351     }
352     mywrite!(w, "]");
353     if fsig.variadic {
354         mywrite!(w, "V");
355     } else {
356         mywrite!(w, "N");
357     }
358     enc_ty(w, cx, fsig.output);
359 }
360
361 fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
362     for bound in bs.builtin_bounds.iter() {
363         match bound {
364             ty::BoundSend => mywrite!(w, "S"),
365             ty::BoundStatic => mywrite!(w, "O"),
366             ty::BoundSized => mywrite!(w, "Z"),
367             ty::BoundCopy => mywrite!(w, "P"),
368             ty::BoundShare => mywrite!(w, "T"),
369         }
370     }
371
372     for tp in bs.trait_bounds.iter() {
373         mywrite!(w, "I");
374         enc_trait_ref(w, cx, &**tp);
375     }
376
377     mywrite!(w, ".");
378 }
379
380 pub fn enc_type_param_def(w: &mut MemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
381     mywrite!(w, "{}:{}|", token::get_ident(v.ident), (cx.ds)(v.def_id));
382     enc_bounds(w, cx, &*v.bounds);
383     enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
384 }