use metadata::csearch::StaticMethodInfo;
use metadata::csearch;
use metadata::cstore;
-use metadata::tydecode::{parse_ty_data, parse_def_id,
- parse_type_param_def_data,
+use metadata::tydecode::{parse_ty_data, parse_region_data, parse_def_id,
+ parse_type_param_def_data, parse_bounds_data,
parse_bare_fn_ty_data, parse_trait_ref_data};
-use middle::lang_items;
use middle::def;
+use middle::lang_items;
+use middle::resolve::{TraitItemKind, TypeTraitItemKind};
use middle::subst;
use middle::ty::{ImplContainer, TraitContainer};
use middle::ty;
use middle::typeck;
use middle::astencode::vtable_decoder_helpers;
-use std::gc::Gc;
use std::hash::Hash;
use std::hash;
use std::io::extensions::u64_from_be_bytes;
use syntax::print::pprust;
use syntax::ast;
use syntax::codemap;
+use syntax::ptr::P;
pub type Cmd<'a> = &'a crate_metadata;
}
}
-fn item_method_sort(item: rbml::Doc) -> char {
+fn item_sort(item: rbml::Doc) -> char {
+ // NB(pcwalton): The default of 'r' here is relied upon in
+ // `is_associated_type` below.
let mut ret = 'r';
- reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
+ reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
ret = doc.as_str_slice().as_bytes()[0] as char;
false
});
doc_trait_ref(tp, tcx, cdata)
}
-fn item_ty_param_defs(item: rbml::Doc,
- tcx: &ty::ctxt,
- cdata: Cmd,
- tag: uint)
- -> subst::VecPerParamSpace<ty::TypeParameterDef> {
- let mut bounds = subst::VecPerParamSpace::empty();
- reader::tagged_docs(item, tag, |p| {
- let bd = parse_type_param_def_data(
- p.data, p.start, cdata.cnum, tcx,
- |_, did| translate_def_id(cdata, did));
- bounds.push(bd.space, bd);
- true
- });
- bounds
+fn doc_bounds(doc: rbml::Doc, tcx: &ty::ctxt, cdata: Cmd) -> ty::ParamBounds {
+ parse_bounds_data(doc.data, cdata.cnum, doc.start, tcx,
+ |_, did| translate_def_id(cdata, did))
}
-fn item_region_param_defs(item_doc: rbml::Doc, cdata: Cmd)
- -> subst::VecPerParamSpace<ty::RegionParameterDef>
-{
- let mut v = subst::VecPerParamSpace::empty();
- reader::tagged_docs(item_doc, tag_region_param_def, |rp_doc| {
- let ident_str_doc = reader::get_doc(rp_doc,
- tag_region_param_def_ident);
- let ident = item_name(&*token::get_ident_interner(), ident_str_doc);
- let def_id_doc = reader::get_doc(rp_doc,
- tag_region_param_def_def_id);
- let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
- let def_id = translate_def_id(cdata, def_id);
-
- let doc = reader::get_doc(rp_doc, tag_region_param_def_space);
- let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as uint);
-
- let doc = reader::get_doc(rp_doc, tag_region_param_def_index);
- let index = reader::doc_as_u64(doc) as uint;
-
- v.push(space, ty::RegionParameterDef { name: ident.name,
- def_id: def_id,
- space: space,
- index: index });
- true
- });
- v
+fn trait_def_bounds(doc: rbml::Doc, tcx: &ty::ctxt, cdata: Cmd) -> ty::ParamBounds {
+ let d = reader::get_doc(doc, tag_trait_def_bounds);
+ doc_bounds(d, tcx, cdata)
}
fn enum_variant_ids(item: rbml::Doc, cdata: Cmd) -> Vec<ast::DefId> {
UnsafeFn => DlDef(def::DefFn(did, ast::UnsafeFn)),
Fn => DlDef(def::DefFn(did, ast::NormalFn)),
StaticMethod | UnsafeStaticMethod => {
- let fn_style = if fam == UnsafeStaticMethod { ast::UnsafeFn } else
- { ast::NormalFn };
+ let fn_style = if fam == UnsafeStaticMethod {
+ ast::UnsafeFn
+ } else {
+ ast::NormalFn
+ };
// def_static_method carries an optional field of its enclosing
// trait or enclosing impl (if this is an inherent static method).
// So we need to detect whether this is in a trait or not, which
// we do through the mildly hacky way of checking whether there is
- // a trait_method_sort.
+ // a trait_parent_sort.
let provenance = if reader::maybe_get_doc(
- item, tag_item_trait_method_sort).is_some() {
+ item, tag_item_trait_parent_sort).is_some() {
def::FromTrait(item_reqd_and_translated_parent_item(cnum,
item))
} else {
};
DlDef(def::DefStaticMethod(did, provenance, fn_style))
}
- Type | ForeignType => DlDef(def::DefTy(did)),
+ Type | ForeignType => DlDef(def::DefTy(did, false)),
Mod => DlDef(def::DefMod(did)),
ForeignMod => DlDef(def::DefForeignMod(did)),
StructVariant => {
DlDef(def::DefVariant(enum_did, did, false))
}
Trait => DlDef(def::DefTrait(did)),
- Enum => DlDef(def::DefTy(did)),
+ Enum => DlDef(def::DefTy(did, true)),
Impl => DlImpl(did),
PublicField | InheritedField => DlField,
}
tcx: &ty::ctxt) -> ty::TraitDef
{
let item_doc = lookup_item(item_id, cdata.data());
- let tp_defs = item_ty_param_defs(item_doc, tcx, cdata,
- tag_items_data_item_ty_param_bounds);
- let rp_defs = item_region_param_defs(item_doc, cdata);
- let mut bounds = ty::empty_builtin_bounds();
- // Collect the builtin bounds from the encoded supertraits.
- // FIXME(#8559): They should be encoded directly.
- reader::tagged_docs(item_doc, tag_item_super_trait_ref, |trait_doc| {
- // NB. Bypasses real supertraits. See get_supertraits() if you wanted them.
- let trait_ref = doc_trait_ref(trait_doc, tcx, cdata);
- tcx.lang_items.to_builtin_kind(trait_ref.def_id).map(|bound| {
- bounds.add(bound);
- });
- true
- });
+ let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
+ let bounds = trait_def_bounds(item_doc, tcx, cdata);
ty::TraitDef {
- generics: ty::Generics {types: tp_defs,
- regions: rp_defs},
+ generics: generics,
bounds: bounds,
trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata))
}
let t = item_type(ast::DefId { krate: cdata.cnum, node: id }, item, tcx,
cdata);
- let tp_defs = item_ty_param_defs(item, tcx, cdata, tag_items_data_item_ty_param_bounds);
- let rp_defs = item_region_param_defs(item, cdata);
+ let generics = doc_generics(item, tcx, cdata, tag_item_generics);
ty::Polytype {
- generics: ty::Generics {types: tp_defs,
- regions: rp_defs},
+ generics: generics,
ty: t
}
}
None => {}
Some(inherent_impl_doc) => {
let _ = reader::tagged_docs(inherent_impl_doc,
- tag_item_impl_method,
- |impl_method_def_id_doc| {
- let impl_method_def_id =
- reader::with_doc_data(impl_method_def_id_doc,
- parse_def_id);
- let impl_method_def_id =
- translate_def_id(cdata, impl_method_def_id);
- match maybe_find_item(impl_method_def_id.node, items) {
+ tag_item_impl_item,
+ |impl_item_def_id_doc| {
+ let impl_item_def_id = item_def_id(impl_item_def_id_doc,
+ cdata);
+ match maybe_find_item(impl_item_def_id.node, items) {
None => {}
Some(impl_method_doc) => {
match item_family(impl_method_doc) {
item_name(&*intr, impl_method_doc);
let static_method_def_like =
item_to_def_like(impl_method_doc,
- impl_method_def_id,
+ impl_item_def_id,
cdata.cnum);
callback(static_method_def_like,
static_method_name,
item_path(lookup_item(id, cdata.data()))
}
-pub type DecodeInlinedItem<'a> = |cdata: Cmd,
- tcx: &ty::ctxt,
- path: Vec<ast_map::PathElem>,
- par_doc: rbml::Doc|: 'a
- -> Result<ast::InlinedItem, Vec<ast_map::PathElem> >;
+pub type DecodeInlinedItem<'a> = <'tcx> |cdata: Cmd,
+ tcx: &ty::ctxt<'tcx>,
+ path: Vec<ast_map::PathElem>,
+ par_doc: rbml::Doc|: 'a
+ -> Result<&'tcx ast::InlinedItem,
+ Vec<ast_map::PathElem>>;
-pub fn maybe_get_item_ast(cdata: Cmd, tcx: &ty::ctxt, id: ast::NodeId,
- decode_inlined_item: DecodeInlinedItem)
- -> csearch::found_ast {
+pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeId,
+ decode_inlined_item: DecodeInlinedItem)
+ -> csearch::found_ast<'tcx> {
debug!("Looking up item: {}", id);
let item_doc = lookup_item(id, cdata.data());
let path = Vec::from_slice(item_path(item_doc).init());
match decode_inlined_item(cdata, tcx, path, item_doc) {
- Ok(ref ii) => csearch::found(*ii),
+ Ok(ii) => csearch::found(ii),
Err(path) => {
match item_parent_item(item_doc) {
Some(did) => {
let did = translate_def_id(cdata, did);
let parent_item = lookup_item(did.node, cdata.data());
match decode_inlined_item(cdata, tcx, path, parent_item) {
- Ok(ref ii) => csearch::found_parent(did, *ii),
+ Ok(ii) => csearch::found_parent(did, ii),
Err(_) => csearch::not_found
}
}
}
}
-/// Returns information about the given implementation.
-pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
- let mut methods = Vec::new();
+/// Returns the def IDs of all the items in the given implementation.
+pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
+ -> Vec<ty::ImplOrTraitItemId> {
+ let mut impl_items = Vec::new();
reader::tagged_docs(lookup_item(impl_id, cdata.data()),
- tag_item_impl_method, |doc| {
- let m_did = reader::with_doc_data(doc, parse_def_id);
- methods.push(translate_def_id(cdata, m_did));
+ tag_item_impl_item, |doc| {
+ let def_id = item_def_id(doc, cdata);
+ match item_sort(doc) {
+ 'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
+ 't' => impl_items.push(ty::TypeTraitItemId(def_id)),
+ _ => fail!("unknown impl item sort"),
+ }
true
});
- methods
+ impl_items
}
-pub fn get_method_name_and_explicit_self(intr: Rc<IdentInterner>,
- cdata: Cmd,
- id: ast::NodeId)
- -> (ast::Ident,
- ty::ExplicitSelfCategory) {
- let method_doc = lookup_item(id, cdata.data());
- let name = item_name(&*intr, method_doc);
- let explicit_self = get_explicit_self(method_doc);
- (name, explicit_self)
+pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
+ cdata: Cmd,
+ id: ast::NodeId)
+ -> (ast::Ident, TraitItemKind) {
+ let doc = lookup_item(id, cdata.data());
+ let name = item_name(&*intr, doc);
+ match item_sort(doc) {
+ 'r' | 'p' => {
+ let explicit_self = get_explicit_self(doc);
+ (name, TraitItemKind::from_explicit_self_category(explicit_self))
+ }
+ 't' => (name, TypeTraitItemKind),
+ c => {
+ fail!("get_trait_item_name_and_kind(): unknown trait item kind \
+ in metadata: `{}`", c)
+ }
+ }
}
-pub fn get_method(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
- tcx: &ty::ctxt) -> ty::Method
-{
+pub fn get_impl_or_trait_item(intr: Rc<IdentInterner>,
+ cdata: Cmd,
+ id: ast::NodeId,
+ tcx: &ty::ctxt)
+ -> ty::ImplOrTraitItem {
let method_doc = lookup_item(id, cdata.data());
+
let def_id = item_def_id(method_doc, cdata);
let container_id = item_reqd_and_translated_parent_item(cdata.cnum,
};
let name = item_name(&*intr, method_doc);
- let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
- tag_item_method_tps);
- let rp_defs = item_region_param_defs(method_doc, cdata);
- let fty = doc_method_fty(method_doc, tcx, cdata);
let vis = item_visibility(method_doc);
- let explicit_self = get_explicit_self(method_doc);
- let provided_source = get_provided_source(method_doc, cdata);
-
- ty::Method::new(
- name,
- ty::Generics {
- types: type_param_defs,
- regions: rp_defs,
- },
- fty,
- explicit_self,
- vis,
- def_id,
- container,
- provided_source
- )
-}
-
-pub fn get_trait_method_def_ids(cdata: Cmd,
- id: ast::NodeId) -> Vec<ast::DefId> {
+
+ match item_sort(method_doc) {
+ 'r' | 'p' => {
+ let generics = doc_generics(method_doc, tcx, cdata,
+ tag_method_ty_generics);
+ let fty = doc_method_fty(method_doc, tcx, cdata);
+ let explicit_self = get_explicit_self(method_doc);
+ let provided_source = get_provided_source(method_doc, cdata);
+
+ ty::MethodTraitItem(Rc::new(ty::Method::new(name,
+ generics,
+ fty,
+ explicit_self,
+ vis,
+ def_id,
+ container,
+ provided_source)))
+ }
+ 't' => {
+ ty::TypeTraitItem(Rc::new(ty::AssociatedType {
+ ident: name,
+ vis: vis,
+ def_id: def_id,
+ container: container,
+ }))
+ }
+ _ => fail!("unknown impl/trait item sort"),
+ }
+}
+
+pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
+ -> Vec<ty::ImplOrTraitItemId> {
let data = cdata.data();
let item = lookup_item(id, data);
let mut result = Vec::new();
- reader::tagged_docs(item, tag_item_trait_method, |mth| {
- result.push(item_def_id(mth, cdata));
+ reader::tagged_docs(item, tag_item_trait_item, |mth| {
+ let def_id = item_def_id(mth, cdata);
+ match item_sort(mth) {
+ 'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
+ 't' => result.push(ty::TypeTraitItemId(def_id)),
+ _ => fail!("unknown trait item sort"),
+ }
true
});
result
Decodable::decode(&mut decoder).unwrap()
}
-pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
- id: ast::NodeId, tcx: &ty::ctxt)
+pub fn get_provided_trait_methods(intr: Rc<IdentInterner>,
+ cdata: Cmd,
+ id: ast::NodeId,
+ tcx: &ty::ctxt)
-> Vec<Rc<ty::Method>> {
let data = cdata.data();
let item = lookup_item(id, data);
let mut result = Vec::new();
- reader::tagged_docs(item, tag_item_trait_method, |mth_id| {
+ reader::tagged_docs(item, tag_item_trait_item, |mth_id| {
let did = item_def_id(mth_id, cdata);
let mth = lookup_item(did.node, data);
- if item_method_sort(mth) == 'p' {
- result.push(Rc::new(get_method(intr.clone(), cdata, did.node, tcx)));
+ if item_sort(mth) == 'p' {
+ let trait_item = get_impl_or_trait_item(intr.clone(),
+ cdata,
+ did.node,
+ tcx);
+ match trait_item {
+ ty::MethodTraitItem(ref method) => {
+ result.push((*method).clone())
+ }
+ ty::TypeTraitItem(_) => {}
+ }
}
true
});
if !ret { return None }
let mut impl_method_ids = Vec::new();
- reader::tagged_docs(item, tag_item_impl_method, |impl_method_doc| {
- impl_method_ids.push(reader::with_doc_data(impl_method_doc, parse_def_id));
+ reader::tagged_docs(item, tag_item_impl_item, |impl_method_doc| {
+ impl_method_ids.push(item_def_id(impl_method_doc, cdata));
true
});
result
}
-fn get_meta_items(md: rbml::Doc) -> Vec<Gc<ast::MetaItem>> {
- let mut items: Vec<Gc<ast::MetaItem>> = Vec::new();
+fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
+ let mut items: Vec<P<ast::MetaItem>> = Vec::new();
reader::tagged_docs(md, tag_meta_item_word, |meta_item_doc| {
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
let n = token::intern_and_get_ident(nd.as_str_slice());
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
let n = token::intern_and_get_ident(nd.as_str_slice());
let subitems = get_meta_items(meta_item_doc);
- items.push(attr::mk_list_item(n, subitems.move_iter().collect()));
+ items.push(attr::mk_list_item(n, subitems.into_iter().collect()));
true
});
return items;
// Currently it's only possible to have a single meta item on
// an attribute
assert_eq!(meta_items.len(), 1u);
- let meta_item = *meta_items.get(0);
+ let meta_item = meta_items.into_iter().nth(0).unwrap();
attrs.push(
codemap::Spanned {
node: ast::Attribute_ {
});
}
-pub fn get_trait_of_method(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
- -> Option<ast::DefId> {
+pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
+ -> Option<ast::DefId> {
let item_doc = lookup_item(id, cdata.data());
let parent_item_id = match item_parent_item(item_doc) {
None => return None,
_ => false,
}
}
+
+fn doc_generics(base_doc: rbml::Doc,
+ tcx: &ty::ctxt,
+ cdata: Cmd,
+ tag: uint)
+ -> ty::Generics
+{
+ let doc = reader::get_doc(base_doc, tag);
+
+ let mut types = subst::VecPerParamSpace::empty();
+ reader::tagged_docs(doc, tag_type_param_def, |p| {
+ let bd = parse_type_param_def_data(
+ p.data, p.start, cdata.cnum, tcx,
+ |_, did| translate_def_id(cdata, did));
+ types.push(bd.space, bd);
+ true
+ });
+
+ let mut regions = subst::VecPerParamSpace::empty();
+ reader::tagged_docs(doc, tag_region_param_def, |rp_doc| {
+ let ident_str_doc = reader::get_doc(rp_doc,
+ tag_region_param_def_ident);
+ let ident = item_name(&*token::get_ident_interner(), ident_str_doc);
+ let def_id_doc = reader::get_doc(rp_doc,
+ tag_region_param_def_def_id);
+ let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
+ let def_id = translate_def_id(cdata, def_id);
+
+ let doc = reader::get_doc(rp_doc, tag_region_param_def_space);
+ let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as uint);
+
+ let doc = reader::get_doc(rp_doc, tag_region_param_def_index);
+ let index = reader::doc_as_u64(doc) as uint;
+
+ let mut bounds = Vec::new();
+ reader::tagged_docs(rp_doc, tag_items_data_region, |p| {
+ bounds.push(
+ parse_region_data(
+ p.data, cdata.cnum, p.start, tcx,
+ |_, did| translate_def_id(cdata, did)));
+ true
+ });
+
+ regions.push(space, ty::RegionParameterDef { name: ident.name,
+ def_id: def_id,
+ space: space,
+ index: index,
+ bounds: bounds });
+
+ true
+ });
+
+ ty::Generics { types: types, regions: regions }
+}
+
+pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
+ let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
+ match maybe_find_item(id, items) {
+ None => false,
+ Some(item) => item_sort(item) == 't',
+ }
+}
+