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