]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/tydecode.rs
Rollup merge of #35980 - kyrias:E0094-underline, r=jonathandturner
[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::{Kind, 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 params = vec![];
133         assert_eq!(self.next(), '[');
134         while self.peek() != ']' {
135             let k = match self.next() {
136                 'r' => Kind::from(self.parse_region()),
137                 't' => Kind::from(self.parse_ty()),
138                 _ => bug!()
139             };
140             params.push(k);
141         }
142         assert_eq!(self.next(), ']');
143
144         Substs::new(self.tcx, params)
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) -> &'tcx ty::Region {
211         self.tcx.mk_region(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                 return tcx.mk_ref(self.parse_region(), self.parse_mt());
407             }
408             'V' => {
409                 let t = self.parse_ty();
410                 return match self.parse_size() {
411                     Some(n) => tcx.mk_array(t, n),
412                     None => tcx.mk_slice(t)
413                 };
414             }
415             'v' => {
416                 return tcx.mk_str();
417             }
418             'T' => {
419                 assert_eq!(self.next(), '[');
420                 let mut params = Vec::new();
421                 while self.peek() != ']' { params.push(self.parse_ty()); }
422                 self.pos = self.pos + 1;
423                 return tcx.mk_tup(params);
424             }
425             'F' => {
426                 let def_id = self.parse_def();
427                 let substs = self.parse_substs();
428                 return tcx.mk_fn_def(def_id, substs, self.parse_bare_fn_ty());
429             }
430             'G' => {
431                 return tcx.mk_fn_ptr(self.parse_bare_fn_ty());
432             }
433             '#' => {
434                 // This is a hacky little caching scheme. The idea is that if we encode
435                 // the same type twice, the second (and third, and fourth...) time we will
436                 // just write `#123`, where `123` is the offset in the metadata of the
437                 // first appearance. Now when we are *decoding*, if we see a `#123`, we
438                 // can first check a cache (`tcx.rcache`) for that offset. If we find something,
439                 // we return it (modulo closure types, see below). But if not, then we
440                 // jump to offset 123 and read the type from there.
441
442                 let pos = self.parse_vuint();
443                 let key = ty::CReaderCacheKey { cnum: self.krate, pos: pos };
444                 if let Some(tt) = tcx.rcache.borrow().get(&key).cloned() {
445                     // If there is a closure buried in the type some where, then we
446                     // need to re-convert any def ids (see case 'k', below). That means
447                     // we can't reuse the cached version.
448                     if !tt.has_closure_types() {
449                         return tt;
450                     }
451                 }
452
453                 let mut substate = TyDecoder::new(self.data,
454                                                   self.krate,
455                                                   pos,
456                                                   self.tcx,
457                                                   self.conv_def_id);
458                 let tt = substate.parse_ty();
459                 tcx.rcache.borrow_mut().insert(key, tt);
460                 return tt;
461             }
462             '\"' => {
463                 let _ = self.parse_def();
464                 let inner = self.parse_ty();
465                 inner
466             }
467             'a' => {
468                 assert_eq!(self.next(), '[');
469                 let did = self.parse_def();
470                 let substs = self.parse_substs();
471                 assert_eq!(self.next(), ']');
472                 let def = self.tcx.lookup_adt_def(did);
473                 return self.tcx.mk_struct(def, substs);
474             }
475             'k' => {
476                 assert_eq!(self.next(), '[');
477                 let did = self.parse_def();
478                 let substs = self.parse_substs();
479                 let mut tys = vec![];
480                 while self.peek() != '.' {
481                     tys.push(self.parse_ty());
482                 }
483                 assert_eq!(self.next(), '.');
484                 assert_eq!(self.next(), ']');
485                 return self.tcx.mk_closure(did, substs, tys);
486             }
487             'P' => {
488                 assert_eq!(self.next(), '[');
489                 let trait_ref = self.parse_trait_ref();
490                 let name = token::intern(&self.parse_str(']'));
491                 return tcx.mk_projection(trait_ref, name);
492             }
493             'A' => {
494                 assert_eq!(self.next(), '[');
495                 let def_id = self.parse_def();
496                 let substs = self.parse_substs();
497                 assert_eq!(self.next(), ']');
498                 return self.tcx.mk_anon(def_id, substs);
499             }
500             'e' => {
501                 return tcx.types.err;
502             }
503             c => { bug!("unexpected char in type string: {}", c);}
504         }
505     }
506
507     fn parse_mutability(&mut self) -> hir::Mutability {
508         match self.peek() {
509             'm' => { self.next(); hir::MutMutable }
510             _ => { hir::MutImmutable }
511         }
512     }
513
514     fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> {
515         let m = self.parse_mutability();
516         ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
517     }
518
519     fn parse_def(&mut self) -> DefId {
520         let def_id = parse_defid(self.scan(|c| c == '|'));
521         return (self.conv_def_id)(def_id);
522     }
523
524     fn parse_uint(&mut self) -> usize {
525         let mut n = 0;
526         loop {
527             let cur = self.peek();
528             if cur < '0' || cur > '9' { return n; }
529             self.pos = self.pos + 1;
530             n *= 10;
531             n += (cur as usize) - ('0' as usize);
532         };
533     }
534
535     fn parse_u32(&mut self) -> u32 {
536         let n = self.parse_uint();
537         let m = n as u32;
538         assert_eq!(m as usize, n);
539         m
540     }
541
542     fn parse_abi_set(&mut self) -> abi::Abi {
543         assert_eq!(self.next(), '[');
544         let bytes = self.scan(|c| c == ']');
545         let abi_str = str::from_utf8(bytes).unwrap();
546         abi::lookup(&abi_str[..]).expect(abi_str)
547     }
548
549     pub fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
550         let unsafety = parse_unsafety(self.next());
551         let sig = self.parse_sig();
552         let abi = self.parse_abi_set();
553         ty::ClosureTy {
554             unsafety: unsafety,
555             sig: sig,
556             abi: abi,
557         }
558     }
559
560     pub fn parse_bare_fn_ty(&mut self) -> &'tcx ty::BareFnTy<'tcx> {
561         let unsafety = parse_unsafety(self.next());
562         let abi = self.parse_abi_set();
563         let sig = self.parse_sig();
564         self.tcx.mk_bare_fn(ty::BareFnTy {
565             unsafety: unsafety,
566             abi: abi,
567             sig: sig
568         })
569     }
570
571     fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> {
572         assert_eq!(self.next(), '[');
573         let mut inputs = Vec::new();
574         while self.peek() != ']' {
575             inputs.push(self.parse_ty());
576         }
577         self.pos += 1; // eat the ']'
578         let variadic = match self.next() {
579             'V' => true,
580             'N' => false,
581             r => bug!("bad variadic: {}", r),
582         };
583         let output = self.parse_ty();
584         ty::Binder(ty::FnSig {inputs: inputs,
585                               output: output,
586                               variadic: variadic})
587     }
588
589     pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
590         match self.next() {
591             't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
592             'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
593                                                   self.parse_ty())).to_predicate(),
594             'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(),
595                                                     self.parse_region())).to_predicate(),
596             'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(),
597                                                     self.parse_region())).to_predicate(),
598             'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
599             'w' => ty::Predicate::WellFormed(self.parse_ty()),
600             'O' => {
601                 let def_id = self.parse_def();
602                 assert_eq!(self.next(), '|');
603                 ty::Predicate::ObjectSafe(def_id)
604             }
605             'c' => {
606                 let def_id = self.parse_def();
607                 assert_eq!(self.next(), '|');
608                 let kind = match self.next() {
609                     'f' => ty::ClosureKind::Fn,
610                     'm' => ty::ClosureKind::FnMut,
611                     'o' => ty::ClosureKind::FnOnce,
612                     c => bug!("Encountered invalid character in metadata: {}", c)
613                 };
614                 assert_eq!(self.next(), '|');
615                 ty::Predicate::ClosureKind(def_id, kind)
616             }
617             c => bug!("Encountered invalid character in metadata: {}", c)
618         }
619     }
620
621     fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
622         ty::ProjectionPredicate {
623             projection_ty: ty::ProjectionTy {
624                 trait_ref: self.parse_trait_ref(),
625                 item_name: token::intern(&self.parse_str('|')),
626             },
627             ty: self.parse_ty(),
628         }
629     }
630
631     fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> {
632         ty::ExistentialProjection {
633             trait_ref: self.parse_existential_trait_ref(),
634             item_name: token::intern(&self.parse_str('|')),
635             ty: self.parse_ty(),
636         }
637     }
638
639     fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
640         let name = self.parse_name(':');
641         let def_id = self.parse_def();
642         let index = self.parse_u32();
643         assert_eq!(self.next(), '|');
644         let default_def_id = self.parse_def();
645         let default = self.parse_opt(|this| this.parse_ty());
646         let object_lifetime_default = self.parse_object_lifetime_default();
647
648         ty::TypeParameterDef {
649             name: name,
650             def_id: def_id,
651             index: index,
652             default_def_id: default_def_id,
653             default: default,
654             object_lifetime_default: object_lifetime_default,
655         }
656     }
657
658     fn parse_region_param_def(&mut self) -> ty::RegionParameterDef<'tcx> {
659         let name = self.parse_name(':');
660         let def_id = self.parse_def();
661         let index = self.parse_u32();
662         assert_eq!(self.next(), '|');
663         let mut bounds = vec![];
664         loop {
665             match self.next() {
666                 'R' => bounds.push(self.parse_region()),
667                 '.' => { break; }
668                 c => {
669                     bug!("parse_region_param_def: bad bounds ('{}')", c)
670                 }
671             }
672         }
673         ty::RegionParameterDef {
674             name: name,
675             def_id: def_id,
676             index: index,
677             bounds: bounds,
678         }
679     }
680
681
682     fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault<'tcx> {
683         match self.next() {
684             'a' => ty::ObjectLifetimeDefault::Ambiguous,
685             'b' => ty::ObjectLifetimeDefault::BaseDefault,
686             's' => {
687                 let region = self.parse_region();
688                 ty::ObjectLifetimeDefault::Specific(region)
689             }
690             _ => bug!("parse_object_lifetime_default: bad input")
691         }
692     }
693
694     fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
695         let mut builtin_bounds = ty::BuiltinBounds::empty();
696         loop {
697             match self.next() {
698                 'S' => {
699                     builtin_bounds.insert(ty::BoundSend);
700                 }
701                 'Z' => {
702                     builtin_bounds.insert(ty::BoundSized);
703                 }
704                 'P' => {
705                     builtin_bounds.insert(ty::BoundCopy);
706                 }
707                 'T' => {
708                     builtin_bounds.insert(ty::BoundSync);
709                 }
710                 '.' => {
711                     return builtin_bounds;
712                 }
713                 c => {
714                     bug!("parse_bounds: bad builtin bounds ('{}')", c)
715                 }
716             }
717         }
718     }
719 }
720
721 // Rust metadata parsing
722 fn parse_defid(buf: &[u8]) -> DefId {
723     let mut colon_idx = 0;
724     let len = buf.len();
725     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }
726     if colon_idx == len {
727         error!("didn't find ':' when parsing def id");
728         bug!();
729     }
730
731     let crate_part = &buf[0..colon_idx];
732     let def_part = &buf[colon_idx + 1..len];
733
734     let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| {
735         s.parse::<usize>().ok()
736     }) {
737         Some(cn) => cn as ast::CrateNum,
738         None => bug!("internal error: parse_defid: crate number expected, found {:?}",
739                        crate_part)
740     };
741     let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
742         s.parse::<usize>().ok()
743     }) {
744         Some(dn) => dn,
745         None => bug!("internal error: parse_defid: id expected, found {:?}",
746                        def_part)
747     };
748     let index = DefIndex::new(def_num);
749     DefId { krate: crate_num, index: index }
750 }
751
752 fn parse_unsafety(c: char) -> hir::Unsafety {
753     match c {
754         'u' => hir::Unsafety::Unsafe,
755         'n' => hir::Unsafety::Normal,
756         _ => bug!("parse_unsafety: bad unsafety {}", c)
757     }
758 }