]> git.proxmox.com Git - rustc.git/blob - src/librustc/metadata/tydecode.rs
Move away from hash to the same rust naming schema
[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 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 ident = token::str_to_ident(&self.parse_str(']'));
188 ty::BrNamed(def, ident.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 // this is the wrong NodeId, but `param_id` is only accessed
213 // by the receiver-matching code in collect, which won't
214 // be going down this code path, and anyway I will kill it
215 // the moment wfcheck becomes the standard.
216 let node_id = self.parse_uint() as ast::NodeId;
217 assert_eq!(self.next(), '|');
218 let space = self.parse_param_space();
219 assert_eq!(self.next(), '|');
220 let index = self.parse_u32();
221 assert_eq!(self.next(), '|');
222 let nm = token::str_to_ident(&self.parse_str(']'));
223 ty::ReEarlyBound(ty::EarlyBoundRegion {
224 param_id: node_id,
225 space: space,
226 index: index,
227 name: nm.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' => {
245 ty::ReStatic
246 }
247 'e' => {
248 ty::ReStatic
249 }
250 _ => panic!("parse_region: bad input")
251 }
252 }
253
254 fn parse_scope(&mut self) -> region::CodeExtent {
255 self.tcx.region_maps.bogus_code_extent(match self.next() {
256 // This creates scopes with the wrong NodeId. This isn't
257 // actually a problem because scopes only exist *within*
258 // functions, and functions aren't loaded until trans which
259 // doesn't care about regions.
260 //
261 // May still be worth fixing though.
262 'P' => {
263 assert_eq!(self.next(), '[');
264 let fn_id = self.parse_uint() as ast::NodeId;
265 assert_eq!(self.next(), '|');
266 let body_id = self.parse_uint() as ast::NodeId;
267 assert_eq!(self.next(), ']');
268 region::CodeExtentData::ParameterScope {
269 fn_id: fn_id, body_id: body_id
270 }
271 }
272 'M' => {
273 let node_id = self.parse_uint() as ast::NodeId;
274 region::CodeExtentData::Misc(node_id)
275 }
276 'D' => {
277 let node_id = self.parse_uint() as ast::NodeId;
278 region::CodeExtentData::DestructionScope(node_id)
279 }
280 'B' => {
281 assert_eq!(self.next(), '[');
282 let node_id = self.parse_uint() as ast::NodeId;
283 assert_eq!(self.next(), '|');
284 let first_stmt_index = self.parse_u32();
285 assert_eq!(self.next(), ']');
286 let block_remainder = region::BlockRemainder {
287 block: node_id, first_statement_index: first_stmt_index,
288 };
289 region::CodeExtentData::Remainder(block_remainder)
290 }
291 _ => panic!("parse_scope: bad input")
292 })
293 }
294
295 fn parse_opt<T, F>(&mut self, f: F) -> Option<T>
296 where F: FnOnce(&mut TyDecoder<'a, 'tcx>) -> T,
297 {
298 match self.next() {
299 'n' => None,
300 's' => Some(f(self)),
301 _ => panic!("parse_opt: bad input")
302 }
303 }
304
305 fn parse_str(&mut self, term: char) -> String {
306 let mut result = String::new();
307 while self.peek() != term {
308 unsafe {
309 result.as_mut_vec().push_all(&[self.next_byte()])
310 }
311 }
312 self.next();
313 result
314 }
315
316 pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
317 let def = self.parse_def(NominalType);
318 let substs = self.tcx.mk_substs(self.parse_substs());
319 ty::TraitRef {def_id: def, substs: substs}
320 }
321
322 pub fn parse_ty(&mut self) -> Ty<'tcx> {
323 let tcx = self.tcx;
324 match self.next() {
325 'b' => return tcx.types.bool,
326 'i' => { /* eat the s of is */ self.next(); return tcx.types.isize },
327 'u' => { /* eat the s of us */ self.next(); return tcx.types.usize },
328 'M' => {
329 match self.next() {
330 'b' => return tcx.types.u8,
331 'w' => return tcx.types.u16,
332 'l' => return tcx.types.u32,
333 'd' => return tcx.types.u64,
334 'B' => return tcx.types.i8,
335 'W' => return tcx.types.i16,
336 'L' => return tcx.types.i32,
337 'D' => return tcx.types.i64,
338 'f' => return tcx.types.f32,
339 'F' => return tcx.types.f64,
340 _ => panic!("parse_ty: bad numeric type")
341 }
342 }
343 'c' => return tcx.types.char,
344 't' => {
345 assert_eq!(self.next(), '[');
346 let did = self.parse_def(NominalType);
347 let substs = self.parse_substs();
348 assert_eq!(self.next(), ']');
349 let def = self.tcx.lookup_adt_def(did);
350 return tcx.mk_enum(def, self.tcx.mk_substs(substs));
351 }
352 'x' => {
353 assert_eq!(self.next(), '[');
354 let trait_ref = ty::Binder(self.parse_trait_ref());
355 let bounds = self.parse_existential_bounds();
356 assert_eq!(self.next(), ']');
357 return tcx.mk_trait(trait_ref, bounds);
358 }
359 'p' => {
360 assert_eq!(self.next(), '[');
361 let index = self.parse_u32();
362 assert_eq!(self.next(), '|');
363 let space = self.parse_param_space();
364 assert_eq!(self.next(), '|');
365 let name = token::intern(&self.parse_str(']'));
366 return tcx.mk_param(space, index, name);
367 }
368 '~' => return tcx.mk_box(self.parse_ty()),
369 '*' => return tcx.mk_ptr(self.parse_mt()),
370 '&' => {
371 let r = self.parse_region();
372 let mt = self.parse_mt();
373 return tcx.mk_ref(tcx.mk_region(r), mt);
374 }
375 'V' => {
376 let t = self.parse_ty();
377 return match self.parse_size() {
378 Some(n) => tcx.mk_array(t, n),
379 None => tcx.mk_slice(t)
380 };
381 }
382 'v' => {
383 return tcx.mk_str();
384 }
385 'T' => {
386 assert_eq!(self.next(), '[');
387 let mut params = Vec::new();
388 while self.peek() != ']' { params.push(self.parse_ty()); }
389 self.pos = self.pos + 1;
390 return tcx.mk_tup(params);
391 }
392 'F' => {
393 let def_id = self.parse_def(NominalType);
394 return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(self.parse_bare_fn_ty()));
395 }
396 'G' => {
397 return tcx.mk_fn(None, tcx.mk_bare_fn(self.parse_bare_fn_ty()));
398 }
399 '#' => {
400 // This is a hacky little caching scheme. The idea is that if we encode
401 // the same type twice, the second (and third, and fourth...) time we will
402 // just write `#123`, where `123` is the offset in the metadata of the
403 // first appearance. Now when we are *decoding*, if we see a `#123`, we
404 // can first check a cache (`tcx.rcache`) for that offset. If we find something,
405 // we return it (modulo closure types, see below). But if not, then we
406 // jump to offset 123 and read the type from there.
407
408 let pos = self.parse_hex();
409 assert_eq!(self.next(), ':');
410 let len = self.parse_hex();
411 assert_eq!(self.next(), '#');
412 let key = ty::CReaderCacheKey {cnum: self.krate, pos: pos, len: len };
413 match tcx.rcache.borrow().get(&key).cloned() {
414 Some(tt) => {
415 // If there is a closure buried in the type some where, then we
416 // need to re-convert any def ids (see case 'k', below). That means
417 // we can't reuse the cached version.
418 if !tt.has_closure_types() {
419 return tt;
420 }
421 }
422 None => {}
423 }
424
425 let mut substate = TyDecoder::new(self.data,
426 self.krate,
427 pos,
428 self.tcx,
429 self.conv_def_id);
430 let tt = substate.parse_ty();
431 tcx.rcache.borrow_mut().insert(key, tt);
432 return tt;
433 }
434 '\"' => {
435 let _ = self.parse_def(TypeWithId);
436 let inner = self.parse_ty();
437 inner
438 }
439 'a' => {
440 assert_eq!(self.next(), '[');
441 let did = self.parse_def(NominalType);
442 let substs = self.parse_substs();
443 assert_eq!(self.next(), ']');
444 let def = self.tcx.lookup_adt_def(did);
445 return self.tcx.mk_struct(def, self.tcx.mk_substs(substs));
446 }
447 'k' => {
448 assert_eq!(self.next(), '[');
449 let did = self.parse_def(ClosureSource);
450 let substs = self.parse_substs();
451 let mut tys = vec![];
452 while self.peek() != '.' {
453 tys.push(self.parse_ty());
454 }
455 assert_eq!(self.next(), '.');
456 assert_eq!(self.next(), ']');
457 return self.tcx.mk_closure(did, self.tcx.mk_substs(substs), tys);
458 }
459 'P' => {
460 assert_eq!(self.next(), '[');
461 let trait_ref = self.parse_trait_ref();
462 let name = token::intern(&self.parse_str(']'));
463 return tcx.mk_projection(trait_ref, name);
464 }
465 'e' => {
466 return tcx.types.err;
467 }
468 c => { panic!("unexpected char in type string: {}", c);}
469 }
470 }
471
472 fn parse_mutability(&mut self) -> hir::Mutability {
473 match self.peek() {
474 'm' => { self.next(); hir::MutMutable }
475 _ => { hir::MutImmutable }
476 }
477 }
478
479 fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> {
480 let m = self.parse_mutability();
481 ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
482 }
483
484 fn parse_def(&mut self, source: DefIdSource) -> DefId {
485 let def_id = parse_defid(self.scan(|c| c == '|'));
486 return (self.conv_def_id)(source, def_id);
487 }
488
489 fn parse_uint(&mut self) -> usize {
490 let mut n = 0;
491 loop {
492 let cur = self.peek();
493 if cur < '0' || cur > '9' { return n; }
494 self.pos = self.pos + 1;
495 n *= 10;
496 n += (cur as usize) - ('0' as usize);
497 };
498 }
499
500 fn parse_u32(&mut self) -> u32 {
501 let n = self.parse_uint();
502 let m = n as u32;
503 assert_eq!(m as usize, n);
504 m
505 }
506
507 fn parse_param_space(&mut self) -> subst::ParamSpace {
508 subst::ParamSpace::from_uint(self.parse_uint())
509 }
510
511 fn parse_hex(&mut self) -> usize {
512 let mut n = 0;
513 loop {
514 let cur = self.peek();
515 if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
516 self.pos = self.pos + 1;
517 n *= 16;
518 if '0' <= cur && cur <= '9' {
519 n += (cur as usize) - ('0' as usize);
520 } else { n += 10 + (cur as usize) - ('a' as usize); }
521 };
522 }
523
524 fn parse_abi_set(&mut self) -> abi::Abi {
525 assert_eq!(self.next(), '[');
526 let bytes = self.scan(|c| c == ']');
527 let abi_str = str::from_utf8(bytes).unwrap();
528 abi::lookup(&abi_str[..]).expect(abi_str)
529 }
530
531 pub fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
532 let unsafety = parse_unsafety(self.next());
533 let sig = self.parse_sig();
534 let abi = self.parse_abi_set();
535 ty::ClosureTy {
536 unsafety: unsafety,
537 sig: sig,
538 abi: abi,
539 }
540 }
541
542 pub fn parse_bare_fn_ty(&mut self) -> ty::BareFnTy<'tcx> {
543 let unsafety = parse_unsafety(self.next());
544 let abi = self.parse_abi_set();
545 let sig = self.parse_sig();
546 ty::BareFnTy {
547 unsafety: unsafety,
548 abi: abi,
549 sig: sig
550 }
551 }
552
553 fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> {
554 assert_eq!(self.next(), '[');
555 let mut inputs = Vec::new();
556 while self.peek() != ']' {
557 inputs.push(self.parse_ty());
558 }
559 self.pos += 1; // eat the ']'
560 let variadic = match self.next() {
561 'V' => true,
562 'N' => false,
563 r => panic!(format!("bad variadic: {}", r)),
564 };
565 let output = match self.peek() {
566 'z' => {
567 self.pos += 1;
568 ty::FnDiverging
569 }
570 _ => ty::FnConverging(self.parse_ty())
571 };
572 ty::Binder(ty::FnSig {inputs: inputs,
573 output: output,
574 variadic: variadic})
575 }
576
577 pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
578 match self.next() {
579 't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
580 'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
581 self.parse_ty())).to_predicate(),
582 'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(),
583 self.parse_region())).to_predicate(),
584 'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(),
585 self.parse_region())).to_predicate(),
586 'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
587 'w' => ty::Predicate::WellFormed(self.parse_ty()),
588 'O' => {
589 let def_id = self.parse_def(NominalType);
590 assert_eq!(self.next(), '|');
591 ty::Predicate::ObjectSafe(def_id)
592 }
593 c => panic!("Encountered invalid character in metadata: {}", c)
594 }
595 }
596
597 fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
598 ty::ProjectionPredicate {
599 projection_ty: ty::ProjectionTy {
600 trait_ref: self.parse_trait_ref(),
601 item_name: token::str_to_ident(&self.parse_str('|')).name,
602 },
603 ty: self.parse_ty(),
604 }
605 }
606
607 pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
608 let name = self.parse_name(':');
609 let def_id = self.parse_def(NominalType);
610 let space = self.parse_param_space();
611 assert_eq!(self.next(), '|');
612 let index = self.parse_u32();
613 assert_eq!(self.next(), '|');
614 let default_def_id = self.parse_def(NominalType);
615 let default = self.parse_opt(|this| this.parse_ty());
616 let object_lifetime_default = self.parse_object_lifetime_default();
617
618 ty::TypeParameterDef {
619 name: name,
620 def_id: def_id,
621 space: space,
622 index: index,
623 default_def_id: default_def_id,
624 default: default,
625 object_lifetime_default: object_lifetime_default,
626 }
627 }
628
629 pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
630 let name = self.parse_name(':');
631 let def_id = self.parse_def(NominalType);
632 let space = self.parse_param_space();
633 assert_eq!(self.next(), '|');
634 let index = self.parse_u32();
635 assert_eq!(self.next(), '|');
636 let mut bounds = vec![];
637 loop {
638 match self.next() {
639 'R' => bounds.push(self.parse_region()),
640 '.' => { break; }
641 c => {
642 panic!("parse_region_param_def: bad bounds ('{}')", c)
643 }
644 }
645 }
646 ty::RegionParameterDef {
647 name: name,
648 def_id: def_id,
649 space: space,
650 index: index,
651 bounds: bounds
652 }
653 }
654
655
656 fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
657 match self.next() {
658 'a' => ty::ObjectLifetimeDefault::Ambiguous,
659 'b' => ty::ObjectLifetimeDefault::BaseDefault,
660 's' => {
661 let region = self.parse_region();
662 ty::ObjectLifetimeDefault::Specific(region)
663 }
664 _ => panic!("parse_object_lifetime_default: bad input")
665 }
666 }
667
668 pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
669 let builtin_bounds = self.parse_builtin_bounds();
670 let region_bound = self.parse_region();
671 let mut projection_bounds = Vec::new();
672
673 loop {
674 match self.next() {
675 'P' => {
676 projection_bounds.push(ty::Binder(self.parse_projection_predicate()));
677 }
678 '.' => { break; }
679 c => {
680 panic!("parse_bounds: bad bounds ('{}')", c)
681 }
682 }
683 }
684
685 ty::ExistentialBounds::new(
686 region_bound, builtin_bounds, projection_bounds)
687 }
688
689 fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
690 let mut builtin_bounds = ty::BuiltinBounds::empty();
691 loop {
692 match self.next() {
693 'S' => {
694 builtin_bounds.insert(ty::BoundSend);
695 }
696 'Z' => {
697 builtin_bounds.insert(ty::BoundSized);
698 }
699 'P' => {
700 builtin_bounds.insert(ty::BoundCopy);
701 }
702 'T' => {
703 builtin_bounds.insert(ty::BoundSync);
704 }
705 '.' => {
706 return builtin_bounds;
707 }
708 c => {
709 panic!("parse_bounds: bad builtin bounds ('{}')", c)
710 }
711 }
712 }
713 }
714 }
715
716 // Rust metadata parsing
717 fn parse_defid(buf: &[u8]) -> DefId {
718 let mut colon_idx = 0;
719 let len = buf.len();
720 while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }
721 if colon_idx == len {
722 error!("didn't find ':' when parsing def id");
723 panic!();
724 }
725
726 let crate_part = &buf[0..colon_idx];
727 let def_part = &buf[colon_idx + 1..len];
728
729 let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| {
730 s.parse::<usize>().ok()
731 }) {
732 Some(cn) => cn as ast::CrateNum,
733 None => panic!("internal error: parse_defid: crate number expected, found {:?}",
734 crate_part)
735 };
736 let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
737 s.parse::<usize>().ok()
738 }) {
739 Some(dn) => dn as ast::NodeId,
740 None => panic!("internal error: parse_defid: id expected, found {:?}",
741 def_part)
742 };
743 DefId { krate: crate_num, node: def_num }
744 }
745
746 fn parse_unsafety(c: char) -> hir::Unsafety {
747 match c {
748 'u' => hir::Unsafety::Unsafe,
749 'n' => hir::Unsafety::Normal,
750 _ => panic!("parse_unsafety: bad unsafety {}", c)
751 }
752 }