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.
|
|
|
|
|
2011-07-08 01:29:09 -05:00
|
|
|
// Decoding metadata from a single crate's metadata
|
2011-06-27 18:03:01 -05:00
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
use metadata::cstore::crate_metadata;
|
2012-12-13 15:05:22 -06:00
|
|
|
use metadata::common::*;
|
|
|
|
use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
|
2012-12-23 16:41:37 -06:00
|
|
|
use metadata::csearch;
|
|
|
|
use metadata::cstore;
|
|
|
|
use metadata::decoder;
|
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
|
|
|
use metadata::tydecode::{parse_ty_data, parse_def_id,
|
|
|
|
parse_type_param_def_data,
|
2013-03-27 05:16:28 -05:00
|
|
|
parse_bare_fn_ty_data, parse_trait_ref_data};
|
2013-02-19 01:40:42 -06:00
|
|
|
use middle::{ty, resolve};
|
2012-12-13 15:05:22 -06:00
|
|
|
|
2013-03-26 15:38:07 -05:00
|
|
|
use core::hash::HashUtil;
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::int;
|
2013-03-01 12:44:43 -06:00
|
|
|
use core::io::WriterUtil;
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::io;
|
|
|
|
use core::option;
|
|
|
|
use core::str;
|
|
|
|
use core::vec;
|
|
|
|
use std::ebml::reader;
|
2012-10-07 18:33:20 -05:00
|
|
|
use std::ebml;
|
2012-12-19 18:08:48 -06:00
|
|
|
use std::serialize::Decodable;
|
2012-09-04 13:54:36 -05:00
|
|
|
use syntax::ast_map;
|
2012-12-13 15:05:22 -06:00
|
|
|
use syntax::attr;
|
2012-09-04 13:54:36 -05:00
|
|
|
use syntax::diagnostic::span_handler;
|
2013-04-02 18:20:02 -05:00
|
|
|
use syntax::parse::token::{StringRef, ident_interner, special_idents};
|
2012-12-13 15:05:22 -06:00
|
|
|
use syntax::print::pprust;
|
|
|
|
use syntax::{ast, ast_util};
|
2013-01-30 11:56:33 -06:00
|
|
|
use syntax::codemap;
|
2011-06-27 17:53:27 -05:00
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
type cmd = @crate_metadata;
|
|
|
|
|
2011-07-08 16:53:25 -05:00
|
|
|
// A function that takes a def_id relative to the crate being searched and
|
|
|
|
// returns a def_id relative to the compilation environment, i.e. if we hit a
|
|
|
|
// def_id for an item defined in another crate, somebody needs to figure out
|
|
|
|
// what crate that's in and give us a def_id that makes sense for the current
|
|
|
|
// build.
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2013-03-07 16:38:38 -06:00
|
|
|
fn lookup_hash(d: ebml::Doc, eq_fn: &fn(x:&[u8]) -> bool, hash: uint) ->
|
2012-10-07 18:33:20 -05:00
|
|
|
Option<ebml::Doc> {
|
2012-12-06 18:13:54 -06:00
|
|
|
let index = reader::get_doc(d, tag_index);
|
|
|
|
let table = reader::get_doc(index, tag_index_table);
|
2011-07-27 07:19:39 -05:00
|
|
|
let hash_pos = table.start + hash % 256u * 4u;
|
2012-02-14 17:21:53 -06:00
|
|
|
let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4u) as uint;
|
2012-12-06 18:13:54 -06:00
|
|
|
let tagged_doc = reader::doc_at(d.data, pos);
|
2011-06-27 17:53:27 -05:00
|
|
|
|
2011-07-27 07:19:39 -05:00
|
|
|
let belt = tag_index_buckets_bucket_elt;
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(tagged_doc.doc, belt) |elt| {
|
2012-02-14 17:21:53 -06:00
|
|
|
let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4u) as uint;
|
2013-02-08 13:28:20 -06:00
|
|
|
if eq_fn(vec::slice(*elt.data, elt.start + 4u, elt.end)) {
|
2012-12-06 18:13:54 -06:00
|
|
|
return Some(reader::doc_at(d.data, pos).doc);
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
2011-10-21 05:31:48 -05:00
|
|
|
};
|
2012-08-20 14:23:37 -05:00
|
|
|
None
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2013-03-25 15:21:04 -05:00
|
|
|
pub type GetCrateDataCb<'self> = &'self fn(ast::crate_num) -> cmd;
|
2012-11-08 18:52:21 -06:00
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn maybe_find_item(item_id: int, items: ebml::Doc) -> Option<ebml::Doc> {
|
2012-07-03 18:37:38 -05:00
|
|
|
fn eq_item(bytes: &[u8], item_id: int) -> bool {
|
2013-02-08 13:28:20 -06:00
|
|
|
return io::u64_from_be_bytes(
|
|
|
|
vec::slice(bytes, 0u, 4u), 0u, 4u) as int
|
2012-07-03 18:37:38 -05:00
|
|
|
== item_id;
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
2012-07-26 15:43:27 -05:00
|
|
|
lookup_hash(items,
|
|
|
|
|a| eq_item(a, item_id),
|
2012-09-19 15:13:24 -05:00
|
|
|
item_id.hash() as uint)
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn find_item(item_id: int, items: ebml::Doc) -> ebml::Doc {
|
2012-09-21 21:37:57 -05:00
|
|
|
return maybe_find_item(item_id, items).get();
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
// Looks up an item in the given metadata and returns an ebml doc pointing
|
2011-06-27 17:53:27 -05:00
|
|
|
// to the item data.
|
2012-10-07 18:33:20 -05:00
|
|
|
fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc {
|
2012-12-06 18:13:54 -06:00
|
|
|
let items = reader::get_doc(reader::Doc(data), tag_items);
|
2012-08-06 14:34:08 -05:00
|
|
|
match maybe_find_item(item_id, items) {
|
2013-02-11 21:26:38 -06:00
|
|
|
None => fail!(fmt!("lookup_item: id not found: %d", item_id)),
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(d) => d
|
2012-03-06 10:02:13 -06:00
|
|
|
}
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2013-03-20 10:40:02 -05:00
|
|
|
#[deriving(Eq)]
|
2012-08-22 19:58:05 -05:00
|
|
|
enum Family {
|
|
|
|
Const, // c
|
|
|
|
Fn, // f
|
|
|
|
UnsafeFn, // u
|
|
|
|
PureFn, // p
|
|
|
|
StaticMethod, // F
|
|
|
|
UnsafeStaticMethod, // U
|
|
|
|
PureStaticMethod, // P
|
|
|
|
ForeignFn, // e
|
|
|
|
Type, // y
|
|
|
|
ForeignType, // T
|
|
|
|
Mod, // m
|
|
|
|
ForeignMod, // n
|
|
|
|
Enum, // t
|
|
|
|
Variant, // v
|
|
|
|
Impl, // i
|
|
|
|
Trait, // I
|
|
|
|
Struct, // S
|
|
|
|
PublicField, // g
|
|
|
|
PrivateField, // j
|
|
|
|
InheritedField // N
|
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_family(item: ebml::Doc) -> Family {
|
2012-12-06 18:13:54 -06:00
|
|
|
let fam = reader::get_doc(item, tag_items_data_item_family);
|
|
|
|
match reader::doc_as_u8(fam) as char {
|
2012-08-22 19:58:05 -05:00
|
|
|
'c' => Const,
|
|
|
|
'f' => Fn,
|
|
|
|
'u' => UnsafeFn,
|
|
|
|
'p' => PureFn,
|
|
|
|
'F' => StaticMethod,
|
|
|
|
'U' => UnsafeStaticMethod,
|
|
|
|
'P' => PureStaticMethod,
|
|
|
|
'e' => ForeignFn,
|
|
|
|
'y' => Type,
|
|
|
|
'T' => ForeignType,
|
|
|
|
'm' => Mod,
|
|
|
|
'n' => ForeignMod,
|
|
|
|
't' => Enum,
|
|
|
|
'v' => Variant,
|
|
|
|
'i' => Impl,
|
|
|
|
'I' => Trait,
|
|
|
|
'S' => Struct,
|
|
|
|
'g' => PublicField,
|
|
|
|
'j' => PrivateField,
|
|
|
|
'N' => InheritedField,
|
2013-02-11 21:26:38 -06:00
|
|
|
c => fail!(fmt!("unexpected family char: %c", c))
|
2012-08-22 19:58:05 -05:00
|
|
|
}
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2013-02-27 15:45:37 -06:00
|
|
|
fn item_visibility(item: ebml::Doc) -> ast::visibility {
|
2013-03-20 16:38:57 -05:00
|
|
|
match reader::maybe_get_doc(item, tag_items_data_item_visibility) {
|
|
|
|
None => ast::public,
|
|
|
|
Some(visibility_doc) => {
|
|
|
|
match reader::doc_as_u8(visibility_doc) as char {
|
|
|
|
'y' => ast::public,
|
|
|
|
'n' => ast::private,
|
|
|
|
'i' => ast::inherited,
|
|
|
|
_ => fail!(~"unknown visibility character")
|
|
|
|
}
|
|
|
|
}
|
2013-02-27 15:45:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-08 14:39:30 -05:00
|
|
|
fn item_method_sort(item: ebml::Doc) -> char {
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, tag_item_trait_method_sort) |doc| {
|
|
|
|
return str::from_bytes(reader::doc_data(doc))[0] as char;
|
2012-10-08 14:39:30 -05:00
|
|
|
}
|
|
|
|
return 'r';
|
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_symbol(item: ebml::Doc) -> ~str {
|
2012-12-06 18:13:54 -06:00
|
|
|
let sym = reader::get_doc(item, tag_items_data_item_symbol);
|
|
|
|
return str::from_bytes(reader::doc_data(sym));
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(d, tag_items_data_parent_item) |did| {
|
|
|
|
return Some(reader::with_doc_data(did, |d| parse_def_id(d)));
|
2012-03-08 16:13:57 -06:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-10-18 15:29:34 -05:00
|
|
|
fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) ->
|
|
|
|
Option<ast::def_id> {
|
|
|
|
let trait_did_opt = item_parent_item(d);
|
2013-01-13 13:05:40 -06:00
|
|
|
do trait_did_opt.map |trait_did| {
|
|
|
|
ast::def_id { crate: cnum, node: trait_did.node }
|
|
|
|
}
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
|
|
|
|
2012-10-12 19:00:08 -05:00
|
|
|
fn item_reqd_and_translated_parent_item(cnum: ast::crate_num,
|
|
|
|
d: ebml::Doc) -> ast::def_id {
|
|
|
|
let trait_did = item_parent_item(d).expect(~"item without parent");
|
2013-01-13 13:05:40 -06:00
|
|
|
ast::def_id { crate: cnum, node: trait_did.node }
|
2012-10-12 19:00:08 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id {
|
2012-12-06 18:13:54 -06:00
|
|
|
let tagdoc = reader::get_doc(d, tag_def_id);
|
|
|
|
return translate_def_id(cdata, reader::with_doc_data(tagdoc,
|
2012-07-03 19:11:39 -05:00
|
|
|
|d| parse_def_id(d)));
|
2012-03-06 10:02:13 -06:00
|
|
|
}
|
|
|
|
|
2013-03-07 16:38:38 -06:00
|
|
|
fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) {
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| {
|
2012-08-17 14:41:34 -05:00
|
|
|
if !f(reexport_doc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn variant_disr_val(d: ebml::Doc) -> Option<int> {
|
2013-03-16 14:49:12 -05:00
|
|
|
do reader::maybe_get_doc(d, tag_disr_val).chain |val_doc| {
|
2012-12-06 18:13:54 -06:00
|
|
|
int::parse_bytes(reader::doc_data(val_doc), 10u)
|
2012-01-10 15:50:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
|
2012-12-06 18:13:54 -06:00
|
|
|
let tp = reader::get_doc(doc, tag_items_data_item_type);
|
2013-01-17 08:13:26 -06:00
|
|
|
parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
|
|
|
|
|_, did| translate_def_id(cdata, did))
|
2012-01-05 06:57:27 -06:00
|
|
|
}
|
|
|
|
|
2013-03-27 09:26:57 -05:00
|
|
|
fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy {
|
|
|
|
let tp = reader::get_doc(doc, tag_item_method_fty);
|
|
|
|
parse_bare_fn_ty_data(tp.data, cdata.cnum, tp.start, tcx,
|
|
|
|
|_, did| translate_def_id(cdata, did))
|
|
|
|
}
|
|
|
|
|
2013-03-29 15:02:55 -05:00
|
|
|
fn doc_transformed_self_ty(doc: ebml::Doc,
|
|
|
|
tcx: ty::ctxt,
|
|
|
|
cdata: cmd) -> Option<ty::t>
|
|
|
|
{
|
|
|
|
do reader::maybe_get_doc(doc, tag_item_method_transformed_self_ty).map |tp| {
|
|
|
|
parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
|
|
|
|
|_, did| translate_def_id(cdata, did))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-15 14:24:24 -05:00
|
|
|
pub fn item_type(_item_id: ast::def_id, item: ebml::Doc,
|
|
|
|
tcx: ty::ctxt, cdata: cmd) -> ty::t {
|
2013-04-02 15:41:18 -05:00
|
|
|
doc_type(item, tcx, cdata)
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2013-03-27 05:16:28 -05:00
|
|
|
fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef {
|
|
|
|
parse_trait_ref_data(doc.data, cdata.cnum, doc.start, tcx,
|
|
|
|
|_, did| translate_def_id(cdata, did))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn item_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef {
|
|
|
|
let tp = reader::get_doc(doc, tag_item_trait_ref);
|
|
|
|
doc_trait_ref(tp, tcx, cdata)
|
2012-01-05 03:57:19 -06:00
|
|
|
}
|
|
|
|
|
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
|
|
|
fn item_ty_param_defs(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd,
|
|
|
|
tag: uint)
|
|
|
|
-> @~[ty::TypeParameterDef] {
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut bounds = ~[];
|
2013-03-27 09:26:57 -05:00
|
|
|
for reader::tagged_docs(item, tag) |p| {
|
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
|
|
|
let bd = parse_type_param_def_data(
|
|
|
|
p.data, p.start, cdata.cnum, tcx,
|
|
|
|
|_, did| translate_def_id(cdata, did));
|
2012-09-26 19:33:34 -05:00
|
|
|
bounds.push(bd);
|
2011-12-28 10:50:12 -06:00
|
|
|
}
|
2012-01-02 05:09:26 -06:00
|
|
|
@bounds
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_ty_region_param(item: ebml::Doc) -> Option<ty::region_variance> {
|
2012-12-06 18:13:54 -06:00
|
|
|
reader::maybe_get_doc(item, tag_region_param).map(|doc| {
|
2013-05-01 19:54:54 -05:00
|
|
|
let mut decoder = reader::Decoder(*doc);
|
|
|
|
Decodable::decode(&mut decoder)
|
2012-08-09 11:59:50 -05:00
|
|
|
})
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_ty_param_count(item: ebml::Doc) -> uint {
|
2012-03-15 08:47:03 -05:00
|
|
|
let mut n = 0u;
|
2012-12-06 18:13:54 -06:00
|
|
|
reader::tagged_docs(item, tag_items_data_item_ty_param_bounds,
|
2012-07-26 15:43:27 -05:00
|
|
|
|_p| { n += 1u; true } );
|
2011-12-16 07:41:12 -06:00
|
|
|
n
|
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn enum_variant_ids(item: ebml::Doc, cdata: cmd) -> ~[ast::def_id] {
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut ids: ~[ast::def_id] = ~[];
|
2011-07-27 07:19:39 -05:00
|
|
|
let v = tag_items_data_item_variant;
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, v) |p| {
|
|
|
|
let ext = reader::with_doc_data(p, |d| parse_def_id(d));
|
2013-01-13 13:05:40 -06:00
|
|
|
ids.push(ast::def_id { crate: cdata.cnum, node: ext.node });
|
2011-10-21 05:31:48 -05:00
|
|
|
};
|
2012-08-01 19:30:05 -05:00
|
|
|
return ids;
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path {
|
2012-12-06 18:13:54 -06:00
|
|
|
let path_doc = reader::get_doc(item_doc, tag_path);
|
2012-02-10 08:01:32 -06:00
|
|
|
|
2012-12-06 18:13:54 -06:00
|
|
|
let len_doc = reader::get_doc(path_doc, tag_path_len);
|
|
|
|
let len = reader::doc_as_u32(len_doc) as uint;
|
2012-02-10 08:01:32 -06:00
|
|
|
|
2012-09-21 20:43:30 -05:00
|
|
|
let mut result = vec::with_capacity(len);
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::docs(path_doc) |tag, elt_doc| {
|
2012-02-10 08:01:32 -06:00
|
|
|
if tag == tag_path_elt_mod {
|
2012-12-06 18:13:54 -06:00
|
|
|
let str = reader::doc_as_str(elt_doc);
|
2012-09-26 19:33:34 -05:00
|
|
|
result.push(ast_map::path_mod(intr.intern(@str)));
|
2012-02-10 08:01:32 -06:00
|
|
|
} else if tag == tag_path_elt_name {
|
2012-12-06 18:13:54 -06:00
|
|
|
let str = reader::doc_as_str(elt_doc);
|
2012-09-26 19:33:34 -05:00
|
|
|
result.push(ast_map::path_name(intr.intern(@str)));
|
2012-02-10 08:01:32 -06:00
|
|
|
} else {
|
|
|
|
// ignore tag_path_len element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-01 19:30:05 -05:00
|
|
|
return result;
|
2012-02-10 08:01:32 -06:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident {
|
2012-12-06 18:13:54 -06:00
|
|
|
let name = reader::get_doc(item, tag_paths_data_name);
|
2013-04-02 18:20:02 -05:00
|
|
|
do reader::with_doc_data(name) |data| {
|
|
|
|
let string = str::from_bytes_slice(data);
|
|
|
|
match intr.find_equiv(&StringRef(string)) {
|
|
|
|
None => intr.intern(@(string.to_owned())),
|
|
|
|
Some(val) => val,
|
|
|
|
}
|
|
|
|
}
|
2011-12-16 07:41:12 -06:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
|
2012-10-12 19:00:08 -05:00
|
|
|
-> def_like
|
|
|
|
{
|
2012-08-22 19:58:05 -05:00
|
|
|
let fam = item_family(item);
|
|
|
|
match fam {
|
2012-10-12 19:00:08 -05:00
|
|
|
Const => dl_def(ast::def_const(did)),
|
2012-12-10 15:47:54 -06:00
|
|
|
Struct => dl_def(ast::def_struct(did)),
|
2012-10-12 19:00:08 -05:00
|
|
|
UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)),
|
|
|
|
Fn => dl_def(ast::def_fn(did, ast::impure_fn)),
|
|
|
|
PureFn => dl_def(ast::def_fn(did, ast::pure_fn)),
|
|
|
|
ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)),
|
|
|
|
UnsafeStaticMethod => {
|
2012-10-18 15:29:34 -05:00
|
|
|
let trait_did_opt = translated_parent_item_opt(cnum, item);
|
|
|
|
dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn))
|
2012-10-12 19:00:08 -05:00
|
|
|
}
|
|
|
|
StaticMethod => {
|
2012-10-18 15:29:34 -05:00
|
|
|
let trait_did_opt = translated_parent_item_opt(cnum, item);
|
|
|
|
dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn))
|
2012-10-12 19:00:08 -05:00
|
|
|
}
|
|
|
|
PureStaticMethod => {
|
2012-10-18 15:29:34 -05:00
|
|
|
let trait_did_opt = translated_parent_item_opt(cnum, item);
|
|
|
|
dl_def(ast::def_static_method(did, trait_did_opt, ast::pure_fn))
|
2012-10-12 19:00:08 -05:00
|
|
|
}
|
|
|
|
Type | ForeignType => dl_def(ast::def_ty(did)),
|
|
|
|
Mod => dl_def(ast::def_mod(did)),
|
|
|
|
ForeignMod => dl_def(ast::def_foreign_mod(did)),
|
|
|
|
Variant => {
|
|
|
|
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
|
|
|
|
dl_def(ast::def_variant(enum_did, did))
|
|
|
|
}
|
2013-03-27 09:26:57 -05:00
|
|
|
Trait => dl_def(ast::def_trait(did)),
|
|
|
|
Enum => dl_def(ast::def_ty(did)),
|
2012-10-12 19:00:08 -05:00
|
|
|
Impl => dl_impl(did),
|
|
|
|
PublicField | PrivateField | InheritedField => dl_field,
|
2012-02-13 13:55:23 -06:00
|
|
|
}
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn lookup_def(cnum: ast::crate_num, data: @~[u8], did_: ast::def_id) ->
|
2012-05-22 12:54:12 -05:00
|
|
|
ast::def {
|
|
|
|
let item = lookup_item(did_.node, data);
|
2013-01-13 13:05:40 -06:00
|
|
|
let did = ast::def_id { crate: cnum, node: did_.node };
|
2012-05-22 12:54:12 -05:00
|
|
|
// We treat references to enums as references to types.
|
2012-08-01 19:30:05 -05:00
|
|
|
return def_like_to_def(item_to_def_like(item, did, cnum));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-03-27 05:16:28 -05:00
|
|
|
pub fn get_trait_def(cdata: cmd,
|
|
|
|
item_id: ast::node_id,
|
|
|
|
tcx: ty::ctxt) -> ty::TraitDef
|
|
|
|
{
|
|
|
|
let item_doc = lookup_item(item_id, cdata.data);
|
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
|
|
|
let tp_defs = item_ty_param_defs(item_doc, tcx, cdata,
|
|
|
|
tag_items_data_item_ty_param_bounds);
|
2013-03-27 05:16:28 -05:00
|
|
|
let rp = item_ty_region_param(item_doc);
|
|
|
|
ty::TraitDef {
|
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
|
|
|
generics: ty::Generics {type_param_defs: tp_defs,
|
2013-03-27 05:16:28 -05:00
|
|
|
region_param: rp},
|
|
|
|
trait_ref: @item_trait_ref(item_doc, tcx, cdata)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
2012-01-05 09:04:59 -06:00
|
|
|
-> ty::ty_param_bounds_and_ty {
|
2012-04-18 23:26:25 -05:00
|
|
|
|
2012-01-05 09:04:59 -06:00
|
|
|
let item = lookup_item(id, cdata.data);
|
2013-01-13 13:05:40 -06:00
|
|
|
let t = item_type(ast::def_id { crate: cdata.cnum, node: id }, item, tcx,
|
|
|
|
cdata);
|
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
|
|
|
let tp_defs = if family_has_type_params(item_family(item)) {
|
|
|
|
item_ty_param_defs(item, tcx, cdata, tag_items_data_item_ty_param_bounds)
|
2012-06-29 18:26:56 -05:00
|
|
|
} else { @~[] };
|
2012-04-18 23:26:25 -05:00
|
|
|
let rp = item_ty_region_param(item);
|
2013-02-19 01:40:42 -06:00
|
|
|
ty::ty_param_bounds_and_ty {
|
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
|
|
|
generics: ty::Generics {type_param_defs: tp_defs,
|
2013-03-27 05:16:28 -05:00
|
|
|
region_param: rp},
|
2013-02-19 01:40:42 -06:00
|
|
|
ty: t
|
|
|
|
}
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_region_param(cdata: cmd, id: ast::node_id)
|
2012-08-20 14:23:37 -05:00
|
|
|
-> Option<ty::region_variance> {
|
2012-08-09 11:59:50 -05:00
|
|
|
|
2012-07-11 12:28:30 -05:00
|
|
|
let item = lookup_item(id, cdata.data);
|
2012-08-01 19:30:05 -05:00
|
|
|
return item_ty_region_param(item);
|
2012-07-11 12:28:30 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
|
2011-12-16 07:41:12 -06:00
|
|
|
item_ty_param_count(lookup_item(id, data))
|
2011-07-29 18:40:23 -05:00
|
|
|
}
|
|
|
|
|
2013-03-27 05:16:28 -05:00
|
|
|
pub fn get_impl_traits(cdata: cmd,
|
|
|
|
id: ast::node_id,
|
|
|
|
tcx: ty::ctxt) -> ~[@ty::TraitRef]
|
|
|
|
{
|
|
|
|
let item_doc = lookup_item(id, cdata.data);
|
|
|
|
let mut results = ~[];
|
|
|
|
for reader::tagged_docs(item_doc, tag_item_trait_ref) |tp| {
|
|
|
|
let trait_ref =
|
|
|
|
@parse_trait_ref_data(tp.data, cdata.cnum, tp.start, tcx,
|
|
|
|
|_, did| translate_def_id(cdata, did));
|
|
|
|
results.push(trait_ref);
|
|
|
|
};
|
|
|
|
results
|
2012-01-05 03:57:19 -06:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
|
|
|
name: ast::ident) -> ast::def_id {
|
2012-12-06 18:13:54 -06:00
|
|
|
let items = reader::get_doc(reader::Doc(cdata.data), tag_items);
|
2012-08-20 14:23:37 -05:00
|
|
|
let mut found = None;
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(find_item(id, items), tag_item_impl_method)
|
2012-11-24 15:38:23 -06:00
|
|
|
|mid| {
|
2012-12-06 18:13:54 -06:00
|
|
|
let m_did = reader::with_doc_data(mid, |d| parse_def_id(d));
|
2012-11-24 15:38:23 -06:00
|
|
|
if item_name(intr, find_item(m_did.node, items)) == name {
|
|
|
|
found = Some(translate_def_id(cdata, m_did));
|
|
|
|
}
|
2012-03-08 05:15:02 -06:00
|
|
|
}
|
2012-09-21 21:37:57 -05:00
|
|
|
found.get()
|
2012-03-08 05:15:02 -06:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_symbol(data: @~[u8], id: ast::node_id) -> ~str {
|
2012-08-01 19:30:05 -05:00
|
|
|
return item_symbol(lookup_item(id, data));
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// Something that a name can resolve to.
|
2013-01-29 18:51:16 -06:00
|
|
|
pub enum def_like {
|
2012-05-22 12:54:12 -05:00
|
|
|
dl_def(ast::def),
|
|
|
|
dl_impl(ast::def_id),
|
|
|
|
dl_field
|
|
|
|
}
|
|
|
|
|
|
|
|
fn def_like_to_def(def_like: def_like) -> ast::def {
|
2012-08-06 14:34:08 -05:00
|
|
|
match def_like {
|
2012-08-03 21:59:04 -05:00
|
|
|
dl_def(def) => return def,
|
2013-02-11 21:26:38 -06:00
|
|
|
dl_impl(*) => fail!(~"found impl in def_like_to_def"),
|
|
|
|
dl_field => fail!(~"found field in def_like_to_def")
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-07 12:51:53 -06:00
|
|
|
/// Iterates over the language items in the given crate.
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) {
|
2013-01-07 12:51:53 -06:00
|
|
|
let root = reader::Doc(cdata.data);
|
|
|
|
let lang_items = reader::get_doc(root, tag_lang_items);
|
|
|
|
for reader::tagged_docs(lang_items, tag_lang_items_item) |item_doc| {
|
|
|
|
let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id);
|
|
|
|
let id = reader::doc_as_u32(id_doc) as uint;
|
|
|
|
let node_id_doc = reader::get_doc(item_doc,
|
|
|
|
tag_lang_items_item_node_id);
|
|
|
|
let node_id = reader::doc_as_u32(node_id_doc) as ast::node_id;
|
|
|
|
|
|
|
|
if !f(node_id, id) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Iterates over all the paths in the given crate.
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn each_path(intr: @ident_interner, cdata: cmd,
|
|
|
|
get_crate_data: GetCrateDataCb,
|
2013-03-07 16:38:38 -06:00
|
|
|
f: &fn(&str, def_like) -> bool) {
|
2012-12-06 18:13:54 -06:00
|
|
|
let root = reader::Doc(cdata.data);
|
|
|
|
let items = reader::get_doc(root, tag_items);
|
|
|
|
let items_data = reader::get_doc(items, tag_items_data);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
let mut broken = false;
|
|
|
|
|
|
|
|
// First, go through all the explicit items.
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(items_data, tag_items_data_item) |item_doc| {
|
2012-05-22 12:54:12 -05:00
|
|
|
if !broken {
|
2012-07-18 18:18:02 -05:00
|
|
|
let path = ast_map::path_to_str_with_sep(
|
|
|
|
item_path(intr, item_doc), ~"::", intr);
|
2013-01-21 22:32:13 -06:00
|
|
|
let path_is_empty = path.is_empty();
|
|
|
|
if !path_is_empty {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Extract the def ID.
|
2012-08-08 13:46:06 -05:00
|
|
|
let def_id = item_def_id(item_doc, cdata);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Construct the def for this item.
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("(each_path) yielding explicit item: %s", path);
|
2012-05-22 12:54:12 -05:00
|
|
|
let def_like = item_to_def_like(item_doc, def_id, cdata.cnum);
|
|
|
|
|
|
|
|
// Hand the information off to the iteratee.
|
2013-01-21 22:32:13 -06:00
|
|
|
if !f(path, def_like) {
|
|
|
|
broken = true; // FIXME #4572: This is awful.
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2012-07-03 20:30:11 -05:00
|
|
|
|
2012-08-17 14:41:34 -05:00
|
|
|
// If this is a module, find the reexports.
|
|
|
|
for each_reexport(item_doc) |reexport_doc| {
|
|
|
|
if !broken {
|
|
|
|
let def_id_doc =
|
2012-12-06 18:13:54 -06:00
|
|
|
reader::get_doc(reexport_doc,
|
2012-08-17 14:41:34 -05:00
|
|
|
tag_items_data_item_reexport_def_id);
|
|
|
|
let def_id =
|
2012-12-06 18:13:54 -06:00
|
|
|
reader::with_doc_data(def_id_doc,
|
2012-11-24 15:38:23 -06:00
|
|
|
|d| parse_def_id(d));
|
2012-08-17 14:41:34 -05:00
|
|
|
let def_id = translate_def_id(cdata, def_id);
|
|
|
|
|
|
|
|
let reexport_name_doc =
|
2012-12-06 18:13:54 -06:00
|
|
|
reader::get_doc(reexport_doc,
|
2012-08-17 14:41:34 -05:00
|
|
|
tag_items_data_item_reexport_name);
|
2012-12-06 18:13:54 -06:00
|
|
|
let reexport_name = reader::doc_as_str(reexport_name_doc);
|
2012-08-17 14:41:34 -05:00
|
|
|
|
|
|
|
let reexport_path;
|
2013-01-21 22:32:13 -06:00
|
|
|
if path_is_empty {
|
2012-08-17 14:41:34 -05:00
|
|
|
reexport_path = reexport_name;
|
|
|
|
} else {
|
|
|
|
reexport_path = path + ~"::" + reexport_name;
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-11-08 18:52:21 -06:00
|
|
|
// This reexport may be in yet another crate
|
|
|
|
let other_crates_items = if def_id.crate == cdata.cnum {
|
|
|
|
items
|
|
|
|
} else {
|
|
|
|
let crate_data = get_crate_data(def_id.crate);
|
2012-12-06 18:13:54 -06:00
|
|
|
let root = reader::Doc(crate_data.data);
|
|
|
|
reader::get_doc(root, tag_items)
|
2012-11-08 18:52:21 -06:00
|
|
|
};
|
|
|
|
|
2012-08-17 14:41:34 -05:00
|
|
|
// Get the item.
|
2012-11-08 18:52:21 -06:00
|
|
|
match maybe_find_item(def_id.node, other_crates_items) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {}
|
|
|
|
Some(item_doc) => {
|
2012-08-17 14:41:34 -05:00
|
|
|
// Construct the def for this item.
|
|
|
|
let def_like = item_to_def_like(item_doc,
|
|
|
|
def_id,
|
|
|
|
cdata.cnum);
|
|
|
|
|
|
|
|
// Hand the information off to the iteratee.
|
|
|
|
debug!("(each_path) yielding reexported \
|
|
|
|
item: %s", reexport_path);
|
|
|
|
|
2013-01-21 22:32:13 -06:00
|
|
|
if (!f(reexport_path, def_like)) {
|
|
|
|
broken = true; // FIXME #4572: This is awful.
|
2012-08-17 14:41:34 -05:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-09 19:43:36 -05:00
|
|
|
|
2012-08-17 14:41:34 -05:00
|
|
|
// If broken, stop here.
|
|
|
|
if broken {
|
|
|
|
return;
|
2012-07-09 19:43:36 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_item_path(intr: @ident_interner, cdata: cmd, id: ast::node_id)
|
2012-07-18 18:18:02 -05:00
|
|
|
-> ast_map::path {
|
|
|
|
item_path(intr, lookup_item(id, cdata.data))
|
2012-02-10 08:01:32 -06:00
|
|
|
}
|
|
|
|
|
2013-03-25 15:21:04 -05:00
|
|
|
pub type decode_inlined_item<'self> = &'self fn(
|
2013-02-19 01:40:42 -06:00
|
|
|
cdata: @cstore::crate_metadata,
|
2012-05-14 19:46:45 -05:00
|
|
|
tcx: ty::ctxt,
|
|
|
|
path: ast_map::path,
|
2012-10-07 18:33:20 -05:00
|
|
|
par_doc: ebml::Doc) -> Option<ast::inlined_item>;
|
2012-05-14 19:46:45 -05:00
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt,
|
|
|
|
id: ast::node_id,
|
|
|
|
decode_inlined_item: decode_inlined_item)
|
|
|
|
-> csearch::found_ast {
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("Looking up item: %d", id);
|
2012-02-14 17:21:53 -06:00
|
|
|
let item_doc = lookup_item(id, cdata.data);
|
2013-03-03 10:06:31 -06:00
|
|
|
let path = {
|
|
|
|
let item_path = item_path(intr, item_doc);
|
|
|
|
vec::from_slice(item_path.init())
|
|
|
|
};
|
2013-03-10 10:02:16 -05:00
|
|
|
match decode_inlined_item(cdata, tcx, copy path, item_doc) {
|
2013-01-07 16:16:52 -06:00
|
|
|
Some(ref ii) => csearch::found((/*bad*/copy *ii)),
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-08-06 14:34:08 -05:00
|
|
|
match item_parent_item(item_doc) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(did) => {
|
2012-03-08 16:13:57 -06:00
|
|
|
let did = translate_def_id(cdata, did);
|
|
|
|
let parent_item = lookup_item(did.node, cdata.data);
|
2013-03-03 10:06:31 -06:00
|
|
|
match decode_inlined_item(cdata, tcx, path, parent_item) {
|
2013-01-07 16:16:52 -06:00
|
|
|
Some(ref ii) => csearch::found_parent(did, (/*bad*/copy *ii)),
|
2012-08-20 14:23:37 -05:00
|
|
|
None => csearch::not_found
|
2012-03-08 16:13:57 -06:00
|
|
|
}
|
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => csearch::not_found
|
2012-03-08 16:13:57 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-14 17:21:53 -06:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
2012-11-30 13:24:16 -06:00
|
|
|
tcx: ty::ctxt) -> ~[ty::VariantInfo] {
|
2012-01-05 09:04:59 -06:00
|
|
|
let data = cdata.data;
|
2012-12-06 18:13:54 -06:00
|
|
|
let items = reader::get_doc(reader::Doc(data), tag_items);
|
2012-01-05 09:04:59 -06:00
|
|
|
let item = find_item(id, items);
|
2012-11-30 13:24:16 -06:00
|
|
|
let mut infos: ~[ty::VariantInfo] = ~[];
|
2012-01-25 07:34:31 -06:00
|
|
|
let variant_ids = enum_variant_ids(item, cdata);
|
2012-03-15 08:47:03 -05:00
|
|
|
let mut disr_val = 0;
|
2012-06-30 18:19:07 -05:00
|
|
|
for variant_ids.each |did| {
|
2011-07-27 07:19:39 -05:00
|
|
|
let item = find_item(did.node, items);
|
2013-01-13 13:05:40 -06:00
|
|
|
let ctor_ty = item_type(ast::def_id { crate: cdata.cnum, node: id},
|
|
|
|
item, tcx, cdata);
|
2012-07-18 18:18:02 -05:00
|
|
|
let name = item_name(intr, item);
|
2012-10-18 11:14:11 -05:00
|
|
|
let arg_tys = match ty::get(ctor_ty).sty {
|
2013-01-31 19:12:29 -06:00
|
|
|
ty::ty_bare_fn(ref f) => f.sig.inputs.map(|a| a.ty),
|
|
|
|
_ => ~[], // Nullary enum variant.
|
2012-10-18 11:14:11 -05:00
|
|
|
};
|
2012-08-06 14:34:08 -05:00
|
|
|
match variant_disr_val(item) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(val) => { disr_val = val; }
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => { /* empty */ }
|
2012-01-10 15:50:40 -06:00
|
|
|
}
|
2012-11-30 13:24:16 -06:00
|
|
|
infos.push(@ty::VariantInfo_{args: arg_tys,
|
|
|
|
ctor_ty: ctor_ty, name: name,
|
|
|
|
// I'm not even sure if we encode visibility
|
|
|
|
// for variants -- TEST -- tjc
|
|
|
|
id: *did, disr_val: disr_val, vis: ast::inherited});
|
2012-01-10 15:50:40 -06:00
|
|
|
disr_val += 1;
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return infos;
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ {
|
2012-07-31 18:32:37 -05:00
|
|
|
fn get_mutability(ch: u8) -> ast::mutability {
|
2012-08-06 14:34:08 -05:00
|
|
|
match ch as char {
|
2012-07-31 18:32:37 -05:00
|
|
|
'i' => { ast::m_imm }
|
|
|
|
'm' => { ast::m_mutbl }
|
|
|
|
'c' => { ast::m_const }
|
|
|
|
_ => {
|
2013-02-11 21:26:38 -06:00
|
|
|
fail!(fmt!("unknown mutability character: `%c`", ch as char))
|
2012-07-31 18:32:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-06 18:13:54 -06:00
|
|
|
let self_type_doc = reader::get_doc(item, tag_item_trait_method_self_ty);
|
|
|
|
let string = reader::doc_as_str(self_type_doc);
|
2012-07-31 18:32:37 -05:00
|
|
|
|
|
|
|
let self_ty_kind = string[0];
|
2012-08-06 14:34:08 -05:00
|
|
|
match self_ty_kind as char {
|
2012-08-02 18:01:38 -05:00
|
|
|
's' => { return ast::sty_static; }
|
2012-08-01 19:30:05 -05:00
|
|
|
'v' => { return ast::sty_value; }
|
|
|
|
'@' => { return ast::sty_box(get_mutability(string[1])); }
|
|
|
|
'~' => { return ast::sty_uniq(get_mutability(string[1])); }
|
2013-03-09 18:43:53 -06:00
|
|
|
'&' => {
|
|
|
|
// FIXME(#4846) expl. region
|
|
|
|
return ast::sty_region(None, get_mutability(string[1]));
|
|
|
|
}
|
2012-07-31 18:32:37 -05:00
|
|
|
_ => {
|
2013-02-11 21:26:38 -06:00
|
|
|
fail!(fmt!("unknown self type code: `%c`", self_ty_kind as char));
|
2012-07-31 18:32:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc,
|
2013-02-19 01:40:42 -06:00
|
|
|
base_tps: uint) -> ~[@resolve::MethodInfo] {
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut rslt = ~[];
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, tag_item_impl_method) |doc| {
|
|
|
|
let m_did = reader::with_doc_data(doc, |d| parse_def_id(d));
|
2012-01-11 10:11:56 -06:00
|
|
|
let mth_item = lookup_item(m_did.node, cdata.data);
|
2012-07-31 18:32:37 -05:00
|
|
|
let self_ty = get_self_ty(mth_item);
|
2013-02-19 01:40:42 -06:00
|
|
|
rslt.push(@resolve::MethodInfo {
|
|
|
|
did: translate_def_id(cdata, m_did),
|
|
|
|
n_tps: item_ty_param_count(mth_item) - base_tps,
|
|
|
|
ident: item_name(intr, mth_item),
|
|
|
|
self_type: self_ty});
|
2011-12-16 07:41:12 -06:00
|
|
|
}
|
|
|
|
rslt
|
|
|
|
}
|
|
|
|
|
2013-02-11 18:28:39 -06:00
|
|
|
pub fn get_impls_for_mod(intr: @ident_interner,
|
|
|
|
cdata: cmd,
|
|
|
|
m_id: ast::node_id,
|
|
|
|
name: Option<ast::ident>,
|
|
|
|
get_cdata: &fn(ast::crate_num) -> cmd)
|
2013-02-19 01:40:42 -06:00
|
|
|
-> @~[@resolve::Impl] {
|
2012-01-05 09:04:59 -06:00
|
|
|
let data = cdata.data;
|
2012-03-15 08:47:03 -05:00
|
|
|
let mod_item = lookup_item(m_id, data);
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut result = ~[];
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(mod_item, tag_mod_impl) |doc| {
|
|
|
|
let did = reader::with_doc_data(doc, |d| parse_def_id(d));
|
2012-04-16 16:58:58 -05:00
|
|
|
let local_did = translate_def_id(cdata, did);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("(get impls for mod) getting did %? for '%?'",
|
|
|
|
local_did, name);
|
2012-04-26 14:15:46 -05:00
|
|
|
// The impl may be defined in a different crate. Ask the caller
|
|
|
|
// to give us the metadata
|
2012-04-16 16:58:58 -05:00
|
|
|
let impl_cdata = get_cdata(local_did.crate);
|
|
|
|
let impl_data = impl_cdata.data;
|
|
|
|
let item = lookup_item(local_did.node, impl_data);
|
2012-07-18 18:18:02 -05:00
|
|
|
let nm = item_name(intr, item);
|
2012-08-20 14:23:37 -05:00
|
|
|
if match name { Some(n) => { n == nm } None => { true } } {
|
2012-04-26 14:15:46 -05:00
|
|
|
let base_tps = item_ty_param_count(item);
|
2013-02-19 01:40:42 -06:00
|
|
|
result.push(@resolve::Impl {
|
2012-04-16 16:58:58 -05:00
|
|
|
did: local_did, ident: nm,
|
2012-07-18 18:18:02 -05:00
|
|
|
methods: item_impl_methods(intr, impl_cdata, item, base_tps)
|
2012-06-26 02:39:18 -05:00
|
|
|
});
|
2012-04-26 14:15:46 -05:00
|
|
|
};
|
2012-01-05 06:57:27 -06:00
|
|
|
}
|
|
|
|
@result
|
|
|
|
}
|
|
|
|
|
2013-03-27 09:26:57 -05:00
|
|
|
pub fn get_method_name_and_self_ty(
|
|
|
|
intr: @ident_interner,
|
|
|
|
cdata: cmd,
|
|
|
|
id: ast::node_id) -> (ast::ident, ast::self_ty_)
|
|
|
|
{
|
|
|
|
let method_doc = lookup_item(id, cdata.data);
|
|
|
|
let name = item_name(intr, method_doc);
|
|
|
|
let self_ty = get_self_ty(method_doc);
|
|
|
|
(name, self_ty)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
|
|
|
tcx: ty::ctxt) -> ty::method
|
|
|
|
{
|
|
|
|
let method_doc = lookup_item(id, cdata.data);
|
2013-03-28 13:27:54 -05:00
|
|
|
let def_id = item_def_id(method_doc, cdata);
|
|
|
|
let name = item_name(intr, method_doc);
|
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
|
|
|
let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
|
|
|
|
tag_item_method_tps);
|
2013-03-29 15:02:55 -05:00
|
|
|
let transformed_self_ty = doc_transformed_self_ty(method_doc, tcx, cdata);
|
2013-03-27 09:26:57 -05:00
|
|
|
let fty = doc_method_fty(method_doc, tcx, cdata);
|
2013-03-28 13:27:54 -05:00
|
|
|
let vis = item_visibility(method_doc);
|
2013-03-27 09:26:57 -05:00
|
|
|
let self_ty = get_self_ty(method_doc);
|
|
|
|
ty::method {
|
|
|
|
ident: name,
|
2013-03-27 05:16:28 -05:00
|
|
|
generics: ty::Generics {
|
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
|
|
|
type_param_defs: type_param_defs,
|
2013-03-27 05:16:28 -05:00
|
|
|
region_param: None
|
|
|
|
},
|
2013-03-29 15:02:55 -05:00
|
|
|
transformed_self_ty: transformed_self_ty,
|
2013-03-27 09:26:57 -05:00
|
|
|
fty: fty,
|
|
|
|
self_ty: self_ty,
|
2013-03-28 13:27:54 -05:00
|
|
|
vis: vis,
|
2013-03-27 09:26:57 -05:00
|
|
|
def_id: def_id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_trait_method_def_ids(cdata: cmd,
|
|
|
|
id: ast::node_id) -> ~[ast::def_id] {
|
2012-01-05 09:04:59 -06:00
|
|
|
let data = cdata.data;
|
2012-03-15 08:47:03 -05:00
|
|
|
let item = lookup_item(id, data);
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut result = ~[];
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, tag_item_trait_method) |mth| {
|
2013-03-27 09:26:57 -05:00
|
|
|
result.push(item_def_id(mth, cdata));
|
2012-01-05 06:57:27 -06:00
|
|
|
}
|
2013-03-27 09:26:57 -05:00
|
|
|
result
|
2012-01-05 06:57:27 -06:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
|
|
|
|
id: ast::node_id, tcx: ty::ctxt) ->
|
2012-10-08 14:39:30 -05:00
|
|
|
~[ProvidedTraitMethodInfo] {
|
|
|
|
let data = cdata.data;
|
|
|
|
let item = lookup_item(id, data);
|
|
|
|
let mut result = ~[];
|
|
|
|
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, tag_item_trait_method) |mth| {
|
2012-10-08 14:39:30 -05:00
|
|
|
if item_method_sort(mth) != 'p' { loop; }
|
|
|
|
|
|
|
|
let did = item_def_id(mth, cdata);
|
|
|
|
|
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
|
|
|
let type_param_defs =
|
|
|
|
item_ty_param_defs(mth, tcx, cdata,
|
|
|
|
tag_items_data_item_ty_param_bounds);
|
2012-10-08 14:39:30 -05:00
|
|
|
let name = item_name(intr, mth);
|
|
|
|
let ty = doc_type(mth, tcx, cdata);
|
|
|
|
|
2013-01-31 19:12:29 -06:00
|
|
|
let fty = match ty::get(ty).sty {
|
|
|
|
ty::ty_bare_fn(ref f) => copy *f,
|
2012-10-08 14:39:30 -05:00
|
|
|
_ => {
|
|
|
|
tcx.diag.handler().bug(~"get_provided_trait_methods(): id \
|
|
|
|
has non-function type");
|
|
|
|
}
|
2013-01-31 19:12:29 -06:00
|
|
|
};
|
2012-10-08 14:39:30 -05:00
|
|
|
|
2013-03-29 15:02:55 -05:00
|
|
|
let transformed_self_ty = doc_transformed_self_ty(mth, tcx, cdata);
|
2012-10-08 14:39:30 -05:00
|
|
|
let self_ty = get_self_ty(mth);
|
2013-02-19 01:40:42 -06:00
|
|
|
let ty_method = ty::method {
|
|
|
|
ident: name,
|
2013-03-27 05:16:28 -05:00
|
|
|
generics: ty::Generics {
|
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
|
|
|
type_param_defs: type_param_defs,
|
2013-03-27 05:16:28 -05:00
|
|
|
region_param: None
|
|
|
|
},
|
2013-03-29 15:02:55 -05:00
|
|
|
transformed_self_ty: transformed_self_ty,
|
2013-02-19 01:40:42 -06:00
|
|
|
fty: fty,
|
|
|
|
self_ty: self_ty,
|
|
|
|
vis: ast::public,
|
|
|
|
def_id: did
|
|
|
|
};
|
2012-10-08 14:39:30 -05:00
|
|
|
let provided_trait_method_info = ProvidedTraitMethodInfo {
|
|
|
|
ty: ty_method,
|
|
|
|
def_id: did
|
|
|
|
};
|
|
|
|
|
2013-02-15 03:14:34 -06:00
|
|
|
vec::push(&mut result, provided_trait_method_info);
|
2012-10-08 14:39:30 -05:00
|
|
|
}
|
|
|
|
|
2013-02-15 03:14:34 -06:00
|
|
|
return result;
|
2012-10-08 14:39:30 -05:00
|
|
|
}
|
|
|
|
|
2012-10-19 23:27:01 -05:00
|
|
|
/// Returns the supertraits of the given trait.
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
2013-03-27 05:16:28 -05:00
|
|
|
-> ~[@ty::TraitRef] {
|
2013-03-07 17:37:14 -06:00
|
|
|
let mut results = ~[];
|
2012-10-19 23:27:01 -05:00
|
|
|
let item_doc = lookup_item(id, cdata.data);
|
2013-03-27 05:16:28 -05:00
|
|
|
for reader::tagged_docs(item_doc, tag_item_super_trait_ref) |trait_doc| {
|
|
|
|
results.push(@doc_trait_ref(trait_doc, tcx, cdata));
|
2012-10-19 23:27:01 -05:00
|
|
|
}
|
2013-03-07 17:37:14 -06:00
|
|
|
return results;
|
2012-10-19 23:27:01 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_type_name_if_impl(intr: @ident_interner,
|
|
|
|
cdata: cmd,
|
|
|
|
node_id: ast::node_id) -> Option<ast::ident> {
|
2012-10-18 15:29:34 -05:00
|
|
|
let item = lookup_item(node_id, cdata.data);
|
|
|
|
if item_family(item) != Impl {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, tag_item_impl_type_basename) |doc| {
|
|
|
|
return Some(intr.intern(@str::from_bytes(reader::doc_data(doc))));
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_static_methods_if_impl(intr: @ident_interner,
|
|
|
|
cdata: cmd,
|
|
|
|
node_id: ast::node_id)
|
|
|
|
-> Option<~[StaticMethodInfo]> {
|
2012-10-18 15:29:34 -05:00
|
|
|
let item = lookup_item(node_id, cdata.data);
|
|
|
|
if item_family(item) != Impl {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2013-03-27 05:16:28 -05:00
|
|
|
// If this impl implements a trait, don't consider it.
|
|
|
|
for reader::tagged_docs(item, tag_item_trait_ref) |_doc| {
|
2012-10-18 15:29:34 -05:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2013-03-07 17:37:14 -06:00
|
|
|
let mut impl_method_ids = ~[];
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, tag_item_impl_method) |impl_method_doc| {
|
|
|
|
impl_method_ids.push(parse_def_id(reader::doc_data(impl_method_doc)));
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
|
|
|
|
2013-03-07 17:37:14 -06:00
|
|
|
let mut static_impl_methods = ~[];
|
2012-10-18 15:29:34 -05:00
|
|
|
for impl_method_ids.each |impl_method_id| {
|
|
|
|
let impl_method_doc = lookup_item(impl_method_id.node, cdata.data);
|
|
|
|
let family = item_family(impl_method_doc);
|
|
|
|
match family {
|
|
|
|
StaticMethod | UnsafeStaticMethod | PureStaticMethod => {
|
|
|
|
let purity;
|
|
|
|
match item_family(impl_method_doc) {
|
|
|
|
StaticMethod => purity = ast::impure_fn,
|
|
|
|
UnsafeStaticMethod => purity = ast::unsafe_fn,
|
|
|
|
PureStaticMethod => purity = ast::pure_fn,
|
2013-02-11 21:26:38 -06:00
|
|
|
_ => fail!()
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static_impl_methods.push(StaticMethodInfo {
|
|
|
|
ident: item_name(intr, impl_method_doc),
|
|
|
|
def_id: item_def_id(impl_method_doc, cdata),
|
|
|
|
purity: purity
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-07 17:37:14 -06:00
|
|
|
return Some(static_impl_methods);
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_item_attrs(cdata: cmd,
|
|
|
|
node_id: ast::node_id,
|
2013-03-07 16:38:38 -06:00
|
|
|
f: &fn(~[@ast::meta_item])) {
|
2012-07-25 20:36:18 -05:00
|
|
|
|
|
|
|
let item = lookup_item(node_id, cdata.data);
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, tag_attributes) |attributes| {
|
|
|
|
for reader::tagged_docs(attributes, tag_attribute) |attribute| {
|
2012-07-25 20:36:18 -05:00
|
|
|
f(get_meta_items(attribute));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-22 13:09:13 -05:00
|
|
|
fn struct_field_family_to_visibility(family: Family) -> ast::visibility {
|
2012-12-10 15:47:54 -06:00
|
|
|
match family {
|
|
|
|
PublicField => ast::public,
|
|
|
|
PrivateField => ast::private,
|
|
|
|
InheritedField => ast::inherited,
|
2013-02-11 21:26:38 -06:00
|
|
|
_ => fail!()
|
2012-12-10 15:47:54 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_struct_fields(intr: @ident_interner, cdata: cmd, id: ast::node_id)
|
2012-12-10 15:47:54 -06:00
|
|
|
-> ~[ty::field_ty] {
|
2012-03-06 10:02:13 -06:00
|
|
|
let data = cdata.data;
|
2012-03-15 08:47:03 -05:00
|
|
|
let item = lookup_item(id, data);
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut result = ~[];
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(item, tag_item_field) |an_item| {
|
2013-01-16 21:24:10 -06:00
|
|
|
let f = item_family(an_item);
|
|
|
|
if f == PublicField || f == PrivateField || f == InheritedField {
|
|
|
|
let name = item_name(intr, an_item);
|
|
|
|
let did = item_def_id(an_item, cdata);
|
|
|
|
result.push(ty::field_ty {
|
|
|
|
ident: name,
|
|
|
|
id: did, vis:
|
2013-02-27 15:45:37 -06:00
|
|
|
struct_field_family_to_visibility(f),
|
2013-01-16 21:24:10 -06:00
|
|
|
});
|
|
|
|
}
|
2012-03-06 10:02:13 -06:00
|
|
|
}
|
2013-02-11 18:28:39 -06:00
|
|
|
for reader::tagged_docs(item, tag_item_unnamed_field) |an_item| {
|
|
|
|
let did = item_def_id(an_item, cdata);
|
|
|
|
result.push(ty::field_ty {
|
|
|
|
ident: special_idents::unnamed_field,
|
|
|
|
id: did,
|
|
|
|
vis: ast::inherited,
|
|
|
|
});
|
|
|
|
}
|
2012-03-06 10:02:13 -06:00
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2013-03-20 16:38:57 -05:00
|
|
|
pub fn get_item_visibility(cdata: cmd, id: ast::node_id)
|
|
|
|
-> ast::visibility {
|
2013-02-27 15:45:37 -06:00
|
|
|
item_visibility(lookup_item(id, cdata.data))
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:58:05 -05:00
|
|
|
fn family_has_type_params(fam: Family) -> bool {
|
|
|
|
match fam {
|
|
|
|
Const | ForeignType | Mod | ForeignMod | PublicField | PrivateField
|
|
|
|
| ForeignFn => false,
|
|
|
|
_ => true
|
2012-01-05 06:57:27 -06:00
|
|
|
}
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:58:05 -05:00
|
|
|
fn family_names_type(fam: Family) -> bool {
|
|
|
|
match fam { Type | Mod | Trait => true, _ => false }
|
2011-12-19 06:52:58 -06:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
fn read_path(d: ebml::Doc) -> (~str, uint) {
|
2012-12-06 18:13:54 -06:00
|
|
|
let desc = reader::doc_data(d);
|
2012-02-14 17:21:53 -06:00
|
|
|
let pos = io::u64_from_be_bytes(desc, 0u, 4u) as uint;
|
2011-08-13 02:09:25 -05:00
|
|
|
let pathbytes = vec::slice::<u8>(desc, 4u, vec::len::<u8>(desc));
|
2012-01-25 03:20:55 -06:00
|
|
|
let path = str::from_bytes(pathbytes);
|
2013-02-19 01:40:42 -06:00
|
|
|
|
|
|
|
(path, pos)
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str {
|
2012-08-01 19:30:05 -05:00
|
|
|
if id.crate != ast::local_crate { return ~"external"; }
|
2012-08-06 14:34:08 -05:00
|
|
|
let it = match maybe_find_item(id.node, items) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(it) => it,
|
2013-02-11 21:26:38 -06:00
|
|
|
None => fail!(fmt!("describe_def: item not found %?", id))
|
2012-06-25 18:49:14 -05:00
|
|
|
};
|
2012-08-01 19:30:05 -05:00
|
|
|
return item_family_to_str(item_family(it));
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:58:05 -05:00
|
|
|
fn item_family_to_str(fam: Family) -> ~str {
|
|
|
|
match fam {
|
|
|
|
Const => ~"const",
|
|
|
|
Fn => ~"fn",
|
|
|
|
UnsafeFn => ~"unsafe fn",
|
|
|
|
PureFn => ~"pure fn",
|
|
|
|
StaticMethod => ~"static method",
|
|
|
|
UnsafeStaticMethod => ~"unsafe static method",
|
|
|
|
PureStaticMethod => ~"pure static method",
|
|
|
|
ForeignFn => ~"foreign fn",
|
|
|
|
Type => ~"type",
|
|
|
|
ForeignType => ~"foreign type",
|
|
|
|
Mod => ~"mod",
|
|
|
|
ForeignMod => ~"foreign mod",
|
|
|
|
Enum => ~"enum",
|
|
|
|
Variant => ~"variant",
|
|
|
|
Impl => ~"impl",
|
|
|
|
Trait => ~"trait",
|
|
|
|
Struct => ~"struct",
|
|
|
|
PublicField => ~"public field",
|
|
|
|
PrivateField => ~"private field",
|
|
|
|
InheritedField => ~"inherited field",
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn get_meta_items(md: ebml::Doc) -> ~[@ast::meta_item] {
|
2012-09-20 20:15:39 -05:00
|
|
|
let mut items: ~[@ast::meta_item] = ~[];
|
2012-12-06 18:13:54 -06:00
|
|
|
for 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 = str::from_bytes(reader::doc_data(nd));
|
2013-02-14 22:19:27 -06:00
|
|
|
items.push(attr::mk_word_item(@n));
|
2011-10-21 05:31:48 -05:00
|
|
|
};
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(md, tag_meta_item_name_value) |meta_item_doc| {
|
|
|
|
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
|
|
|
|
let vd = reader::get_doc(meta_item_doc, tag_meta_item_value);
|
|
|
|
let n = str::from_bytes(reader::doc_data(nd));
|
|
|
|
let v = str::from_bytes(reader::doc_data(vd));
|
2012-05-17 18:17:11 -05:00
|
|
|
// FIXME (#623): Should be able to decode meta_name_value variants,
|
|
|
|
// but currently the encoder just drops them
|
2013-02-14 22:19:27 -06:00
|
|
|
items.push(attr::mk_name_value_item_str(@n, @v));
|
2011-10-21 05:31:48 -05:00
|
|
|
};
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(md, tag_meta_item_list) |meta_item_doc| {
|
|
|
|
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
|
|
|
|
let n = str::from_bytes(reader::doc_data(nd));
|
2011-07-27 07:19:39 -05:00
|
|
|
let subitems = get_meta_items(meta_item_doc);
|
2013-02-14 22:19:27 -06:00
|
|
|
items.push(attr::mk_list_item(@n, subitems));
|
2011-10-21 05:31:48 -05:00
|
|
|
};
|
2012-08-01 19:30:05 -05:00
|
|
|
return items;
|
2011-06-27 20:32:15 -05:00
|
|
|
}
|
|
|
|
|
2012-10-07 18:33:20 -05:00
|
|
|
fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] {
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut attrs: ~[ast::attribute] = ~[];
|
2012-12-06 18:13:54 -06:00
|
|
|
match reader::maybe_get_doc(md, tag_attributes) {
|
2012-08-20 14:23:37 -05:00
|
|
|
option::Some(attrs_d) => {
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(attrs_d, tag_attribute) |attr_doc| {
|
2011-07-27 07:19:39 -05:00
|
|
|
let meta_items = get_meta_items(attr_doc);
|
|
|
|
// Currently it's only possible to have a single meta item on
|
|
|
|
// an attribute
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!((vec::len(meta_items) == 1u));
|
2011-08-19 17:16:48 -05:00
|
|
|
let meta_item = meta_items[0];
|
2012-09-26 19:33:34 -05:00
|
|
|
attrs.push(
|
2013-01-30 11:56:33 -06:00
|
|
|
codemap::spanned {
|
2013-01-13 18:51:48 -06:00
|
|
|
node: ast::attribute_ {
|
|
|
|
style: ast::attr_outer,
|
2013-02-25 08:19:44 -06:00
|
|
|
value: meta_item,
|
2013-01-13 18:51:48 -06:00
|
|
|
is_sugared_doc: false,
|
|
|
|
},
|
2013-01-30 11:56:33 -06:00
|
|
|
span: codemap::dummy_sp()
|
2013-01-13 18:51:48 -06:00
|
|
|
});
|
2011-10-21 05:31:48 -05:00
|
|
|
};
|
2011-07-27 07:19:39 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
option::None => ()
|
2011-06-27 21:41:48 -05:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return attrs;
|
2011-06-27 21:41:48 -05:00
|
|
|
}
|
|
|
|
|
2012-09-19 20:50:24 -05:00
|
|
|
fn list_meta_items(intr: @ident_interner,
|
2013-03-12 15:00:50 -05:00
|
|
|
meta_items: ebml::Doc,
|
|
|
|
out: @io::Writer) {
|
2012-06-30 18:19:07 -05:00
|
|
|
for get_meta_items(meta_items).each |mi| {
|
2012-09-19 18:55:01 -05:00
|
|
|
out.write_str(fmt!("%s\n", pprust::meta_item_to_str(*mi, intr)));
|
2011-06-27 20:32:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-16 12:16:32 -06:00
|
|
|
fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: &str,
|
2013-03-12 15:00:50 -05:00
|
|
|
out: @io::Writer) {
|
2012-08-22 19:24:52 -05:00
|
|
|
out.write_str(fmt!("=Crate Attributes (%s)=\n", hash));
|
2011-06-27 21:41:48 -05:00
|
|
|
|
2012-06-30 18:19:07 -05:00
|
|
|
for get_attributes(md).each |attr| {
|
2012-09-19 18:55:01 -05:00
|
|
|
out.write_str(fmt!("%s\n", pprust::attribute_to_str(*attr, intr)));
|
2011-06-27 21:41:48 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
out.write_str(~"\n\n");
|
2011-06-27 20:32:15 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] {
|
2012-12-06 18:13:54 -06:00
|
|
|
return get_attributes(reader::Doc(data));
|
2011-06-28 13:24:24 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub struct crate_dep {
|
|
|
|
cnum: ast::crate_num,
|
|
|
|
name: ast::ident,
|
|
|
|
vers: @~str,
|
|
|
|
hash: @~str
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn get_crate_deps(intr: @ident_interner, data: @~[u8]) -> ~[crate_dep] {
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut deps: ~[crate_dep] = ~[];
|
2012-12-06 18:13:54 -06:00
|
|
|
let cratedoc = reader::Doc(data);
|
|
|
|
let depsdoc = reader::get_doc(cratedoc, tag_crate_deps);
|
2012-03-15 08:47:03 -05:00
|
|
|
let mut crate_num = 1;
|
2012-10-07 18:33:20 -05:00
|
|
|
fn docstr(doc: ebml::Doc, tag_: uint) -> ~str {
|
2012-12-06 18:13:54 -06:00
|
|
|
str::from_bytes(reader::doc_data(reader::get_doc(doc, tag_)))
|
2012-04-07 12:59:37 -05:00
|
|
|
}
|
2012-12-06 18:13:54 -06:00
|
|
|
for reader::tagged_docs(depsdoc, tag_crate_dep) |depdoc| {
|
2013-02-19 01:40:42 -06:00
|
|
|
deps.push(crate_dep {cnum: crate_num,
|
2012-07-18 18:18:02 -05:00
|
|
|
name: intr.intern(@docstr(depdoc, tag_crate_dep_name)),
|
2013-02-16 12:16:32 -06:00
|
|
|
vers: @docstr(depdoc, tag_crate_dep_vers),
|
|
|
|
hash: @docstr(depdoc, tag_crate_dep_hash)});
|
2011-07-08 13:29:56 -05:00
|
|
|
crate_num += 1;
|
2011-10-21 05:31:48 -05:00
|
|
|
};
|
2012-08-01 19:30:05 -05:00
|
|
|
return deps;
|
2011-07-08 13:29:56 -05:00
|
|
|
}
|
|
|
|
|
2013-03-12 15:00:50 -05:00
|
|
|
fn list_crate_deps(intr: @ident_interner, data: @~[u8], out: @io::Writer) {
|
2012-07-14 00:57:48 -05:00
|
|
|
out.write_str(~"=External Dependencies=\n");
|
2011-07-08 13:29:56 -05:00
|
|
|
|
2012-07-18 18:18:02 -05:00
|
|
|
for get_crate_deps(intr, data).each |dep| {
|
|
|
|
out.write_str(
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%d %s-%s-%s\n",
|
2013-02-16 12:16:32 -06:00
|
|
|
dep.cnum, *intr.get(dep.name), *dep.hash, *dep.vers));
|
2011-07-08 13:29:56 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
out.write_str(~"\n");
|
2011-07-08 13:29:56 -05:00
|
|
|
}
|
|
|
|
|
2013-02-16 12:16:32 -06:00
|
|
|
pub fn get_crate_hash(data: @~[u8]) -> @~str {
|
2012-12-06 18:13:54 -06:00
|
|
|
let cratedoc = reader::Doc(data);
|
|
|
|
let hashdoc = reader::get_doc(cratedoc, tag_crate_hash);
|
2013-02-16 12:16:32 -06:00
|
|
|
@str::from_bytes(reader::doc_data(hashdoc))
|
2011-12-11 09:23:38 -06:00
|
|
|
}
|
|
|
|
|
2013-02-16 12:16:32 -06:00
|
|
|
pub fn get_crate_vers(data: @~[u8]) -> @~str {
|
2012-04-07 12:59:37 -05:00
|
|
|
let attrs = decoder::get_crate_attributes(data);
|
2013-02-16 11:48:28 -06:00
|
|
|
let linkage_attrs = attr::find_linkage_metas(attrs);
|
|
|
|
|
|
|
|
match attr::last_meta_item_value_str_by_name(linkage_attrs, ~"vers") {
|
2013-02-16 12:16:32 -06:00
|
|
|
Some(ver) => ver,
|
|
|
|
None => @~"0.0"
|
2013-02-16 11:48:28 -06:00
|
|
|
}
|
2012-04-07 12:59:37 -05:00
|
|
|
}
|
|
|
|
|
2012-11-08 18:52:21 -06:00
|
|
|
fn iter_crate_items(intr: @ident_interner, cdata: cmd,
|
|
|
|
get_crate_data: GetCrateDataCb,
|
2013-03-07 16:38:38 -06:00
|
|
|
proc: &fn(path: &str, ast::def_id)) {
|
2013-01-21 22:32:13 -06:00
|
|
|
for each_path(intr, cdata, get_crate_data) |path_string, def_like| {
|
|
|
|
match def_like {
|
2012-08-17 16:54:28 -05:00
|
|
|
dl_impl(*) | dl_field => {}
|
|
|
|
dl_def(def) => {
|
2013-01-21 22:32:13 -06:00
|
|
|
proc(path_string,
|
2013-01-07 16:16:52 -06:00
|
|
|
ast_util::def_id_of_def(def))
|
2012-08-17 16:54:28 -05:00
|
|
|
}
|
|
|
|
}
|
2012-01-20 12:45:25 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8],
|
2013-03-12 15:00:50 -05:00
|
|
|
out: @io::Writer) {
|
2011-12-11 09:23:38 -06:00
|
|
|
let hash = get_crate_hash(bytes);
|
2012-12-06 18:13:54 -06:00
|
|
|
let md = reader::Doc(bytes);
|
2013-02-16 12:16:32 -06:00
|
|
|
list_crate_attributes(intr, md, *hash, out);
|
2012-07-18 18:18:02 -05:00
|
|
|
list_crate_deps(intr, bytes, out);
|
2011-06-27 17:53:27 -05:00
|
|
|
}
|
|
|
|
|
2012-01-05 09:04:59 -06:00
|
|
|
// Translates a def_id from an external crate to a def_id for the current
|
|
|
|
// compilation environment. We use this when trying to load types from
|
|
|
|
// external crates - if those types further refer to types in other crates
|
|
|
|
// then we must translate the crate number from that encoded in the external
|
|
|
|
// crate to the correct local crate number.
|
2013-01-29 18:51:16 -06:00
|
|
|
pub fn translate_def_id(cdata: cmd, did: ast::def_id) -> ast::def_id {
|
2012-01-05 09:04:59 -06:00
|
|
|
if did.crate == ast::local_crate {
|
2013-01-13 13:05:40 -06:00
|
|
|
return ast::def_id { crate: cdata.cnum, node: did.node };
|
2012-01-05 09:04:59 -06:00
|
|
|
}
|
|
|
|
|
2013-02-05 21:41:45 -06:00
|
|
|
match cdata.cnum_map.find(&did.crate) {
|
2013-03-22 21:26:41 -05:00
|
|
|
option::Some(&n) => ast::def_id { crate: n, node: did.node },
|
2013-02-11 21:26:38 -06:00
|
|
|
option::None => fail!(~"didn't find a crate in the cnum_map")
|
2012-01-05 09:04:59 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-07 00:06:53 -06:00
|
|
|
pub fn get_link_args_for_crate(cdata: cmd) -> ~[~str] {
|
|
|
|
let link_args = reader::get_doc(reader::Doc(cdata.data), tag_link_args);
|
|
|
|
let mut result = ~[];
|
|
|
|
for reader::tagged_docs(link_args, tag_link_args_arg) |arg_doc| {
|
|
|
|
result.push(reader::doc_as_str(arg_doc));
|
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|