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.
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.
13 #![allow(unused_must_use)] // as with encoding, everything is a no-fail MemWriter
14 #![allow(non_camel_case_types)]
16 use std::cell::RefCell;
18 use std::io::prelude::*;
20 use rustc::hir::def_id::DefId;
22 use rustc::ty::subst::Substs;
23 use rustc::ty::{self, Ty, TyCtxt};
24 use rustc::util::nodemap::FnvHashMap;
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,
40 pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
41 pub abbrevs: &'a abbrev_map<'tcx>
44 impl<'a, 'tcx> encoder::EncodeContext<'a, 'tcx> {
45 pub fn ty_str_ctxt<'b>(&'b self) -> ctxt<'b, 'tcx> {
47 diag: self.tcx.sess.diagnostic(),
48 ds: encoder::def_to_string,
50 abbrevs: &self.type_abbrevs
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 {
62 pub type abbrev_map<'tcx> = RefCell<FnvHashMap<Ty<'tcx>, ty_abbrev>>;
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) {
70 let pos = w.position();
73 ty::TyBool => { write!(w, "b"); }
74 ty::TyChar => { write!(w, "c"); }
75 ty::TyNever => { write!(w, "!"); }
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")
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")
96 ast::FloatTy::F32 => write!(w, "Mf"),
97 ast::FloatTy::F64 => write!(w, "MF"),
100 ty::TyEnum(def, substs) => {
101 write!(w, "t[{}|", (cx.ds)(cx.tcx, def.did));
102 enc_substs(w, cx, substs);
105 ty::TyTrait(ref obj) => {
107 enc_existential_trait_ref(w, cx, obj.principal.0);
108 enc_builtin_bounds(w, cx, &obj.builtin_bounds);
110 enc_region(w, cx, obj.region_bound);
112 // Encode projection_bounds in a stable order
113 let mut projection_bounds: Vec<_> = obj.projection_bounds
115 .map(|b| (b.item_name().as_str(), b))
117 projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
119 for tp in projection_bounds.iter().map(|&(_, tp)| tp) {
121 enc_existential_projection(w, cx, &tp.0);
129 for t in ts { enc_ty(w, cx, *t); }
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) => {
136 enc_region(w, cx, *r);
139 ty::TyArray(t, sz) => {
142 write!(w, "/{}|", sz);
152 ty::TyFnDef(def_id, substs, f) => {
154 write!(w, "{}|", (cx.ds)(cx.tcx, def_id));
155 enc_substs(w, cx, substs);
156 enc_bare_fn_ty(w, cx, f);
160 enc_bare_fn_ty(w, cx, f);
163 bug!("cannot encode inference variable types");
166 write!(w, "p[{}|{}]", p.idx, p.name);
168 ty::TyStruct(def, substs) => {
169 write!(w, "a[{}|", (cx.ds)(cx.tcx, def.did));
170 enc_substs(w, cx, substs);
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 {
182 ty::TyProjection(ref data) => {
184 enc_trait_ref(w, cx, data.trait_ref);
185 write!(w, "{}]", data.item_name);
187 ty::TyAnon(def_id, substs) => {
188 write!(w, "A[{}|", (cx.ds)(cx.tcx, def_id));
189 enc_substs(w, cx, substs);
197 let end = w.position();
200 let mut abbrev = Cursor::new(Vec::with_capacity(16));
201 abbrev.write_all(b"#");
203 let start_position = abbrev.position() as usize;
204 let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(),
207 abbrev.set_position((start_position + bytes_written) as u64);
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()
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()
222 fn enc_mutability(w: &mut Cursor<Vec<u8>>, mt: hir::Mutability) {
224 hir::MutImmutable => (),
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);
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),
251 pub fn enc_substs<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
252 substs: &Substs<'tcx>) {
254 for &r in &substs.regions {
255 enc_region(w, cx, r);
258 for &ty in &substs.types {
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));
270 generics.parent_regions,
271 generics.parent_types);
273 for r in &generics.regions {
274 enc_region_param_def(w, cx, r)
277 for t in &generics.types {
278 enc_type_param_def(w, cx, t);
282 if generics.has_self {
289 pub fn enc_region(w: &mut Cursor<Vec<u8>>, cx: &ctxt, r: ty::Region) {
291 ty::ReLateBound(id, br) => {
292 write!(w, "b[{}|", id.depth);
293 enc_bound_region(w, cx, br);
296 ty::ReEarlyBound(ref data) => {
297 write!(w, "B[{}|{}]",
301 ty::ReFree(ref fr) => {
303 enc_scope(w, cx, fr.scope);
305 enc_bound_region(w, cx, fr.bound_region);
308 ty::ReScope(scope) => {
310 enc_scope(w, cx, scope);
322 ty::ReVar(_) | ty::ReSkolemized(..) => {
323 // these should not crop up after typeck
324 bug!("cannot encode region variables");
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),
342 fn enc_bound_region(w: &mut Cursor<Vec<u8>>, cx: &ctxt, br: ty::BoundRegion) {
345 write!(w, "a{}|", idx);
347 ty::BrNamed(d, name, issue32330) => {
353 ty::Issue32330::WontChange =>
355 ty::Issue32330::WillChange { fn_def_id, region_name } =>
356 write!(w, "y{}|{}]", (cx.ds)(cx.tcx, fn_def_id), region_name),
360 write!(w, "f{}|", id);
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);
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);
380 fn enc_unsafety(w: &mut Cursor<Vec<u8>>, p: hir::Unsafety) {
382 hir::Unsafety::Normal => write!(w, "n"),
383 hir::Unsafety::Unsafe => write!(w, "u"),
387 fn enc_abi(w: &mut Cursor<Vec<u8>>, abi: Abi) {
389 write!(w, "{}", abi.name());
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);
397 enc_fn_sig(w, cx, &ft.sig);
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);
407 fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
408 fsig: &ty::PolyFnSig<'tcx>) {
410 for ty in &fsig.0.inputs {
419 enc_ty(w, cx, fsig.0.output);
422 fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinBounds) {
425 ty::BoundSend => write!(w, "S"),
426 ty::BoundSized => write!(w, "Z"),
427 ty::BoundCopy => write!(w, "P"),
428 ty::BoundSync => write!(w, "T"),
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);
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 {
450 enc_region(w, cx, r);
455 fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
457 default: ty::ObjectLifetimeDefault)
460 ty::ObjectLifetimeDefault::Ambiguous => {
463 ty::ObjectLifetimeDefault::BaseDefault => {
466 ty::ObjectLifetimeDefault::Specific(r) => {
468 enc_region(w, cx, r);
473 pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
475 p: &ty::Predicate<'tcx>)
478 ty::Predicate::Rfc1592(..) => {
479 bug!("RFC1592 predicate in metadata `{:?}`", p);
481 ty::Predicate::Trait(ref trait_ref) => {
483 enc_trait_ref(w, cx, trait_ref.0.trait_ref);
485 ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
490 ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
492 enc_region(w, cx, a);
493 enc_region(w, cx, b);
495 ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
498 enc_region(w, cx, b);
500 ty::Predicate::Projection(ty::Binder(ref data)) => {
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);
506 ty::Predicate::WellFormed(data) => {
510 ty::Predicate::ObjectSafe(trait_def_id) => {
511 write!(w, "O{}|", (cx.ds)(cx.tcx, trait_def_id));
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',
519 write!(w, "c{}|{}|", (cx.ds)(cx.tcx, closure_def_id), kind_char);
524 fn enc_existential_projection<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
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);