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