]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/tydecode.rs
Auto merge of #35719 - Amanieu:atomic_access, r=alexcrichton
[rust.git] / src / librustc_metadata / tydecode.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
12 // Type decoding
13
14 // tjc note: Would be great to have a `match check` macro equivalent
15 // for some of these
16
17 #![allow(non_camel_case_types)]
18
19 use rustc::hir;
20
21 use rustc::hir::def_id::{DefId, DefIndex};
22 use middle::region;
23 use rustc::ty::subst::Substs;
24 use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
25
26 use rbml;
27 use rbml::leb128;
28 use std::str;
29 use syntax::abi;
30 use syntax::ast;
31 use syntax::parse::token;
32
33 // Compact string representation for Ty values. API TyStr &
34 // parse_from_str. Extra parameters are for converting to/from def_ids in the
35 // data buffer. Whatever format you choose should not contain pipe characters.
36
37 pub type DefIdConvert<'a> = &'a mut FnMut(DefId) -> DefId;
38
39 pub struct TyDecoder<'a, 'tcx: 'a> {
40     data: &'a [u8],
41     krate: ast::CrateNum,
42     pos: usize,
43     tcx: TyCtxt<'a, 'tcx, 'tcx>,
44     conv_def_id: DefIdConvert<'a>,
45 }
46
47 impl<'a,'tcx> TyDecoder<'a,'tcx> {
48     pub fn with_doc(tcx: TyCtxt<'a, 'tcx, 'tcx>,
49                     crate_num: ast::CrateNum,
50                     doc: rbml::Doc<'a>,
51                     conv: DefIdConvert<'a>)
52                     -> TyDecoder<'a,'tcx> {
53         TyDecoder::new(doc.data, crate_num, doc.start, tcx, conv)
54     }
55
56     pub fn new(data: &'a [u8],
57                crate_num: ast::CrateNum,
58                pos: usize,
59                tcx: TyCtxt<'a, 'tcx, 'tcx>,
60                conv: DefIdConvert<'a>)
61                -> TyDecoder<'a, 'tcx> {
62         TyDecoder {
63             data: data,
64             krate: crate_num,
65             pos: pos,
66             tcx: tcx,
67             conv_def_id: conv,
68         }
69     }
70
71     pub fn position(&self) -> usize {
72         self.pos
73     }
74
75     fn peek(&self) -> char {
76         self.data[self.pos] as char
77     }
78
79     fn next(&mut self) -> char {
80         let ch = self.data[self.pos] as char;
81         self.pos = self.pos + 1;
82         return ch;
83     }
84
85     fn next_byte(&mut self) -> u8 {
86         let b = self.data[self.pos];
87         self.pos = self.pos + 1;
88         return b;
89     }
90
91     fn scan<F>(&mut self, mut is_last: F) -> &'a [u8]
92         where F: FnMut(char) -> bool,
93     {
94         let start_pos = self.pos;
95         debug!("scan: '{}' (start)", self.data[self.pos] as char);
96         while !is_last(self.data[self.pos] as char) {
97             self.pos += 1;
98             debug!("scan: '{}'", self.data[self.pos] as char);
99         }
100         let end_pos = self.pos;
101         self.pos += 1;
102         return &self.data[start_pos..end_pos];
103     }
104
105     fn parse_vuint(&mut self) -> usize {
106         let (value, bytes_read) = leb128::read_unsigned_leb128(self.data,
107                                                                self.pos);
108         self.pos += bytes_read;
109         value as usize
110     }
111
112     fn parse_name(&mut self, last: char) -> ast::Name {
113         fn is_last(b: char, c: char) -> bool { return c == b; }
114         let bytes = self.scan(|a| is_last(last, a));
115         token::intern(str::from_utf8(bytes).unwrap())
116     }
117
118     fn parse_size(&mut self) -> Option<usize> {
119         assert_eq!(self.next(), '/');
120
121         if self.peek() == '|' {
122             assert_eq!(self.next(), '|');
123             None
124         } else {
125             let n = self.parse_uint();
126             assert_eq!(self.next(), '|');
127             Some(n)
128         }
129     }
130
131     pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> {
132         let mut regions = vec![];
133         let mut types = vec![];
134         assert_eq!(self.next(), '[');
135         while self.peek() != '|' {
136             regions.push(self.parse_region());
137         }
138         assert_eq!(self.next(), '|');
139         while self.peek() != ']' {
140             types.push(self.parse_ty());
141         }
142         assert_eq!(self.next(), ']');
143
144         Substs::new(self.tcx, types, regions)
145     }
146
147     pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> {
148         let parent = self.parse_opt(|this| this.parse_def());
149         let parent_regions = self.parse_u32();
150         assert_eq!(self.next(), '|');
151         let parent_types = self.parse_u32();
152
153         let mut regions = vec![];
154         let mut types = vec![];
155         assert_eq!(self.next(), '[');
156         while self.peek() != '|' {
157             regions.push(self.parse_region_param_def());
158         }
159         assert_eq!(self.next(), '|');
160         while self.peek() != ']' {
161             types.push(self.parse_type_param_def());
162         }
163         assert_eq!(self.next(), ']');
164
165         self.tcx.alloc_generics(ty::Generics {
166             parent: parent,
167             parent_regions: parent_regions,
168             parent_types: parent_types,
169             regions: regions,
170             types: types,
171             has_self: self.next() == 'S'
172         })
173     }
174
175     fn parse_bound_region(&mut self) -> ty::BoundRegion {
176         match self.next() {
177             'a' => {
178                 let id = self.parse_u32();
179                 assert_eq!(self.next(), '|');
180                 ty::BrAnon(id)
181             }
182             '[' => {
183                 let def = self.parse_def();
184                 let name = token::intern(&self.parse_str('|'));
185                 let issue32330 = match self.next() {
186                     'n' => {
187                         assert_eq!(self.next(), ']');
188                         ty::Issue32330::WontChange
189                     }
190                     'y' => {
191                         ty::Issue32330::WillChange {
192                             fn_def_id: self.parse_def(),
193                             region_name: token::intern(&self.parse_str(']')),
194                         }
195                     }
196                     c => panic!("expected n or y not {}", c)
197                 };
198                 ty::BrNamed(def, name, issue32330)
199             }
200             'f' => {
201                 let id = self.parse_u32();
202                 assert_eq!(self.next(), '|');
203                 ty::BrFresh(id)
204             }
205             'e' => ty::BrEnv,
206             _ => bug!("parse_bound_region: bad input")
207         }
208     }
209
210     pub fn parse_region(&mut self) -> ty::Region {
211         match self.next() {
212             'b' => {
213                 assert_eq!(self.next(), '[');
214                 let id = ty::DebruijnIndex::new(self.parse_u32());
215                 assert_eq!(self.next(), '|');
216                 let br = self.parse_bound_region();
217                 assert_eq!(self.next(), ']');
218                 ty::ReLateBound(id, br)
219             }
220             'B' => {
221                 assert_eq!(self.next(), '[');
222                 let index = self.parse_u32();
223                 assert_eq!(self.next(), '|');
224                 let name = token::intern(&self.parse_str(']'));
225                 ty::ReEarlyBound(ty::EarlyBoundRegion {
226                     index: index,
227                     name: name
228                 })
229             }
230             'f' => {
231                 assert_eq!(self.next(), '[');
232                 let scope = self.parse_scope();
233                 assert_eq!(self.next(), '|');
234                 let br = self.parse_bound_region();
235                 assert_eq!(self.next(), ']');
236                 ty::ReFree(ty::FreeRegion { scope: scope,
237                                             bound_region: br})
238             }
239             's' => {
240                 let scope = self.parse_scope();
241                 assert_eq!(self.next(), '|');
242                 ty::ReScope(scope)
243             }
244             't' => ty::ReStatic,
245             'e' => ty::ReEmpty,
246             'E' => ty::ReErased,
247             _ => bug!("parse_region: bad input")
248         }
249     }
250
251     fn parse_scope(&mut self) -> region::CodeExtent {
252         self.tcx.region_maps.bogus_code_extent(match self.next() {
253             // This creates scopes with the wrong NodeId. This isn't
254             // actually a problem because scopes only exist *within*
255             // functions, and functions aren't loaded until trans which
256             // doesn't care about regions.
257             //
258             // May still be worth fixing though.
259             'C' => {
260                 assert_eq!(self.next(), '[');
261                 let fn_id = self.parse_uint() as ast::NodeId;
262                 assert_eq!(self.next(), '|');
263                 let body_id = self.parse_uint() as ast::NodeId;
264                 assert_eq!(self.next(), ']');
265                 region::CodeExtentData::CallSiteScope {
266                     fn_id: fn_id, body_id: body_id
267                 }
268             }
269             // This creates scopes with the wrong NodeId. (See note above.)
270             'P' => {
271                 assert_eq!(self.next(), '[');
272                 let fn_id = self.parse_uint() as ast::NodeId;
273                 assert_eq!(self.next(), '|');
274                 let body_id = self.parse_uint() as ast::NodeId;
275                 assert_eq!(self.next(), ']');
276                 region::CodeExtentData::ParameterScope {
277                     fn_id: fn_id, body_id: body_id
278                 }
279             }
280             'M' => {
281                 let node_id = self.parse_uint() as ast::NodeId;
282                 region::CodeExtentData::Misc(node_id)
283             }
284             'D' => {
285                 let node_id = self.parse_uint() as ast::NodeId;
286                 region::CodeExtentData::DestructionScope(node_id)
287             }
288             'B' => {
289                 assert_eq!(self.next(), '[');
290                 let node_id = self.parse_uint() as ast::NodeId;
291                 assert_eq!(self.next(), '|');
292                 let first_stmt_index = self.parse_u32();
293                 assert_eq!(self.next(), ']');
294                 let block_remainder = region::BlockRemainder {
295                     block: node_id, first_statement_index: first_stmt_index,
296                 };
297                 region::CodeExtentData::Remainder(block_remainder)
298             }
299             _ => bug!("parse_scope: bad input")
300         })
301     }
302
303     fn parse_opt<T, F>(&mut self, f: F) -> Option<T>
304         where F: FnOnce(&mut TyDecoder<'a, 'tcx>) -> T,
305     {
306         match self.next() {
307             'n' => None,
308             's' => Some(f(self)),
309             _ => bug!("parse_opt: bad input")
310         }
311     }
312
313     fn parse_str(&mut self, term: char) -> String {
314         let mut result = String::new();
315         while self.peek() != term {
316             unsafe {
317                 result.as_mut_vec().extend_from_slice(&[self.next_byte()])
318             }
319         }
320         self.next();
321         result
322     }
323
324     pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
325         ty::TraitRef {
326             def_id: self.parse_def(),
327             substs: self.parse_substs()
328         }
329     }
330
331     pub fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> {
332         ty::ExistentialTraitRef {
333             def_id: self.parse_def(),
334             substs: self.parse_substs()
335         }
336     }
337
338     pub fn parse_ty(&mut self) -> Ty<'tcx> {
339         let tcx = self.tcx;
340         match self.next() {
341             'b' => return tcx.types.bool,
342             '!' => return tcx.types.never,
343             'i' => { /* eat the s of is */ self.next(); return tcx.types.isize },
344             'u' => { /* eat the s of us */ self.next(); return tcx.types.usize },
345             'M' => {
346                 match self.next() {
347                     'b' => return tcx.types.u8,
348                     'w' => return tcx.types.u16,
349                     'l' => return tcx.types.u32,
350                     'd' => return tcx.types.u64,
351                     'B' => return tcx.types.i8,
352                     'W' => return tcx.types.i16,
353                     'L' => return tcx.types.i32,
354                     'D' => return tcx.types.i64,
355                     'f' => return tcx.types.f32,
356                     'F' => return tcx.types.f64,
357                     _ => bug!("parse_ty: bad numeric type")
358                 }
359             }
360             'c' => return tcx.types.char,
361             't' => {
362                 assert_eq!(self.next(), '[');
363                 let did = self.parse_def();
364                 let substs = self.parse_substs();
365                 assert_eq!(self.next(), ']');
366                 let def = self.tcx.lookup_adt_def(did);
367                 return tcx.mk_enum(def, substs);
368             }
369             'x' => {
370                 assert_eq!(self.next(), '[');
371                 let trait_ref = ty::Binder(self.parse_existential_trait_ref());
372                 let builtin_bounds = self.parse_builtin_bounds();
373                 let region_bound = self.parse_region();
374                 let mut projection_bounds = Vec::new();
375
376                 loop {
377                     match self.next() {
378                         'P' => {
379                             let bound = self.parse_existential_projection();
380                             projection_bounds.push(ty::Binder(bound));
381                         }
382                         '.' => { break; }
383                         c => {
384                             bug!("parse_bounds: bad bounds ('{}')", c)
385                         }
386                     }
387                 }
388                 assert_eq!(self.next(), ']');
389                 return tcx.mk_trait(ty::TraitObject {
390                     principal: trait_ref,
391                     region_bound: region_bound,
392                     builtin_bounds: builtin_bounds,
393                     projection_bounds: projection_bounds
394                 });
395             }
396             'p' => {
397                 assert_eq!(self.next(), '[');
398                 let index = self.parse_u32();
399                 assert_eq!(self.next(), '|');
400                 let name = token::intern(&self.parse_str(']'));
401                 return tcx.mk_param(index, name);
402             }
403             '~' => return tcx.mk_box(self.parse_ty()),
404             '*' => return tcx.mk_ptr(self.parse_mt()),
405             '&' => {
406                 let r = self.parse_region();
407                 let mt = self.parse_mt();
408                 return tcx.mk_ref(tcx.mk_region(r), mt);
409             }
410             'V' => {
411                 let t = self.parse_ty();
412                 return match self.parse_size() {
413                     Some(n) => tcx.mk_array(t, n),
414                     None => tcx.mk_slice(t)
415                 };
416             }
417             'v' => {
418                 return tcx.mk_str();
419             }
420             'T' => {
421                 assert_eq!(self.next(), '[');
422                 let mut params = Vec::new();
423                 while self.peek() != ']' { params.push(self.parse_ty()); }
424                 self.pos = self.pos + 1;
425                 return tcx.mk_tup(params);
426             }
427             'F' => {
428                 let def_id = self.parse_def();
429                 let substs = self.parse_substs();
430                 return tcx.mk_fn_def(def_id, substs, self.parse_bare_fn_ty());
431             }
432             'G' => {
433                 return tcx.mk_fn_ptr(self.parse_bare_fn_ty());
434             }
435             '#' => {
436                 // This is a hacky little caching scheme. The idea is that if we encode
437                 // the same type twice, the second (and third, and fourth...) time we will
438                 // just write `#123`, where `123` is the offset in the metadata of the
439                 // first appearance. Now when we are *decoding*, if we see a `#123`, we
440                 // can first check a cache (`tcx.rcache`) for that offset. If we find something,
441                 // we return it (modulo closure types, see below). But if not, then we
442                 // jump to offset 123 and read the type from there.
443
444                 let pos = self.parse_vuint();
445                 let key = ty::CReaderCacheKey { cnum: self.krate, pos: pos };
446                 if let Some(tt) = tcx.rcache.borrow().get(&key).cloned() {
447                     // If there is a closure buried in the type some where, then we
448                     // need to re-convert any def ids (see case 'k', below). That means
449                     // we can't reuse the cached version.
450                     if !tt.has_closure_types() {
451                         return tt;
452                     }
453                 }
454
455                 let mut substate = TyDecoder::new(self.data,
456                                                   self.krate,
457                                                   pos,
458                                                   self.tcx,
459                                                   self.conv_def_id);
460                 let tt = substate.parse_ty();
461                 tcx.rcache.borrow_mut().insert(key, tt);
462                 return tt;
463             }
464             '\"' => {
465                 let _ = self.parse_def();
466                 let inner = self.parse_ty();
467                 inner
468             }
469             'a' => {
470                 assert_eq!(self.next(), '[');
471                 let did = self.parse_def();
472                 let substs = self.parse_substs();
473                 assert_eq!(self.next(), ']');
474                 let def = self.tcx.lookup_adt_def(did);
475                 return self.tcx.mk_struct(def, substs);
476             }
477             'k' => {
478                 assert_eq!(self.next(), '[');
479                 let did = self.parse_def();
480                 let substs = self.parse_substs();
481                 let mut tys = vec![];
482                 while self.peek() != '.' {
483                     tys.push(self.parse_ty());
484                 }
485                 assert_eq!(self.next(), '.');
486                 assert_eq!(self.next(), ']');
487                 return self.tcx.mk_closure(did, substs, tys);
488             }
489             'P' => {
490                 assert_eq!(self.next(), '[');
491                 let trait_ref = self.parse_trait_ref();
492                 let name = token::intern(&self.parse_str(']'));
493                 return tcx.mk_projection(trait_ref, name);
494             }
495             'A' => {
496                 assert_eq!(self.next(), '[');
497                 let def_id = self.parse_def();
498                 let substs = self.parse_substs();
499                 assert_eq!(self.next(), ']');
500                 return self.tcx.mk_anon(def_id, substs);
501             }
502             'e' => {
503                 return tcx.types.err;
504             }
505             c => { bug!("unexpected char in type string: {}", c);}
506         }
507     }
508
509     fn parse_mutability(&mut self) -> hir::Mutability {
510         match self.peek() {
511             'm' => { self.next(); hir::MutMutable }
512             _ => { hir::MutImmutable }
513         }
514     }
515
516     fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> {
517         let m = self.parse_mutability();
518         ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
519     }
520
521     fn parse_def(&mut self) -> DefId {
522         let def_id = parse_defid(self.scan(|c| c == '|'));
523         return (self.conv_def_id)(def_id);
524     }
525
526     fn parse_uint(&mut self) -> usize {
527         let mut n = 0;
528         loop {
529             let cur = self.peek();
530             if cur < '0' || cur > '9' { return n; }
531             self.pos = self.pos + 1;
532             n *= 10;
533             n += (cur as usize) - ('0' as usize);
534         };
535     }
536
537     fn parse_u32(&mut self) -> u32 {
538         let n = self.parse_uint();
539         let m = n as u32;
540         assert_eq!(m as usize, n);
541         m
542     }
543
544     fn parse_abi_set(&mut self) -> abi::Abi {
545         assert_eq!(self.next(), '[');
546         let bytes = self.scan(|c| c == ']');
547         let abi_str = str::from_utf8(bytes).unwrap();
548         abi::lookup(&abi_str[..]).expect(abi_str)
549     }
550
551     pub fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
552         let unsafety = parse_unsafety(self.next());
553         let sig = self.parse_sig();
554         let abi = self.parse_abi_set();
555         ty::ClosureTy {
556             unsafety: unsafety,
557             sig: sig,
558             abi: abi,
559         }
560     }
561
562     pub fn parse_bare_fn_ty(&mut self) -> &'tcx ty::BareFnTy<'tcx> {
563         let unsafety = parse_unsafety(self.next());
564         let abi = self.parse_abi_set();
565         let sig = self.parse_sig();
566         self.tcx.mk_bare_fn(ty::BareFnTy {
567             unsafety: unsafety,
568             abi: abi,
569             sig: sig
570         })
571     }
572
573     fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> {
574         assert_eq!(self.next(), '[');
575         let mut inputs = Vec::new();
576         while self.peek() != ']' {
577             inputs.push(self.parse_ty());
578         }
579         self.pos += 1; // eat the ']'
580         let variadic = match self.next() {
581             'V' => true,
582             'N' => false,
583             r => bug!("bad variadic: {}", r),
584         };
585         let output = self.parse_ty();
586         ty::Binder(ty::FnSig {inputs: inputs,
587                               output: output,
588                               variadic: variadic})
589     }
590
591     pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
592         match self.next() {
593             't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
594             'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
595                                                   self.parse_ty())).to_predicate(),
596             'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(),
597                                                     self.parse_region())).to_predicate(),
598             'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(),
599                                                     self.parse_region())).to_predicate(),
600             'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
601             'w' => ty::Predicate::WellFormed(self.parse_ty()),
602             'O' => {
603                 let def_id = self.parse_def();
604                 assert_eq!(self.next(), '|');
605                 ty::Predicate::ObjectSafe(def_id)
606             }
607             'c' => {
608                 let def_id = self.parse_def();
609                 assert_eq!(self.next(), '|');
610                 let kind = match self.next() {
611                     'f' => ty::ClosureKind::Fn,
612                     'm' => ty::ClosureKind::FnMut,
613                     'o' => ty::ClosureKind::FnOnce,
614                     c => bug!("Encountered invalid character in metadata: {}", c)
615                 };
616                 assert_eq!(self.next(), '|');
617                 ty::Predicate::ClosureKind(def_id, kind)
618             }
619             c => bug!("Encountered invalid character in metadata: {}", c)
620         }
621     }
622
623     fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
624         ty::ProjectionPredicate {
625             projection_ty: ty::ProjectionTy {
626                 trait_ref: self.parse_trait_ref(),
627                 item_name: token::intern(&self.parse_str('|')),
628             },
629             ty: self.parse_ty(),
630         }
631     }
632
633     fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> {
634         ty::ExistentialProjection {
635             trait_ref: self.parse_existential_trait_ref(),
636             item_name: token::intern(&self.parse_str('|')),
637             ty: self.parse_ty(),
638         }
639     }
640
641     fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
642         let name = self.parse_name(':');
643         let def_id = self.parse_def();
644         let index = self.parse_u32();
645         assert_eq!(self.next(), '|');
646         let default_def_id = self.parse_def();
647         let default = self.parse_opt(|this| this.parse_ty());
648         let object_lifetime_default = self.parse_object_lifetime_default();
649
650         ty::TypeParameterDef {
651             name: name,
652             def_id: def_id,
653             index: index,
654             default_def_id: default_def_id,
655             default: default,
656             object_lifetime_default: object_lifetime_default,
657         }
658     }
659
660     fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
661         let name = self.parse_name(':');
662         let def_id = self.parse_def();
663         let index = self.parse_u32();
664         assert_eq!(self.next(), '|');
665         let mut bounds = vec![];
666         loop {
667             match self.next() {
668                 'R' => bounds.push(self.parse_region()),
669                 '.' => { break; }
670                 c => {
671                     bug!("parse_region_param_def: bad bounds ('{}')", c)
672                 }
673             }
674         }
675         ty::RegionParameterDef {
676             name: name,
677             def_id: def_id,
678             index: index,
679             bounds: bounds,
680         }
681     }
682
683
684     fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
685         match self.next() {
686             'a' => ty::ObjectLifetimeDefault::Ambiguous,
687             'b' => ty::ObjectLifetimeDefault::BaseDefault,
688             's' => {
689                 let region = self.parse_region();
690                 ty::ObjectLifetimeDefault::Specific(region)
691             }
692             _ => bug!("parse_object_lifetime_default: bad input")
693         }
694     }
695
696     fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
697         let mut builtin_bounds = ty::BuiltinBounds::empty();
698         loop {
699             match self.next() {
700                 'S' => {
701                     builtin_bounds.insert(ty::BoundSend);
702                 }
703                 'Z' => {
704                     builtin_bounds.insert(ty::BoundSized);
705                 }
706                 'P' => {
707                     builtin_bounds.insert(ty::BoundCopy);
708                 }
709                 'T' => {
710                     builtin_bounds.insert(ty::BoundSync);
711                 }
712                 '.' => {
713                     return builtin_bounds;
714                 }
715                 c => {
716                     bug!("parse_bounds: bad builtin bounds ('{}')", c)
717                 }
718             }
719         }
720     }
721 }
722
723 // Rust metadata parsing
724 fn parse_defid(buf: &[u8]) -> DefId {
725     let mut colon_idx = 0;
726     let len = buf.len();
727     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }
728     if colon_idx == len {
729         error!("didn't find ':' when parsing def id");
730         bug!();
731     }
732
733     let crate_part = &buf[0..colon_idx];
734     let def_part = &buf[colon_idx + 1..len];
735
736     let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| {
737         s.parse::<usize>().ok()
738     }) {
739         Some(cn) => cn as ast::CrateNum,
740         None => bug!("internal error: parse_defid: crate number expected, found {:?}",
741                        crate_part)
742     };
743     let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
744         s.parse::<usize>().ok()
745     }) {
746         Some(dn) => dn,
747         None => bug!("internal error: parse_defid: id expected, found {:?}",
748                        def_part)
749     };
750     let index = DefIndex::new(def_num);
751     DefId { krate: crate_num, index: index }
752 }
753
754 fn parse_unsafety(c: char) -> hir::Unsafety {
755     match c {
756         'u' => hir::Unsafety::Unsafe,
757         'n' => hir::Unsafety::Normal,
758         _ => bug!("parse_unsafety: bad unsafety {}", c)
759     }
760 }