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