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