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