]> git.proxmox.com Git - rustc.git/blob - src/librustc_metadata/tydecode.rs
New upstream version 1.12.0+dfsg1
[rustc.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;
24 use rustc::ty::subst::VecPerParamSpace;
25 use rustc::ty::{self, ToPredicate, Ty, TyCtxt, 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: TyCtxt<'a, 'tcx, 'tcx>,
45 conv_def_id: DefIdConvert<'a>,
46 }
47
48 impl<'a,'tcx> TyDecoder<'a,'tcx> {
49 pub fn with_doc(tcx: TyCtxt<'a, 'tcx, '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: TyCtxt<'a, 'tcx, '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_vec_per_param_space(|this| this.parse_region());
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_bound_region(&mut self) -> ty::BoundRegion {
153 match self.next() {
154 'a' => {
155 let id = self.parse_u32();
156 assert_eq!(self.next(), '|');
157 ty::BrAnon(id)
158 }
159 '[' => {
160 let def = self.parse_def();
161 let name = token::intern(&self.parse_str('|'));
162 let issue32330 = match self.next() {
163 'n' => {
164 assert_eq!(self.next(), ']');
165 ty::Issue32330::WontChange
166 }
167 'y' => {
168 ty::Issue32330::WillChange {
169 fn_def_id: self.parse_def(),
170 region_name: token::intern(&self.parse_str(']')),
171 }
172 }
173 c => panic!("expected n or y not {}", c)
174 };
175 ty::BrNamed(def, name, issue32330)
176 }
177 'f' => {
178 let id = self.parse_u32();
179 assert_eq!(self.next(), '|');
180 ty::BrFresh(id)
181 }
182 'e' => ty::BrEnv,
183 _ => bug!("parse_bound_region: bad input")
184 }
185 }
186
187 pub fn parse_region(&mut self) -> ty::Region {
188 match self.next() {
189 'b' => {
190 assert_eq!(self.next(), '[');
191 let id = ty::DebruijnIndex::new(self.parse_u32());
192 assert_eq!(self.next(), '|');
193 let br = self.parse_bound_region();
194 assert_eq!(self.next(), ']');
195 ty::ReLateBound(id, br)
196 }
197 'B' => {
198 assert_eq!(self.next(), '[');
199 let space = self.parse_param_space();
200 assert_eq!(self.next(), '|');
201 let index = self.parse_u32();
202 assert_eq!(self.next(), '|');
203 let name = token::intern(&self.parse_str(']'));
204 ty::ReEarlyBound(ty::EarlyBoundRegion {
205 space: space,
206 index: index,
207 name: name
208 })
209 }
210 'f' => {
211 assert_eq!(self.next(), '[');
212 let scope = self.parse_scope();
213 assert_eq!(self.next(), '|');
214 let br = self.parse_bound_region();
215 assert_eq!(self.next(), ']');
216 ty::ReFree(ty::FreeRegion { scope: scope,
217 bound_region: br})
218 }
219 's' => {
220 let scope = self.parse_scope();
221 assert_eq!(self.next(), '|');
222 ty::ReScope(scope)
223 }
224 't' => ty::ReStatic,
225 'e' => ty::ReEmpty,
226 'E' => ty::ReErased,
227 _ => bug!("parse_region: bad input")
228 }
229 }
230
231 fn parse_scope(&mut self) -> region::CodeExtent {
232 self.tcx.region_maps.bogus_code_extent(match self.next() {
233 // This creates scopes with the wrong NodeId. This isn't
234 // actually a problem because scopes only exist *within*
235 // functions, and functions aren't loaded until trans which
236 // doesn't care about regions.
237 //
238 // May still be worth fixing though.
239 'C' => {
240 assert_eq!(self.next(), '[');
241 let fn_id = self.parse_uint() as ast::NodeId;
242 assert_eq!(self.next(), '|');
243 let body_id = self.parse_uint() as ast::NodeId;
244 assert_eq!(self.next(), ']');
245 region::CodeExtentData::CallSiteScope {
246 fn_id: fn_id, body_id: body_id
247 }
248 }
249 // This creates scopes with the wrong NodeId. (See note above.)
250 'P' => {
251 assert_eq!(self.next(), '[');
252 let fn_id = self.parse_uint() as ast::NodeId;
253 assert_eq!(self.next(), '|');
254 let body_id = self.parse_uint() as ast::NodeId;
255 assert_eq!(self.next(), ']');
256 region::CodeExtentData::ParameterScope {
257 fn_id: fn_id, body_id: body_id
258 }
259 }
260 'M' => {
261 let node_id = self.parse_uint() as ast::NodeId;
262 region::CodeExtentData::Misc(node_id)
263 }
264 'D' => {
265 let node_id = self.parse_uint() as ast::NodeId;
266 region::CodeExtentData::DestructionScope(node_id)
267 }
268 'B' => {
269 assert_eq!(self.next(), '[');
270 let node_id = self.parse_uint() as ast::NodeId;
271 assert_eq!(self.next(), '|');
272 let first_stmt_index = self.parse_u32();
273 assert_eq!(self.next(), ']');
274 let block_remainder = region::BlockRemainder {
275 block: node_id, first_statement_index: first_stmt_index,
276 };
277 region::CodeExtentData::Remainder(block_remainder)
278 }
279 _ => bug!("parse_scope: bad input")
280 })
281 }
282
283 fn parse_opt<T, F>(&mut self, f: F) -> Option<T>
284 where F: FnOnce(&mut TyDecoder<'a, 'tcx>) -> T,
285 {
286 match self.next() {
287 'n' => None,
288 's' => Some(f(self)),
289 _ => bug!("parse_opt: bad input")
290 }
291 }
292
293 fn parse_str(&mut self, term: char) -> String {
294 let mut result = String::new();
295 while self.peek() != term {
296 unsafe {
297 result.as_mut_vec().extend_from_slice(&[self.next_byte()])
298 }
299 }
300 self.next();
301 result
302 }
303
304 pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
305 let def = self.parse_def();
306 let substs = self.tcx.mk_substs(self.parse_substs());
307 ty::TraitRef {def_id: def, substs: substs}
308 }
309
310 pub fn parse_ty(&mut self) -> Ty<'tcx> {
311 let tcx = self.tcx;
312 match self.next() {
313 'b' => return tcx.types.bool,
314 '!' => return tcx.types.never,
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 _ => bug!("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 let substs = self.tcx.mk_substs(self.parse_substs());
384 return tcx.mk_fn_def(def_id, substs, self.parse_bare_fn_ty());
385 }
386 'G' => {
387 return tcx.mk_fn_ptr(self.parse_bare_fn_ty());
388 }
389 '#' => {
390 // This is a hacky little caching scheme. The idea is that if we encode
391 // the same type twice, the second (and third, and fourth...) time we will
392 // just write `#123`, where `123` is the offset in the metadata of the
393 // first appearance. Now when we are *decoding*, if we see a `#123`, we
394 // can first check a cache (`tcx.rcache`) for that offset. If we find something,
395 // we return it (modulo closure types, see below). But if not, then we
396 // jump to offset 123 and read the type from there.
397
398 let pos = self.parse_vuint();
399 let key = ty::CReaderCacheKey { cnum: self.krate, pos: pos };
400 if let Some(tt) = tcx.rcache.borrow().get(&key).cloned() {
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
409 let mut substate = TyDecoder::new(self.data,
410 self.krate,
411 pos,
412 self.tcx,
413 self.conv_def_id);
414 let tt = substate.parse_ty();
415 tcx.rcache.borrow_mut().insert(key, tt);
416 return tt;
417 }
418 '\"' => {
419 let _ = self.parse_def();
420 let inner = self.parse_ty();
421 inner
422 }
423 'a' => {
424 assert_eq!(self.next(), '[');
425 let did = self.parse_def();
426 let substs = self.parse_substs();
427 assert_eq!(self.next(), ']');
428 let def = self.tcx.lookup_adt_def(did);
429 return self.tcx.mk_struct(def, self.tcx.mk_substs(substs));
430 }
431 'k' => {
432 assert_eq!(self.next(), '[');
433 let did = self.parse_def();
434 let substs = self.parse_substs();
435 let mut tys = vec![];
436 while self.peek() != '.' {
437 tys.push(self.parse_ty());
438 }
439 assert_eq!(self.next(), '.');
440 assert_eq!(self.next(), ']');
441 return self.tcx.mk_closure(did, self.tcx.mk_substs(substs), tys);
442 }
443 'P' => {
444 assert_eq!(self.next(), '[');
445 let trait_ref = self.parse_trait_ref();
446 let name = token::intern(&self.parse_str(']'));
447 return tcx.mk_projection(trait_ref, name);
448 }
449 'A' => {
450 assert_eq!(self.next(), '[');
451 let def_id = self.parse_def();
452 let substs = self.parse_substs();
453 assert_eq!(self.next(), ']');
454 return self.tcx.mk_anon(def_id, self.tcx.mk_substs(substs));
455 }
456 'e' => {
457 return tcx.types.err;
458 }
459 c => { bug!("unexpected char in type string: {}", c);}
460 }
461 }
462
463 fn parse_mutability(&mut self) -> hir::Mutability {
464 match self.peek() {
465 'm' => { self.next(); hir::MutMutable }
466 _ => { hir::MutImmutable }
467 }
468 }
469
470 fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> {
471 let m = self.parse_mutability();
472 ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
473 }
474
475 fn parse_def(&mut self) -> DefId {
476 let def_id = parse_defid(self.scan(|c| c == '|'));
477 return (self.conv_def_id)(def_id);
478 }
479
480 fn parse_uint(&mut self) -> usize {
481 let mut n = 0;
482 loop {
483 let cur = self.peek();
484 if cur < '0' || cur > '9' { return n; }
485 self.pos = self.pos + 1;
486 n *= 10;
487 n += (cur as usize) - ('0' as usize);
488 };
489 }
490
491 fn parse_u32(&mut self) -> u32 {
492 let n = self.parse_uint();
493 let m = n as u32;
494 assert_eq!(m as usize, n);
495 m
496 }
497
498 fn parse_param_space(&mut self) -> subst::ParamSpace {
499 subst::ParamSpace::from_uint(self.parse_uint())
500 }
501
502 fn parse_abi_set(&mut self) -> abi::Abi {
503 assert_eq!(self.next(), '[');
504 let bytes = self.scan(|c| c == ']');
505 let abi_str = str::from_utf8(bytes).unwrap();
506 abi::lookup(&abi_str[..]).expect(abi_str)
507 }
508
509 pub fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
510 let unsafety = parse_unsafety(self.next());
511 let sig = self.parse_sig();
512 let abi = self.parse_abi_set();
513 ty::ClosureTy {
514 unsafety: unsafety,
515 sig: sig,
516 abi: abi,
517 }
518 }
519
520 pub fn parse_bare_fn_ty(&mut self) -> &'tcx ty::BareFnTy<'tcx> {
521 let unsafety = parse_unsafety(self.next());
522 let abi = self.parse_abi_set();
523 let sig = self.parse_sig();
524 self.tcx.mk_bare_fn(ty::BareFnTy {
525 unsafety: unsafety,
526 abi: abi,
527 sig: sig
528 })
529 }
530
531 fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> {
532 assert_eq!(self.next(), '[');
533 let mut inputs = Vec::new();
534 while self.peek() != ']' {
535 inputs.push(self.parse_ty());
536 }
537 self.pos += 1; // eat the ']'
538 let variadic = match self.next() {
539 'V' => true,
540 'N' => false,
541 r => bug!("bad variadic: {}", r),
542 };
543 let output = self.parse_ty();
544 ty::Binder(ty::FnSig {inputs: inputs,
545 output: output,
546 variadic: variadic})
547 }
548
549 pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
550 match self.next() {
551 't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
552 'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
553 self.parse_ty())).to_predicate(),
554 'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(),
555 self.parse_region())).to_predicate(),
556 'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(),
557 self.parse_region())).to_predicate(),
558 'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
559 'w' => ty::Predicate::WellFormed(self.parse_ty()),
560 'O' => {
561 let def_id = self.parse_def();
562 assert_eq!(self.next(), '|');
563 ty::Predicate::ObjectSafe(def_id)
564 }
565 'c' => {
566 let def_id = self.parse_def();
567 assert_eq!(self.next(), '|');
568 let kind = match self.next() {
569 'f' => ty::ClosureKind::Fn,
570 'm' => ty::ClosureKind::FnMut,
571 'o' => ty::ClosureKind::FnOnce,
572 c => bug!("Encountered invalid character in metadata: {}", c)
573 };
574 assert_eq!(self.next(), '|');
575 ty::Predicate::ClosureKind(def_id, kind)
576 }
577 c => bug!("Encountered invalid character in metadata: {}", c)
578 }
579 }
580
581 fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
582 ty::ProjectionPredicate {
583 projection_ty: ty::ProjectionTy {
584 trait_ref: self.parse_trait_ref(),
585 item_name: token::intern(&self.parse_str('|')),
586 },
587 ty: self.parse_ty(),
588 }
589 }
590
591 pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
592 let name = self.parse_name(':');
593 let def_id = self.parse_def();
594 let space = self.parse_param_space();
595 assert_eq!(self.next(), '|');
596 let index = self.parse_u32();
597 assert_eq!(self.next(), '|');
598 let default_def_id = self.parse_def();
599 let default = self.parse_opt(|this| this.parse_ty());
600 let object_lifetime_default = self.parse_object_lifetime_default();
601
602 ty::TypeParameterDef {
603 name: name,
604 def_id: def_id,
605 space: space,
606 index: index,
607 default_def_id: default_def_id,
608 default: default,
609 object_lifetime_default: object_lifetime_default,
610 }
611 }
612
613 pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
614 let name = self.parse_name(':');
615 let def_id = self.parse_def();
616 let space = self.parse_param_space();
617 assert_eq!(self.next(), '|');
618 let index = self.parse_u32();
619 assert_eq!(self.next(), '|');
620 let mut bounds = vec![];
621 loop {
622 match self.next() {
623 'R' => bounds.push(self.parse_region()),
624 '.' => { break; }
625 c => {
626 bug!("parse_region_param_def: bad bounds ('{}')", c)
627 }
628 }
629 }
630 ty::RegionParameterDef {
631 name: name,
632 def_id: def_id,
633 space: space,
634 index: index,
635 bounds: bounds,
636 }
637 }
638
639
640 fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
641 match self.next() {
642 'a' => ty::ObjectLifetimeDefault::Ambiguous,
643 'b' => ty::ObjectLifetimeDefault::BaseDefault,
644 's' => {
645 let region = self.parse_region();
646 ty::ObjectLifetimeDefault::Specific(region)
647 }
648 _ => bug!("parse_object_lifetime_default: bad input")
649 }
650 }
651
652 pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
653 let builtin_bounds = self.parse_builtin_bounds();
654 let region_bound = self.parse_region();
655 let mut projection_bounds = Vec::new();
656
657 loop {
658 match self.next() {
659 'P' => {
660 projection_bounds.push(ty::Binder(self.parse_projection_predicate()));
661 }
662 '.' => { break; }
663 c => {
664 bug!("parse_bounds: bad bounds ('{}')", c)
665 }
666 }
667 }
668
669 ty::ExistentialBounds::new(
670 region_bound, builtin_bounds, projection_bounds)
671 }
672
673 fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
674 let mut builtin_bounds = ty::BuiltinBounds::empty();
675 loop {
676 match self.next() {
677 'S' => {
678 builtin_bounds.insert(ty::BoundSend);
679 }
680 'Z' => {
681 builtin_bounds.insert(ty::BoundSized);
682 }
683 'P' => {
684 builtin_bounds.insert(ty::BoundCopy);
685 }
686 'T' => {
687 builtin_bounds.insert(ty::BoundSync);
688 }
689 '.' => {
690 return builtin_bounds;
691 }
692 c => {
693 bug!("parse_bounds: bad builtin bounds ('{}')", c)
694 }
695 }
696 }
697 }
698 }
699
700 // Rust metadata parsing
701 fn parse_defid(buf: &[u8]) -> DefId {
702 let mut colon_idx = 0;
703 let len = buf.len();
704 while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }
705 if colon_idx == len {
706 error!("didn't find ':' when parsing def id");
707 bug!();
708 }
709
710 let crate_part = &buf[0..colon_idx];
711 let def_part = &buf[colon_idx + 1..len];
712
713 let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| {
714 s.parse::<usize>().ok()
715 }) {
716 Some(cn) => cn as ast::CrateNum,
717 None => bug!("internal error: parse_defid: crate number expected, found {:?}",
718 crate_part)
719 };
720 let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
721 s.parse::<usize>().ok()
722 }) {
723 Some(dn) => dn,
724 None => bug!("internal error: parse_defid: id expected, found {:?}",
725 def_part)
726 };
727 let index = DefIndex::new(def_num);
728 DefId { krate: crate_num, index: index }
729 }
730
731 fn parse_unsafety(c: char) -> hir::Unsafety {
732 match c {
733 'u' => hir::Unsafety::Unsafe,
734 'n' => hir::Unsafety::Normal,
735 _ => bug!("parse_unsafety: bad unsafety {}", c)
736 }
737 }