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