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.
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.
14 // tjc note: Would be great to have a `match check` macro equivalent
17 #![allow(non_camel_case_types)]
19 pub use self::DefIdSource
::*;
23 use middle
::def_id
::DefId
;
26 use middle
::subst
::VecPerParamSpace
;
27 use middle
::ty
::{self, ToPredicate, Ty, HasTypeFlags}
;
33 use syntax
::parse
::token
;
35 // Compact string representation for Ty values. API TyStr &
36 // parse_from_str. Extra parameters are for converting to/from def_ids in the
37 // data buffer. Whatever format you choose should not contain pipe characters.
39 // Def id conversion: when we encounter def-ids, they have to be translated.
40 // For example, the crate number must be converted from the crate number used
41 // in the library we are reading from into the local crate numbers in use
42 // here. To perform this translation, the type decoder is supplied with a
43 // conversion function of type `conv_did`.
45 // Sometimes, particularly when inlining, the correct translation of the
46 // def-id will depend on where it originated from. Therefore, the conversion
47 // function is given an indicator of the source of the def-id. See
48 // astencode.rs for more information.
49 #[derive(Copy, Clone, Debug)]
50 pub enum DefIdSource
{
51 // Identifies a struct, trait, enum, etc.
54 // Identifies a type alias (`type X = ...`).
57 // Identifies a region parameter (`fn foo<'X>() { ... }`).
60 // Identifies a closure
64 pub type DefIdConvert
<'a
> = &'a
mut FnMut(DefIdSource
, DefId
) -> DefId
;
66 pub struct TyDecoder
<'a
, 'tcx
: 'a
> {
70 tcx
: &'a ty
::ctxt
<'tcx
>,
71 conv_def_id
: DefIdConvert
<'a
>,
74 impl<'a
,'tcx
> TyDecoder
<'a
,'tcx
> {
75 pub fn with_doc(tcx
: &'a ty
::ctxt
<'tcx
>,
76 crate_num
: ast
::CrateNum
,
78 conv
: DefIdConvert
<'a
>)
79 -> TyDecoder
<'a
,'tcx
> {
80 TyDecoder
::new(doc
.data
, crate_num
, doc
.start
, tcx
, conv
)
83 pub fn new(data
: &'a
[u8],
84 crate_num
: ast
::CrateNum
,
86 tcx
: &'a ty
::ctxt
<'tcx
>,
87 conv
: DefIdConvert
<'a
>)
88 -> TyDecoder
<'a
, 'tcx
> {
98 fn peek(&self) -> char {
99 self.data
[self.pos
] as char
102 fn next(&mut self) -> char {
103 let ch
= self.data
[self.pos
] as char;
104 self.pos
= self.pos
+ 1;
108 fn next_byte(&mut self) -> u8 {
109 let b
= self.data
[self.pos
];
110 self.pos
= self.pos
+ 1;
114 fn scan
<F
>(&mut self, mut is_last
: F
) -> &'a
[u8]
115 where F
: FnMut(char) -> bool
,
117 let start_pos
= self.pos
;
118 debug
!("scan: '{}' (start)", self.data
[self.pos
] as char);
119 while !is_last(self.data
[self.pos
] as char) {
121 debug
!("scan: '{}'", self.data
[self.pos
] as char);
123 let end_pos
= self.pos
;
125 return &self.data
[start_pos
..end_pos
];
128 fn parse_name(&mut self, last
: char) -> ast
::Name
{
129 fn is_last(b
: char, c
: char) -> bool { return c == b; }
130 let bytes
= self.scan(|a
| is_last(last
, a
));
131 token
::intern(str::from_utf8(bytes
).unwrap())
134 fn parse_size(&mut self) -> Option
<usize> {
135 assert_eq
!(self.next(), '
/'
);
137 if self.peek() == '
|'
{
138 assert_eq
!(self.next(), '
|'
);
141 let n
= self.parse_uint();
142 assert_eq
!(self.next(), '
|'
);
147 fn parse_vec_per_param_space
<T
, F
>(&mut self, mut f
: F
) -> VecPerParamSpace
<T
> where
148 F
: FnMut(&mut TyDecoder
<'a
, 'tcx
>) -> T
,
150 let mut r
= VecPerParamSpace
::empty();
151 for &space
in &subst
::ParamSpace
::all() {
152 assert_eq
!(self.next(), '
['
);
153 while self.peek() != '
]'
{
154 r
.push(space
, f(self));
156 assert_eq
!(self.next(), '
]'
);
161 pub fn parse_substs(&mut self) -> subst
::Substs
<'tcx
> {
162 let regions
= self.parse_region_substs();
163 let types
= self.parse_vec_per_param_space(|this
| this
.parse_ty());
164 subst
::Substs { types: types, regions: regions }
167 fn parse_region_substs(&mut self) -> subst
::RegionSubsts
{
169 'e'
=> subst
::ErasedRegions
,
171 subst
::NonerasedRegions(
172 self.parse_vec_per_param_space(|this
| this
.parse_region()))
174 _
=> panic
!("parse_bound_region: bad input")
178 fn parse_bound_region(&mut self) -> ty
::BoundRegion
{
181 let id
= self.parse_u32();
182 assert_eq
!(self.next(), '
|'
);
186 let def
= self.parse_def(RegionParameter
);
187 let ident
= token
::str_to_ident(&self.parse_str('
]'
));
188 ty
::BrNamed(def
, ident
.name
)
191 let id
= self.parse_u32();
192 assert_eq
!(self.next(), '
|'
);
196 _
=> panic
!("parse_bound_region: bad input")
200 pub fn parse_region(&mut self) -> ty
::Region
{
203 assert_eq
!(self.next(), '
['
);
204 let id
= ty
::DebruijnIndex
::new(self.parse_u32());
205 assert_eq
!(self.next(), '
|'
);
206 let br
= self.parse_bound_region();
207 assert_eq
!(self.next(), '
]'
);
208 ty
::ReLateBound(id
, br
)
211 assert_eq
!(self.next(), '
['
);
212 // this is the wrong NodeId, but `param_id` is only accessed
213 // by the receiver-matching code in collect, which won't
214 // be going down this code path, and anyway I will kill it
215 // the moment wfcheck becomes the standard.
216 let node_id
= self.parse_uint() as ast
::NodeId
;
217 assert_eq
!(self.next(), '
|'
);
218 let space
= self.parse_param_space();
219 assert_eq
!(self.next(), '
|'
);
220 let index
= self.parse_u32();
221 assert_eq
!(self.next(), '
|'
);
222 let nm
= token
::str_to_ident(&self.parse_str('
]'
));
223 ty
::ReEarlyBound(ty
::EarlyBoundRegion
{
231 assert_eq
!(self.next(), '
['
);
232 let scope
= self.parse_scope();
233 assert_eq
!(self.next(), '
|'
);
234 let br
= self.parse_bound_region();
235 assert_eq
!(self.next(), '
]'
);
236 ty
::ReFree(ty
::FreeRegion
{ scope
: scope
,
240 let scope
= self.parse_scope();
241 assert_eq
!(self.next(), '
|'
);
250 _
=> panic
!("parse_region: bad input")
254 fn parse_scope(&mut self) -> region
::CodeExtent
{
255 self.tcx
.region_maps
.bogus_code_extent(match self.next() {
256 // This creates scopes with the wrong NodeId. This isn't
257 // actually a problem because scopes only exist *within*
258 // functions, and functions aren't loaded until trans which
259 // doesn't care about regions.
261 // May still be worth fixing though.
263 assert_eq
!(self.next(), '
['
);
264 let fn_id
= self.parse_uint() as ast
::NodeId
;
265 assert_eq
!(self.next(), '
|'
);
266 let body_id
= self.parse_uint() as ast
::NodeId
;
267 assert_eq
!(self.next(), '
]'
);
268 region
::CodeExtentData
::ParameterScope
{
269 fn_id
: fn_id
, body_id
: body_id
273 let node_id
= self.parse_uint() as ast
::NodeId
;
274 region
::CodeExtentData
::Misc(node_id
)
277 let node_id
= self.parse_uint() as ast
::NodeId
;
278 region
::CodeExtentData
::DestructionScope(node_id
)
281 assert_eq
!(self.next(), '
['
);
282 let node_id
= self.parse_uint() as ast
::NodeId
;
283 assert_eq
!(self.next(), '
|'
);
284 let first_stmt_index
= self.parse_u32();
285 assert_eq
!(self.next(), '
]'
);
286 let block_remainder
= region
::BlockRemainder
{
287 block
: node_id
, first_statement_index
: first_stmt_index
,
289 region
::CodeExtentData
::Remainder(block_remainder
)
291 _
=> panic
!("parse_scope: bad input")
295 fn parse_opt
<T
, F
>(&mut self, f
: F
) -> Option
<T
>
296 where F
: FnOnce(&mut TyDecoder
<'a
, 'tcx
>) -> T
,
300 's'
=> Some(f(self)),
301 _
=> panic
!("parse_opt: bad input")
305 fn parse_str(&mut self, term
: char) -> String
{
306 let mut result
= String
::new();
307 while self.peek() != term
{
309 result
.as_mut_vec().push_all(&[self.next_byte()])
316 pub fn parse_trait_ref(&mut self) -> ty
::TraitRef
<'tcx
> {
317 let def
= self.parse_def(NominalType
);
318 let substs
= self.tcx
.mk_substs(self.parse_substs());
319 ty
::TraitRef {def_id: def, substs: substs}
322 pub fn parse_ty(&mut self) -> Ty
<'tcx
> {
325 'b'
=> return tcx
.types
.bool
,
326 'i'
=> { /* eat the s of is */ self.next(); return tcx.types.isize }
,
327 'u'
=> { /* eat the s of us */ self.next(); return tcx.types.usize }
,
330 'b'
=> return tcx
.types
.u8,
331 'w'
=> return tcx
.types
.u16,
332 'l'
=> return tcx
.types
.u32,
333 'd'
=> return tcx
.types
.u64,
334 'B'
=> return tcx
.types
.i8,
335 'W'
=> return tcx
.types
.i16,
336 'L'
=> return tcx
.types
.i32,
337 'D'
=> return tcx
.types
.i64,
338 'f'
=> return tcx
.types
.f32,
339 'F'
=> return tcx
.types
.f64,
340 _
=> panic
!("parse_ty: bad numeric type")
343 'c'
=> return tcx
.types
.char,
345 assert_eq
!(self.next(), '
['
);
346 let did
= self.parse_def(NominalType
);
347 let substs
= self.parse_substs();
348 assert_eq
!(self.next(), '
]'
);
349 let def
= self.tcx
.lookup_adt_def(did
);
350 return tcx
.mk_enum(def
, self.tcx
.mk_substs(substs
));
353 assert_eq
!(self.next(), '
['
);
354 let trait_ref
= ty
::Binder(self.parse_trait_ref());
355 let bounds
= self.parse_existential_bounds();
356 assert_eq
!(self.next(), '
]'
);
357 return tcx
.mk_trait(trait_ref
, bounds
);
360 assert_eq
!(self.next(), '
['
);
361 let index
= self.parse_u32();
362 assert_eq
!(self.next(), '
|'
);
363 let space
= self.parse_param_space();
364 assert_eq
!(self.next(), '
|'
);
365 let name
= token
::intern(&self.parse_str('
]'
));
366 return tcx
.mk_param(space
, index
, name
);
368 '
~'
=> return tcx
.mk_box(self.parse_ty()),
369 '
*'
=> return tcx
.mk_ptr(self.parse_mt()),
371 let r
= self.parse_region();
372 let mt
= self.parse_mt();
373 return tcx
.mk_ref(tcx
.mk_region(r
), mt
);
376 let t
= self.parse_ty();
377 return match self.parse_size() {
378 Some(n
) => tcx
.mk_array(t
, n
),
379 None
=> tcx
.mk_slice(t
)
386 assert_eq
!(self.next(), '
['
);
387 let mut params
= Vec
::new();
388 while self.peek() != '
]' { params.push(self.parse_ty()); }
389 self.pos
= self.pos
+ 1;
390 return tcx
.mk_tup(params
);
393 let def_id
= self.parse_def(NominalType
);
394 return tcx
.mk_fn(Some(def_id
), tcx
.mk_bare_fn(self.parse_bare_fn_ty()));
397 return tcx
.mk_fn(None
, tcx
.mk_bare_fn(self.parse_bare_fn_ty()));
400 // This is a hacky little caching scheme. The idea is that if we encode
401 // the same type twice, the second (and third, and fourth...) time we will
402 // just write `#123`, where `123` is the offset in the metadata of the
403 // first appearance. Now when we are *decoding*, if we see a `#123`, we
404 // can first check a cache (`tcx.rcache`) for that offset. If we find something,
405 // we return it (modulo closure types, see below). But if not, then we
406 // jump to offset 123 and read the type from there.
408 let pos
= self.parse_hex();
409 assert_eq
!(self.next(), '
:'
);
410 let len
= self.parse_hex();
411 assert_eq
!(self.next(), '
#');
412 let key
= ty
::CReaderCacheKey {cnum: self.krate, pos: pos, len: len }
;
413 match tcx
.rcache
.borrow().get(&key
).cloned() {
415 // If there is a closure buried in the type some where, then we
416 // need to re-convert any def ids (see case 'k', below). That means
417 // we can't reuse the cached version.
418 if !tt
.has_closure_types() {
425 let mut substate
= TyDecoder
::new(self.data
,
430 let tt
= substate
.parse_ty();
431 tcx
.rcache
.borrow_mut().insert(key
, tt
);
435 let _
= self.parse_def(TypeWithId
);
436 let inner
= self.parse_ty();
440 assert_eq
!(self.next(), '
['
);
441 let did
= self.parse_def(NominalType
);
442 let substs
= self.parse_substs();
443 assert_eq
!(self.next(), '
]'
);
444 let def
= self.tcx
.lookup_adt_def(did
);
445 return self.tcx
.mk_struct(def
, self.tcx
.mk_substs(substs
));
448 assert_eq
!(self.next(), '
['
);
449 let did
= self.parse_def(ClosureSource
);
450 let substs
= self.parse_substs();
451 let mut tys
= vec
![];
452 while self.peek() != '
.'
{
453 tys
.push(self.parse_ty());
455 assert_eq
!(self.next(), '
.'
);
456 assert_eq
!(self.next(), '
]'
);
457 return self.tcx
.mk_closure(did
, self.tcx
.mk_substs(substs
), tys
);
460 assert_eq
!(self.next(), '
['
);
461 let trait_ref
= self.parse_trait_ref();
462 let name
= token
::intern(&self.parse_str('
]'
));
463 return tcx
.mk_projection(trait_ref
, name
);
466 return tcx
.types
.err
;
468 c
=> { panic!("unexpected char in type string: {}
", c);}
472 fn parse_mutability(&mut self) -> hir::Mutability {
474 'm' => { self.next(); hir::MutMutable }
475 _ => { hir::MutImmutable }
479 fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> {
480 let m = self.parse_mutability();
481 ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
484 fn parse_def(&mut self, source: DefIdSource) -> DefId {
485 let def_id = parse_defid(self.scan(|c| c == '|'));
486 return (self.conv_def_id)(source, def_id);
489 fn parse_uint(&mut self) -> usize {
492 let cur = self.peek();
493 if cur < '0' || cur > '9' { return n; }
494 self.pos = self.pos + 1;
496 n += (cur as usize) - ('0' as usize);
500 fn parse_u32(&mut self) -> u32 {
501 let n = self.parse_uint();
503 assert_eq!(m as usize, n);
507 fn parse_param_space(&mut self) -> subst::ParamSpace {
508 subst::ParamSpace::from_uint(self.parse_uint())
511 fn parse_hex(&mut self) -> usize {
514 let cur = self.peek();
515 if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
516 self.pos = self.pos + 1;
518 if '0' <= cur && cur <= '9' {
519 n += (cur as usize) - ('0' as usize);
520 } else { n += 10 + (cur as usize) - ('a' as usize); }
524 fn parse_abi_set(&mut self) -> abi::Abi {
525 assert_eq!(self.next(), '[');
526 let bytes = self.scan(|c| c == ']');
527 let abi_str = str::from_utf8(bytes).unwrap();
528 abi::lookup(&abi_str[..]).expect(abi_str)
531 pub fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
532 let unsafety = parse_unsafety(self.next());
533 let sig = self.parse_sig();
534 let abi = self.parse_abi_set();
542 pub fn parse_bare_fn_ty(&mut self) -> ty::BareFnTy<'tcx> {
543 let unsafety = parse_unsafety(self.next());
544 let abi = self.parse_abi_set();
545 let sig = self.parse_sig();
553 fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> {
554 assert_eq!(self.next(), '[');
555 let mut inputs = Vec::new();
556 while self.peek() != ']' {
557 inputs.push(self.parse_ty());
559 self.pos += 1; // eat the ']'
560 let variadic = match self.next() {
563 r => panic!(format!("bad variadic
: {}
", r)),
565 let output = match self.peek() {
570 _ => ty::FnConverging(self.parse_ty())
572 ty::Binder(ty::FnSig {inputs: inputs,
577 pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
579 't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
580 'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
581 self.parse_ty())).to_predicate(),
582 'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(),
583 self.parse_region())).to_predicate(),
584 'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(),
585 self.parse_region())).to_predicate(),
586 'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
587 'w' => ty::Predicate::WellFormed(self.parse_ty()),
589 let def_id = self.parse_def(NominalType);
590 assert_eq!(self.next(), '|');
591 ty::Predicate::ObjectSafe(def_id)
593 c => panic!("Encountered invalid character
in metadata
: {}
", c)
597 fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
598 ty::ProjectionPredicate {
599 projection_ty: ty::ProjectionTy {
600 trait_ref: self.parse_trait_ref(),
601 item_name: token::str_to_ident(&self.parse_str('|')).name,
607 pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
608 let name = self.parse_name(':');
609 let def_id = self.parse_def(NominalType);
610 let space = self.parse_param_space();
611 assert_eq!(self.next(), '|');
612 let index = self.parse_u32();
613 assert_eq!(self.next(), '|');
614 let default_def_id = self.parse_def(NominalType);
615 let default = self.parse_opt(|this| this.parse_ty());
616 let object_lifetime_default = self.parse_object_lifetime_default();
618 ty::TypeParameterDef {
623 default_def_id: default_def_id,
625 object_lifetime_default: object_lifetime_default,
629 pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
630 let name = self.parse_name(':');
631 let def_id = self.parse_def(NominalType);
632 let space = self.parse_param_space();
633 assert_eq!(self.next(), '|');
634 let index = self.parse_u32();
635 assert_eq!(self.next(), '|');
636 let mut bounds = vec![];
639 'R' => bounds.push(self.parse_region()),
642 panic!("parse_region_param_def
: bad
bounds ('{}'
)", c)
646 ty::RegionParameterDef {
656 fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
658 'a' => ty::ObjectLifetimeDefault::Ambiguous,
659 'b' => ty::ObjectLifetimeDefault::BaseDefault,
661 let region = self.parse_region();
662 ty::ObjectLifetimeDefault::Specific(region)
664 _ => panic!("parse_object_lifetime_default
: bad input
")
668 pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
669 let builtin_bounds = self.parse_builtin_bounds();
670 let region_bound = self.parse_region();
671 let mut projection_bounds = Vec::new();
676 projection_bounds.push(ty::Binder(self.parse_projection_predicate()));
680 panic!("parse_bounds
: bad
bounds ('{}'
)", c)
685 ty::ExistentialBounds::new(
686 region_bound, builtin_bounds, projection_bounds)
689 fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
690 let mut builtin_bounds = ty::BuiltinBounds::empty();
694 builtin_bounds.insert(ty::BoundSend);
697 builtin_bounds.insert(ty::BoundSized);
700 builtin_bounds.insert(ty::BoundCopy);
703 builtin_bounds.insert(ty::BoundSync);
706 return builtin_bounds;
709 panic!("parse_bounds
: bad builtin
bounds ('{}'
)", c)
716 // Rust metadata parsing
717 fn parse_defid(buf: &[u8]) -> DefId {
718 let mut colon_idx = 0;
720 while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }
721 if colon_idx == len {
722 error!("didn't find '
:' when parsing def id
");
726 let crate_part = &buf[0..colon_idx];
727 let def_part = &buf[colon_idx + 1..len];
729 let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| {
730 s.parse::<usize>().ok()
732 Some(cn) => cn as ast::CrateNum,
733 None => panic!("internal error
: parse_defid
: crate number expected
, found {:?}
",
736 let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
737 s.parse::<usize>().ok()
739 Some(dn) => dn as ast::NodeId,
740 None => panic!("internal error
: parse_defid
: id expected
, found {:?}
",
743 DefId { krate: crate_num, node: def_num }
746 fn parse_unsafety(c: char) -> hir::Unsafety {
748 'u' => hir::Unsafety::Unsafe,
749 'n' => hir::Unsafety::Normal,
750 _ => panic!("parse_unsafety
: bad unsafety {}
", c)