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