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