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