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