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