2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-01-07 16:16:52 -06:00
|
|
|
|
2011-06-27 17:30:17 -05:00
|
|
|
// Type decoding
|
2011-06-27 18:03:01 -05:00
|
|
|
|
2012-08-22 19:58:05 -05:00
|
|
|
// tjc note: Would be great to have a `match check` macro equivalent
|
|
|
|
// for some of these
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
|
2012-12-13 15:05:22 -06:00
|
|
|
use middle::ty;
|
|
|
|
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::str;
|
|
|
|
use std::uint;
|
2013-03-13 21:25:28 -05:00
|
|
|
use syntax::abi::AbiSet;
|
|
|
|
use syntax::abi;
|
2012-09-04 13:54:36 -05:00
|
|
|
use syntax::ast;
|
|
|
|
use syntax::ast::*;
|
2013-03-26 15:38:07 -05:00
|
|
|
use syntax::codemap::dummy_sp;
|
2013-03-27 11:55:18 -05:00
|
|
|
use syntax::opt_vec;
|
2011-06-27 17:30:17 -05:00
|
|
|
|
2011-07-04 21:07:56 -05:00
|
|
|
// Compact string representation for ty::t values. API ty_str &
|
|
|
|
// parse_from_str. Extra parameters are for converting to/from def_ids in the
|
|
|
|
// data buffer. Whatever format you choose should not contain pipe characters.
|
2011-06-27 17:30:17 -05:00
|
|
|
|
2013-01-17 08:13:26 -06:00
|
|
|
// Def id conversion: when we encounter def-ids, they have to be translated.
|
|
|
|
// For example, the crate number must be converted from the crate number used
|
|
|
|
// in the library we are reading from into the local crate numbers in use
|
|
|
|
// here. To perform this translation, the type decoder is supplied with a
|
|
|
|
// conversion function of type `conv_did`.
|
|
|
|
//
|
|
|
|
// Sometimes, particularly when inlining, the correct translation of the
|
|
|
|
// def-id will depend on where it originated from. Therefore, the conversion
|
|
|
|
// function is given an indicator of the source of the def-id. See
|
|
|
|
// astencode.rs for more information.
|
2013-01-29 18:51:16 -06:00
|
|
|
pub enum DefIdSource {
|
2013-01-17 08:13:26 -06:00
|
|
|
// Identifies a struct, trait, enum, etc.
|
|
|
|
NominalType,
|
|
|
|
|
|
|
|
// Identifies a type alias (`type X = ...`).
|
|
|
|
TypeWithId,
|
|
|
|
|
|
|
|
// Identifies a type parameter (`fn foo<X>() { ... }`).
|
|
|
|
TypeParameter
|
|
|
|
}
|
2013-03-25 15:21:04 -05:00
|
|
|
type conv_did<'self> =
|
2013-09-01 20:45:37 -05:00
|
|
|
&'self fn(source: DefIdSource, ast::DefId) -> ast::DefId;
|
2011-06-27 17:30:17 -05:00
|
|
|
|
2013-06-07 19:24:11 -05:00
|
|
|
pub struct PState<'self> {
|
|
|
|
data: &'self [u8],
|
2013-02-04 16:02:01 -06:00
|
|
|
crate: int,
|
|
|
|
pos: uint,
|
|
|
|
tcx: ty::ctxt
|
|
|
|
}
|
2011-06-27 17:30:17 -05:00
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn peek(st: &PState) -> char {
|
2012-02-13 13:55:23 -06:00
|
|
|
st.data[st.pos] as char
|
2011-12-28 10:50:12 -06:00
|
|
|
}
|
2011-06-27 17:30:17 -05:00
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn next(st: &mut PState) -> char {
|
2012-02-13 13:55:23 -06:00
|
|
|
let ch = st.data[st.pos] as char;
|
2011-06-27 17:30:17 -05:00
|
|
|
st.pos = st.pos + 1u;
|
2012-08-01 19:30:05 -05:00
|
|
|
return ch;
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn next_byte(st: &mut PState) -> u8 {
|
2012-02-13 13:55:23 -06:00
|
|
|
let b = st.data[st.pos];
|
|
|
|
st.pos = st.pos + 1u;
|
2012-08-01 19:30:05 -05:00
|
|
|
return b;
|
2012-02-13 13:55:23 -06:00
|
|
|
}
|
|
|
|
|
2013-03-13 21:25:28 -05:00
|
|
|
fn scan<R>(st: &mut PState, is_last: &fn(char) -> bool,
|
|
|
|
op: &fn(&[u8]) -> R) -> R
|
|
|
|
{
|
|
|
|
let start_pos = st.pos;
|
2013-09-28 00:38:08 -05:00
|
|
|
debug2!("scan: '{}' (start)", st.data[st.pos] as char);
|
2013-03-13 21:25:28 -05:00
|
|
|
while !is_last(st.data[st.pos] as char) {
|
|
|
|
st.pos += 1;
|
2013-09-28 00:38:08 -05:00
|
|
|
debug2!("scan: '{}'", st.data[st.pos] as char);
|
2013-03-13 21:25:28 -05:00
|
|
|
}
|
|
|
|
let end_pos = st.pos;
|
|
|
|
st.pos += 1;
|
|
|
|
return op(st.data.slice(start_pos, end_pos));
|
|
|
|
}
|
|
|
|
|
2013-09-01 19:50:59 -05:00
|
|
|
pub fn parse_ident(st: &mut PState, last: char) -> ast::Ident {
|
2012-08-01 19:30:05 -05:00
|
|
|
fn is_last(b: char, c: char) -> bool { return c == b; }
|
|
|
|
return parse_ident_(st, |a| is_last(last, a) );
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2013-08-29 17:04:09 -05:00
|
|
|
fn parse_ident_(st: &mut PState, is_last: &fn(char) -> bool) -> ast::Ident {
|
2013-09-05 07:17:24 -05:00
|
|
|
let rslt = scan(st, is_last, str::from_utf8);
|
2012-07-18 18:18:02 -05:00
|
|
|
return st.tcx.sess.ident_of(rslt);
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:24:11 -05:00
|
|
|
pub fn parse_state_from_data<'a>(data: &'a [u8], crate_num: int,
|
|
|
|
pos: uint, tcx: ty::ctxt) -> PState<'a> {
|
2013-06-07 19:01:30 -05:00
|
|
|
PState {
|
2013-02-04 16:02:01 -06:00
|
|
|
data: data,
|
|
|
|
crate: crate_num,
|
|
|
|
pos: pos,
|
|
|
|
tcx: tcx
|
|
|
|
}
|
2012-09-11 23:25:01 -05:00
|
|
|
}
|
2011-06-27 17:30:17 -05:00
|
|
|
|
2013-06-07 19:24:11 -05:00
|
|
|
pub fn parse_ty_data(data: &[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
|
2013-01-29 18:51:16 -06:00
|
|
|
conv: conv_did) -> ty::t {
|
2013-06-07 19:01:30 -05:00
|
|
|
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
|
|
|
|
parse_ty(&mut st, conv)
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:24:11 -05:00
|
|
|
pub fn parse_bare_fn_ty_data(data: &[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
|
2013-03-27 09:26:57 -05:00
|
|
|
conv: conv_did) -> ty::BareFnTy {
|
2013-06-07 19:01:30 -05:00
|
|
|
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
|
|
|
|
parse_bare_fn_ty(&mut st, conv)
|
2013-03-27 09:26:57 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:24:11 -05:00
|
|
|
pub fn parse_trait_ref_data(data: &[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
|
2013-03-27 05:16:28 -05:00
|
|
|
conv: conv_did) -> ty::TraitRef {
|
2013-06-07 19:01:30 -05:00
|
|
|
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
|
|
|
|
parse_trait_ref(&mut st, conv)
|
2013-03-27 05:16:28 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_path(st: &mut PState) -> @ast::Path {
|
2013-09-01 19:50:59 -05:00
|
|
|
let mut idents: ~[ast::Ident] = ~[];
|
2012-08-01 19:30:05 -05:00
|
|
|
fn is_last(c: char) -> bool { return c == '(' || c == ':'; }
|
2012-09-26 19:33:34 -05:00
|
|
|
idents.push(parse_ident_(st, is_last));
|
2012-03-10 22:34:17 -06:00
|
|
|
loop {
|
2012-08-06 14:34:08 -05:00
|
|
|
match peek(st) {
|
2012-08-03 21:59:04 -05:00
|
|
|
':' => { next(st); next(st); }
|
|
|
|
c => {
|
2011-07-27 07:19:39 -05:00
|
|
|
if c == '(' {
|
2013-08-07 11:47:28 -05:00
|
|
|
return @ast::Path {
|
|
|
|
span: dummy_sp(),
|
|
|
|
global: false,
|
2013-08-08 13:38:10 -05:00
|
|
|
segments: idents.move_iter().map(|identifier| {
|
2013-08-07 11:47:28 -05:00
|
|
|
ast::PathSegment {
|
|
|
|
identifier: identifier,
|
|
|
|
lifetime: None,
|
|
|
|
types: opt_vec::Empty,
|
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
idents.push(parse_ident_(st, is_last));
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
}
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
2012-03-10 22:34:17 -06:00
|
|
|
};
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_sigil(st: &mut PState) -> ast::Sigil {
|
2012-08-10 20:15:08 -05:00
|
|
|
match next(st) {
|
2013-01-31 19:12:29 -06:00
|
|
|
'@' => ast::ManagedSigil,
|
|
|
|
'~' => ast::OwnedSigil,
|
|
|
|
'&' => ast::BorrowedSigil,
|
2013-09-28 00:38:08 -05:00
|
|
|
c => st.tcx.sess.bug(format!("parse_sigil(): bad input '{}'", c))
|
2012-01-12 17:38:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_vstore(st: &mut PState) -> ty::vstore {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '/');
|
2012-04-20 18:56:19 -05:00
|
|
|
|
|
|
|
let c = peek(st);
|
|
|
|
if '0' <= c && c <= '9' {
|
2013-04-10 00:45:12 -05:00
|
|
|
let n = parse_uint(st);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '|');
|
2012-08-01 19:30:05 -05:00
|
|
|
return ty::vstore_fixed(n);
|
2012-04-20 18:56:19 -05:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:58:05 -05:00
|
|
|
match next(st) {
|
2012-08-03 21:59:04 -05:00
|
|
|
'~' => ty::vstore_uniq,
|
|
|
|
'@' => ty::vstore_box,
|
2012-08-22 19:58:05 -05:00
|
|
|
'&' => ty::vstore_slice(parse_region(st)),
|
2013-09-28 00:38:08 -05:00
|
|
|
c => st.tcx.sess.bug(format!("parse_vstore(): bad input '{}'", c))
|
2012-04-20 18:56:19 -05:00
|
|
|
}
|
2012-04-10 20:32:51 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_trait_store(st: &mut PState) -> ty::TraitStore {
|
2013-03-08 23:16:09 -06:00
|
|
|
match next(st) {
|
|
|
|
'~' => ty::UniqTraitStore,
|
|
|
|
'@' => ty::BoxTraitStore,
|
|
|
|
'&' => ty::RegionTraitStore(parse_region(st)),
|
2013-09-28 00:38:08 -05:00
|
|
|
c => st.tcx.sess.bug(format!("parse_trait_store(): bad input '{}'", c))
|
2013-03-08 23:16:09 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
|
2013-07-25 14:49:25 -05:00
|
|
|
let regions = parse_region_substs(st);
|
2012-04-18 23:26:25 -05:00
|
|
|
|
2013-06-21 19:08:35 -05:00
|
|
|
let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
|
2012-05-09 08:09:58 -05:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '[');
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut params: ~[ty::t] = ~[];
|
2013-06-21 19:08:35 -05:00
|
|
|
while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
|
2012-04-18 23:26:25 -05:00
|
|
|
st.pos = st.pos + 1u;
|
|
|
|
|
2013-01-31 19:12:29 -06:00
|
|
|
return ty::substs {
|
2013-07-24 15:52:57 -05:00
|
|
|
regions: regions,
|
2013-01-25 18:57:39 -06:00
|
|
|
self_ty: self_ty,
|
|
|
|
tps: params
|
|
|
|
};
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
|
|
|
|
2013-07-25 14:49:25 -05:00
|
|
|
fn parse_region_substs(st: &mut PState) -> ty::RegionSubsts {
|
2013-07-24 15:52:57 -05:00
|
|
|
match next(st) {
|
|
|
|
'e' => ty::ErasedRegions,
|
|
|
|
'n' => {
|
|
|
|
let mut regions = opt_vec::Empty;
|
|
|
|
while peek(st) != '.' {
|
|
|
|
let r = parse_region(st);
|
|
|
|
regions.push(r);
|
|
|
|
}
|
|
|
|
assert_eq!(next(st), '.');
|
|
|
|
ty::NonerasedRegions(regions)
|
|
|
|
}
|
2013-09-28 00:38:08 -05:00
|
|
|
_ => fail2!("parse_bound_region: bad input")
|
2013-07-24 15:52:57 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_bound_region(st: &mut PState) -> ty::bound_region {
|
2012-08-22 19:58:05 -05:00
|
|
|
match next(st) {
|
2012-08-03 21:59:04 -05:00
|
|
|
's' => ty::br_self,
|
2012-08-20 18:53:33 -05:00
|
|
|
'a' => {
|
2013-04-10 00:45:12 -05:00
|
|
|
let id = parse_uint(st);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '|');
|
2012-08-20 18:53:33 -05:00
|
|
|
ty::br_anon(id)
|
|
|
|
}
|
2012-07-18 18:18:02 -05:00
|
|
|
'[' => ty::br_named(st.tcx.sess.ident_of(parse_str(st, ']'))),
|
2012-08-03 21:59:04 -05:00
|
|
|
'c' => {
|
2013-04-10 00:45:12 -05:00
|
|
|
let id = parse_uint(st) as int;
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '|');
|
2012-07-25 11:19:59 -05:00
|
|
|
ty::br_cap_avoid(id, @parse_bound_region(st))
|
2012-08-22 19:58:05 -05:00
|
|
|
},
|
2013-09-28 00:38:08 -05:00
|
|
|
_ => fail2!("parse_bound_region: bad input")
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_region(st: &mut PState) -> ty::Region {
|
2012-08-22 19:58:05 -05:00
|
|
|
match next(st) {
|
2012-08-03 21:59:04 -05:00
|
|
|
'b' => {
|
2012-04-18 23:26:25 -05:00
|
|
|
ty::re_bound(parse_bound_region(st))
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'f' => {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '[');
|
2013-04-10 00:45:12 -05:00
|
|
|
let id = parse_uint(st) as int;
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '|');
|
2012-04-18 23:26:25 -05:00
|
|
|
let br = parse_bound_region(st);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), ']');
|
2013-04-02 00:32:37 -05:00
|
|
|
ty::re_free(ty::FreeRegion {scope_id: id,
|
|
|
|
bound_region: br})
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
's' => {
|
2013-04-10 00:45:12 -05:00
|
|
|
let id = parse_uint(st) as int;
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '|');
|
2012-04-18 23:26:25 -05:00
|
|
|
ty::re_scope(id)
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
't' => {
|
2012-04-18 23:26:25 -05:00
|
|
|
ty::re_static
|
|
|
|
}
|
2013-03-15 14:24:24 -05:00
|
|
|
'e' => {
|
|
|
|
ty::re_static
|
|
|
|
}
|
2013-09-28 00:38:08 -05:00
|
|
|
_ => fail2!("parse_region: bad input")
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_opt<T>(st: &mut PState, f: &fn(&mut PState) -> T) -> Option<T> {
|
2012-08-22 19:58:05 -05:00
|
|
|
match next(st) {
|
2012-08-20 14:23:37 -05:00
|
|
|
'n' => None,
|
2013-06-07 19:01:30 -05:00
|
|
|
's' => Some(f(st)),
|
2013-09-28 00:38:08 -05:00
|
|
|
_ => fail2!("parse_opt: bad input")
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_str(st: &mut PState, term: char) -> ~str {
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut result = ~"";
|
2012-04-18 23:26:25 -05:00
|
|
|
while peek(st) != term {
|
2013-06-11 21:13:42 -05:00
|
|
|
unsafe {
|
|
|
|
str::raw::push_byte(&mut result, next_byte(st));
|
|
|
|
}
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
|
|
|
next(st);
|
2012-08-01 19:30:05 -05:00
|
|
|
return result;
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_trait_ref(st: &mut PState, conv: conv_did) -> ty::TraitRef {
|
2013-06-21 19:08:35 -05:00
|
|
|
let def = parse_def(st, NominalType, |x,y| conv(x,y));
|
|
|
|
let substs = parse_substs(st, |x,y| conv(x,y));
|
2013-03-27 05:16:28 -05:00
|
|
|
ty::TraitRef {def_id: def, substs: substs}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
|
2012-08-22 19:58:05 -05:00
|
|
|
match next(st) {
|
2013-04-22 22:19:05 -05:00
|
|
|
'n' => return ty::mk_nil(),
|
|
|
|
'z' => return ty::mk_bot(),
|
|
|
|
'b' => return ty::mk_bool(),
|
|
|
|
'i' => return ty::mk_int(),
|
|
|
|
'u' => return ty::mk_uint(),
|
2012-08-03 21:59:04 -05:00
|
|
|
'M' => {
|
2012-08-22 19:58:05 -05:00
|
|
|
match next(st) {
|
2013-04-22 22:19:05 -05:00
|
|
|
'b' => return ty::mk_mach_uint(ast::ty_u8),
|
|
|
|
'w' => return ty::mk_mach_uint(ast::ty_u16),
|
|
|
|
'l' => return ty::mk_mach_uint(ast::ty_u32),
|
|
|
|
'd' => return ty::mk_mach_uint(ast::ty_u64),
|
|
|
|
'B' => return ty::mk_mach_int(ast::ty_i8),
|
|
|
|
'W' => return ty::mk_mach_int(ast::ty_i16),
|
|
|
|
'L' => return ty::mk_mach_int(ast::ty_i32),
|
|
|
|
'D' => return ty::mk_mach_int(ast::ty_i64),
|
|
|
|
'f' => return ty::mk_mach_float(ast::ty_f32),
|
|
|
|
'F' => return ty::mk_mach_float(ast::ty_f64),
|
2013-09-28 00:38:08 -05:00
|
|
|
_ => fail2!("parse_ty: bad numeric type")
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
}
|
2013-04-22 22:19:05 -05:00
|
|
|
'c' => return ty::mk_char(),
|
2012-08-03 21:59:04 -05:00
|
|
|
't' => {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '[');
|
2013-06-21 19:08:35 -05:00
|
|
|
let def = parse_def(st, NominalType, |x,y| conv(x,y));
|
|
|
|
let substs = parse_substs(st, |x,y| conv(x,y));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), ']');
|
2012-08-01 19:30:05 -05:00
|
|
|
return ty::mk_enum(st.tcx, def, substs);
|
2011-07-27 07:19:39 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'x' => {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '[');
|
2013-06-21 19:08:35 -05:00
|
|
|
let def = parse_def(st, NominalType, |x,y| conv(x,y));
|
|
|
|
let substs = parse_substs(st, |x,y| conv(x,y));
|
2013-03-08 23:16:09 -06:00
|
|
|
let store = parse_trait_store(st);
|
2013-04-02 02:40:57 -05:00
|
|
|
let mt = parse_mutability(st);
|
2013-06-21 19:08:35 -05:00
|
|
|
let bounds = parse_bounds(st, |x,y| conv(x,y));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), ']');
|
2013-06-17 14:16:30 -05:00
|
|
|
return ty::mk_trait(st.tcx, def, substs, store, mt, bounds.builtin_bounds);
|
2011-12-29 04:23:35 -06:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'p' => {
|
2013-01-17 08:13:26 -06:00
|
|
|
let did = parse_def(st, TypeParameter, conv);
|
2013-09-28 00:38:08 -05:00
|
|
|
debug2!("parsed ty_param: did={:?}", did);
|
2013-04-10 00:45:12 -05:00
|
|
|
return ty::mk_param(st.tcx, parse_uint(st), did);
|
2011-07-28 15:29:29 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
's' => {
|
2013-03-19 09:36:02 -05:00
|
|
|
let did = parse_def(st, TypeParameter, conv);
|
|
|
|
return ty::mk_self(st.tcx, did);
|
2012-01-30 04:52:34 -06:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'@' => return ty::mk_box(st.tcx, parse_mt(st, conv)),
|
|
|
|
'~' => return ty::mk_uniq(st.tcx, parse_mt(st, conv)),
|
|
|
|
'*' => return ty::mk_ptr(st.tcx, parse_mt(st, conv)),
|
|
|
|
'&' => {
|
2012-04-23 17:23:20 -05:00
|
|
|
let r = parse_region(st);
|
|
|
|
let mt = parse_mt(st, conv);
|
2012-08-01 19:30:05 -05:00
|
|
|
return ty::mk_rptr(st.tcx, r, mt);
|
2012-04-23 17:23:20 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'U' => return ty::mk_unboxed_vec(st.tcx, parse_mt(st, conv)),
|
|
|
|
'V' => {
|
2012-04-10 20:32:51 -05:00
|
|
|
let mt = parse_mt(st, conv);
|
|
|
|
let v = parse_vstore(st);
|
2012-08-01 19:30:05 -05:00
|
|
|
return ty::mk_evec(st.tcx, mt, v);
|
2012-04-10 20:32:51 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'v' => {
|
2012-04-10 20:32:51 -05:00
|
|
|
let v = parse_vstore(st);
|
2012-08-01 19:30:05 -05:00
|
|
|
return ty::mk_estr(st.tcx, v);
|
2012-04-10 20:32:51 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'T' => {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '[');
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut params = ~[];
|
2013-06-21 19:08:35 -05:00
|
|
|
while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
|
2011-08-15 04:40:26 -05:00
|
|
|
st.pos = st.pos + 1u;
|
2012-08-01 19:30:05 -05:00
|
|
|
return ty::mk_tup(st.tcx, params);
|
2011-08-15 04:40:26 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'f' => {
|
2013-01-31 19:12:29 -06:00
|
|
|
return ty::mk_closure(st.tcx, parse_closure_ty(st, conv));
|
|
|
|
}
|
|
|
|
'F' => {
|
|
|
|
return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, conv));
|
2011-07-27 07:19:39 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'Y' => return ty::mk_type(st.tcx),
|
|
|
|
'C' => {
|
2013-01-31 19:12:29 -06:00
|
|
|
let sigil = parse_sigil(st);
|
|
|
|
return ty::mk_opaque_closure_ptr(st.tcx, sigil);
|
2012-01-05 18:19:12 -06:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'#' => {
|
2011-07-27 07:19:39 -05:00
|
|
|
let pos = parse_hex(st);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), ':');
|
2011-07-27 07:19:39 -05:00
|
|
|
let len = parse_hex(st);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '#');
|
2013-01-31 19:12:29 -06:00
|
|
|
let key = ty::creader_cache_key {cnum: st.crate,
|
|
|
|
pos: pos,
|
|
|
|
len: len };
|
2013-02-05 21:41:45 -06:00
|
|
|
match st.tcx.rcache.find(&key) {
|
2013-03-22 21:26:41 -05:00
|
|
|
Some(&tt) => return tt,
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2013-06-27 19:41:35 -05:00
|
|
|
let mut ps = PState {
|
|
|
|
pos: pos,
|
|
|
|
.. *st
|
|
|
|
};
|
2013-06-07 19:01:30 -05:00
|
|
|
let tt = parse_ty(&mut ps, conv);
|
2013-01-25 18:57:39 -06:00
|
|
|
st.tcx.rcache.insert(key, tt);
|
2012-08-01 19:30:05 -05:00
|
|
|
return tt;
|
2011-07-27 07:19:39 -05:00
|
|
|
}
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'"' => {
|
2013-06-21 19:08:35 -05:00
|
|
|
let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
|
|
|
|
let inner = parse_ty(st, |x,y| conv(x,y));
|
2013-04-02 15:41:18 -05:00
|
|
|
inner
|
2012-01-16 04:45:18 -06:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'B' => ty::mk_opaque_box(st.tcx),
|
|
|
|
'a' => {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '[');
|
2013-06-21 19:08:35 -05:00
|
|
|
let did = parse_def(st, NominalType, |x,y| conv(x,y));
|
|
|
|
let substs = parse_substs(st, |x,y| conv(x,y));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), ']');
|
2012-12-10 15:47:54 -06:00
|
|
|
return ty::mk_struct(st.tcx, did, substs);
|
2012-03-06 10:02:13 -06:00
|
|
|
}
|
2013-09-28 00:38:08 -05:00
|
|
|
c => { error2!("unexpected char in type string: {}", c); fail2!();}
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-01 20:45:37 -05:00
|
|
|
fn parse_mutability(st: &mut PState) -> ast::Mutability {
|
2012-08-06 14:34:08 -05:00
|
|
|
match peek(st) {
|
2013-09-01 20:45:37 -05:00
|
|
|
'm' => { next(st); ast::MutMutable }
|
|
|
|
_ => { ast::MutImmutable }
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
2013-04-02 02:40:57 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_mt(st: &mut PState, conv: conv_did) -> ty::mt {
|
2013-04-02 02:40:57 -05:00
|
|
|
let m = parse_mutability(st);
|
2013-01-14 23:36:27 -06:00
|
|
|
ty::mt { ty: parse_ty(st, conv), mutbl: m }
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_def(st: &mut PState, source: DefIdSource,
|
2013-09-01 20:45:37 -05:00
|
|
|
conv: conv_did) -> ast::DefId {
|
2013-06-07 19:01:30 -05:00
|
|
|
return conv(source, scan(st, |c| { c == '|' }, parse_def_id));
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_uint(st: &mut PState) -> uint {
|
2012-03-15 08:47:03 -05:00
|
|
|
let mut n = 0;
|
2012-03-10 22:34:17 -06:00
|
|
|
loop {
|
2012-02-13 13:55:23 -06:00
|
|
|
let cur = peek(st);
|
2012-08-01 19:30:05 -05:00
|
|
|
if cur < '0' || cur > '9' { return n; }
|
2011-06-27 17:30:17 -05:00
|
|
|
st.pos = st.pos + 1u;
|
|
|
|
n *= 10;
|
2013-04-10 00:45:12 -05:00
|
|
|
n += (cur as uint) - ('0' as uint);
|
2012-03-10 22:34:17 -06:00
|
|
|
};
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_hex(st: &mut PState) -> uint {
|
2012-03-15 08:47:03 -05:00
|
|
|
let mut n = 0u;
|
2012-03-10 22:34:17 -06:00
|
|
|
loop {
|
2012-02-13 13:55:23 -06:00
|
|
|
let cur = peek(st);
|
2012-08-01 19:30:05 -05:00
|
|
|
if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
|
2011-06-27 17:30:17 -05:00
|
|
|
st.pos = st.pos + 1u;
|
|
|
|
n *= 16u;
|
2011-07-27 07:19:39 -05:00
|
|
|
if '0' <= cur && cur <= '9' {
|
2011-06-27 17:30:17 -05:00
|
|
|
n += (cur as uint) - ('0' as uint);
|
|
|
|
} else { n += 10u + (cur as uint) - ('a' as uint); }
|
2012-03-10 22:34:17 -06:00
|
|
|
};
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
2012-05-25 01:44:58 -05:00
|
|
|
fn parse_purity(c: char) -> purity {
|
2012-08-22 19:58:05 -05:00
|
|
|
match c {
|
2012-08-03 21:59:04 -05:00
|
|
|
'u' => unsafe_fn,
|
|
|
|
'i' => impure_fn,
|
2012-08-22 19:58:05 -05:00
|
|
|
'c' => extern_fn,
|
2013-09-28 00:38:08 -05:00
|
|
|
_ => fail2!("parse_purity: bad purity {}", c)
|
2012-05-25 01:44:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_abi_set(st: &mut PState) -> AbiSet {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '[');
|
2013-03-13 21:25:28 -05:00
|
|
|
let mut abis = AbiSet::empty();
|
|
|
|
while peek(st) != ']' {
|
|
|
|
// FIXME(#5422) str API should not force this copy
|
2013-09-05 07:17:24 -05:00
|
|
|
let abi_str = scan(st, |c| c == ',', str::from_utf8);
|
2013-03-13 21:25:28 -05:00
|
|
|
let abi = abi::lookup(abi_str).expect(abi_str);
|
|
|
|
abis.add(abi);
|
2013-01-31 19:12:29 -06:00
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), ']');
|
2013-03-13 21:25:28 -05:00
|
|
|
return abis;
|
2013-01-31 19:12:29 -06:00
|
|
|
}
|
|
|
|
|
2012-11-02 15:33:51 -05:00
|
|
|
fn parse_onceness(c: char) -> ast::Onceness {
|
|
|
|
match c {
|
|
|
|
'o' => ast::Once,
|
|
|
|
'm' => ast::Many,
|
2013-09-28 00:38:08 -05:00
|
|
|
_ => fail2!("parse_onceness: bad onceness")
|
2012-11-02 15:33:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
|
2013-01-31 19:12:29 -06:00
|
|
|
let sigil = parse_sigil(st);
|
2012-05-25 01:44:58 -05:00
|
|
|
let purity = parse_purity(next(st));
|
2012-11-02 15:33:51 -05:00
|
|
|
let onceness = parse_onceness(next(st));
|
2012-11-04 22:41:00 -06:00
|
|
|
let region = parse_region(st);
|
2013-06-21 19:08:35 -05:00
|
|
|
let bounds = parse_bounds(st, |x,y| conv(x,y));
|
|
|
|
let sig = parse_sig(st, |x,y| conv(x,y));
|
2013-01-31 19:12:29 -06:00
|
|
|
ty::ClosureTy {
|
|
|
|
purity: purity,
|
|
|
|
sigil: sigil,
|
|
|
|
onceness: onceness,
|
|
|
|
region: region,
|
2013-05-10 14:57:27 -05:00
|
|
|
bounds: bounds.builtin_bounds,
|
2013-01-31 19:12:29 -06:00
|
|
|
sig: sig
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy {
|
2013-01-31 19:12:29 -06:00
|
|
|
let purity = parse_purity(next(st));
|
2013-03-13 21:25:28 -05:00
|
|
|
let abi = parse_abi_set(st);
|
2013-01-31 19:12:29 -06:00
|
|
|
let sig = parse_sig(st, conv);
|
|
|
|
ty::BareFnTy {
|
|
|
|
purity: purity,
|
2013-03-13 21:25:28 -05:00
|
|
|
abis: abi,
|
2013-01-31 19:12:29 -06:00
|
|
|
sig: sig
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next(st), '[');
|
2013-04-26 21:13:38 -05:00
|
|
|
let mut inputs = ~[];
|
2012-02-13 13:55:23 -06:00
|
|
|
while peek(st) != ']' {
|
2013-06-21 19:08:35 -05:00
|
|
|
inputs.push(parse_ty(st, |x,y| conv(x,y)));
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
st.pos += 1u; // eat the ']'
|
2013-01-08 08:21:19 -06:00
|
|
|
let ret_ty = parse_ty(st, conv);
|
2013-03-27 11:55:18 -05:00
|
|
|
ty::FnSig {bound_lifetime_names: opt_vec::Empty, // FIXME(#4846)
|
|
|
|
inputs: inputs,
|
|
|
|
output: ret_ty}
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Rust metadata parsing
|
2013-09-01 20:45:37 -05:00
|
|
|
pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
|
2012-03-15 08:47:03 -05:00
|
|
|
let mut colon_idx = 0u;
|
2013-05-14 04:52:12 -05:00
|
|
|
let len = buf.len();
|
2011-08-19 17:16:48 -05:00
|
|
|
while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1u; }
|
2011-07-27 07:19:39 -05:00
|
|
|
if colon_idx == len {
|
2013-09-28 00:38:08 -05:00
|
|
|
error2!("didn't find ':' when parsing def id");
|
|
|
|
fail2!();
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
2012-08-17 17:54:18 -05:00
|
|
|
|
2013-06-27 04:48:50 -05:00
|
|
|
let crate_part = buf.slice(0u, colon_idx);
|
|
|
|
let def_part = buf.slice(colon_idx + 1u, len);
|
2011-07-12 12:59:18 -05:00
|
|
|
|
2012-09-14 11:55:33 -05:00
|
|
|
let crate_num = match uint::parse_bytes(crate_part, 10u) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(cn) => cn as int,
|
2013-09-28 00:38:08 -05:00
|
|
|
None => fail2!("internal error: parse_def_id: crate number expected, but found {:?}",
|
2013-05-09 06:52:07 -05:00
|
|
|
crate_part)
|
2012-03-06 10:02:13 -06:00
|
|
|
};
|
2012-09-14 11:55:33 -05:00
|
|
|
let def_num = match uint::parse_bytes(def_part, 10u) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(dn) => dn as int,
|
2013-09-28 00:38:08 -05:00
|
|
|
None => fail2!("internal error: parse_def_id: id expected, but found {:?}",
|
2013-05-09 06:52:07 -05:00
|
|
|
def_part)
|
2012-03-06 10:02:13 -06:00
|
|
|
};
|
2013-09-01 20:45:37 -05:00
|
|
|
ast::DefId { crate: crate_num, node: def_num }
|
2011-06-27 17:30:17 -05:00
|
|
|
}
|
2011-07-19 19:52:34 -05:00
|
|
|
|
2013-06-07 19:24:11 -05:00
|
|
|
pub fn parse_type_param_def_data(data: &[u8], start: uint,
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
crate_num: int, tcx: ty::ctxt,
|
|
|
|
conv: conv_did) -> ty::TypeParameterDef
|
|
|
|
{
|
2013-06-07 19:01:30 -05:00
|
|
|
let mut st = parse_state_from_data(data, crate_num, start, tcx);
|
|
|
|
parse_type_param_def(&mut st, conv)
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef {
|
2013-06-21 12:36:50 -05:00
|
|
|
ty::TypeParameterDef {ident: parse_ident(st, ':'),
|
|
|
|
def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
|
2013-06-21 19:08:35 -05:00
|
|
|
bounds: @parse_bounds(st, |x,y| conv(x,y))}
|
2011-12-28 10:50:12 -06:00
|
|
|
}
|
|
|
|
|
2013-06-07 19:01:30 -05:00
|
|
|
fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
|
2013-05-07 16:30:21 -05:00
|
|
|
let mut param_bounds = ty::ParamBounds {
|
|
|
|
builtin_bounds: ty::EmptyBuiltinBounds(),
|
|
|
|
trait_bounds: ~[]
|
|
|
|
};
|
2012-03-10 22:34:17 -06:00
|
|
|
loop {
|
2013-05-07 16:30:21 -05:00
|
|
|
match next(st) {
|
|
|
|
'S' => {
|
2013-06-05 13:33:14 -05:00
|
|
|
param_bounds.builtin_bounds.add(ty::BoundSend);
|
2013-05-07 16:30:21 -05:00
|
|
|
}
|
|
|
|
'K' => {
|
2013-06-05 16:52:27 -05:00
|
|
|
param_bounds.builtin_bounds.add(ty::BoundFreeze);
|
2013-05-07 16:30:21 -05:00
|
|
|
}
|
|
|
|
'O' => {
|
|
|
|
param_bounds.builtin_bounds.add(ty::BoundStatic);
|
|
|
|
}
|
2013-05-30 19:03:01 -05:00
|
|
|
'Z' => {
|
|
|
|
param_bounds.builtin_bounds.add(ty::BoundSized);
|
|
|
|
}
|
2013-05-07 16:30:21 -05:00
|
|
|
'I' => {
|
2013-06-21 19:08:35 -05:00
|
|
|
param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y)));
|
2013-05-07 16:30:21 -05:00
|
|
|
}
|
|
|
|
'.' => {
|
2013-05-10 14:57:27 -05:00
|
|
|
return param_bounds;
|
2013-05-07 16:30:21 -05:00
|
|
|
}
|
|
|
|
_ => {
|
2013-09-28 00:38:08 -05:00
|
|
|
fail2!("parse_bounds: bad bounds")
|
2013-05-07 16:30:21 -05:00
|
|
|
}
|
|
|
|
}
|
2011-12-28 10:50:12 -06:00
|
|
|
}
|
|
|
|
}
|