use codemap::{span, filename};
use parse::token;
-#[cfg(stage0)]
-impl span: Serializable {
- /* Note #1972 -- spans are serialized but not deserialized */
- fn serialize<S: Serializer>(&self, _s: &S) { }
-}
-
-#[cfg(stage0)]
-impl span: Deserializable {
- static fn deserialize<D: Deserializer>(_d: &D) -> span {
- ast_util::dummy_sp()
- }
-}
-
-#[cfg(stage1)]
-#[cfg(stage2)]
-impl<S: Serializer> span: Serializable<S> {
- /* Note #1972 -- spans are serialized but not deserialized */
- fn serialize(&self, _s: &S) { }
-}
-
-#[cfg(stage1)]
-#[cfg(stage2)]
-impl<D: Deserializer> span: Deserializable<D> {
- static fn deserialize(_d: &D) -> span {
- ast_util::dummy_sp()
- }
-}
-
#[auto_serialize]
#[auto_deserialize]
type spanned<T> = {node: T, span: span};
enum def {
def_fn(def_id, purity),
def_static_method(/* method */ def_id,
- /* trait */ def_id,
+ /* trait */ Option<def_id>,
purity),
def_self(node_id),
def_mod(def_id),
use dvec::DVec;
+use std::serialization::{Serializable,
+ Deserializable,
+ Serializer,
+ Deserializer};
export filename;
export filemap;
pure fn ne(other: &span) -> bool { !self.eq(other) }
}
+#[cfg(stage0)]
+impl span: Serializable {
+ /* Note #1972 -- spans are serialized but not deserialized */
+ fn serialize<S: Serializer>(&self, _s: &S) { }
+}
+
+#[cfg(stage0)]
+impl span: Deserializable {
+ static fn deserialize<D: Deserializer>(_d: &D) -> span {
+ ast_util::dummy_sp()
+ }
+}
+
+#[cfg(stage1)]
+#[cfg(stage2)]
+impl<S: Serializer> span: Serializable<S> {
+ /* Note #1972 -- spans are serialized but not deserialized */
+ fn serialize(&self, _s: &S) { }
+}
+
+#[cfg(stage1)]
+#[cfg(stage2)]
+impl<D: Deserializer> span: Deserializable<D> {
+ static fn deserialize(_d: &D) -> span {
+ ast_util::dummy_sp()
+ }
+}
+
fn span_to_str_no_adj(sp: span, cm: CodeMap) -> ~str {
let lo = lookup_char_pos(cm, sp.lo);
let hi = lookup_char_pos(cm, sp.hi);
const tag_item_trait_method_sort: uint = 0x70;
+const tag_item_impl_type_basename: uint = 0x71;
+
type link_meta = {name: ~str, vers: ~str, extras_hash: ~str};
export get_trait_methods;
export get_provided_trait_methods;
export get_method_names_if_trait;
+export get_type_name_if_impl;
+export get_static_methods_if_impl;
export get_item_attrs;
export each_path;
export get_type;
export get_item_path;
export maybe_get_item_ast, found_ast, found, found_parent, not_found;
export ProvidedTraitMethodInfo;
+export StaticMethodInfo;
struct ProvidedTraitMethodInfo {
ty: ty::method,
def_id: ast::def_id
}
+struct StaticMethodInfo {
+ ident: ast::ident,
+ def_id: ast::def_id,
+ purity: ast::purity
+}
+
fn get_symbol(cstore: cstore::CStore, def: ast::def_id) -> ~str {
let cdata = cstore::get_crate_data(cstore, def.crate).data;
return decoder::get_symbol(cdata, def.node);
return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node);
}
+fn get_type_name_if_impl(cstore: cstore::CStore, def: ast::def_id) ->
+ Option<ast::ident> {
+ let cdata = cstore::get_crate_data(cstore, def.crate);
+ decoder::get_type_name_if_impl(cstore.intr, cdata, def.node)
+}
+
+fn get_static_methods_if_impl(cstore: cstore::CStore, def: ast::def_id) ->
+ Option<~[StaticMethodInfo]> {
+ let cdata = cstore::get_crate_data(cstore, def.crate);
+ decoder::get_static_methods_if_impl(cstore.intr, cdata, def.node)
+}
+
fn get_item_attrs(cstore: cstore::CStore,
def_id: ast::def_id,
f: fn(~[@ast::meta_item])) {
use common::*;
use syntax::parse::token::ident_interner;
use hash::{Hash, HashUtil};
-use csearch::ProvidedTraitMethodInfo;
+use csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
export class_dtor;
export get_class_fields;
export get_impl_traits;
export get_class_method;
export get_impl_method;
+export get_static_methods_if_impl;
export lookup_def;
export resolve_path;
export get_crate_attributes;
export get_trait_methods;
export get_provided_trait_methods;
export get_method_names_if_trait;
+export get_type_name_if_impl;
export get_item_attrs;
export get_crate_module_paths;
export def_like;
None
}
+fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) ->
+ Option<ast::def_id> {
+ let trait_did_opt = item_parent_item(d);
+ trait_did_opt.map(|trait_did| {crate: cnum, node: trait_did.node})
+}
+
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");
PureFn => dl_def(ast::def_fn(did, ast::pure_fn)),
ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)),
UnsafeStaticMethod => {
- let trait_did = item_reqd_and_translated_parent_item(cnum, item);
- dl_def(ast::def_static_method(did, trait_did, ast::unsafe_fn))
+ let trait_did_opt = translated_parent_item_opt(cnum, item);
+ dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn))
}
StaticMethod => {
- let trait_did = item_reqd_and_translated_parent_item(cnum, item);
- dl_def(ast::def_static_method(did, trait_did, ast::impure_fn))
+ let trait_did_opt = translated_parent_item_opt(cnum, item);
+ dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn))
}
PureStaticMethod => {
- let trait_did = item_reqd_and_translated_parent_item(cnum, item);
- dl_def(ast::def_static_method(did, trait_did, ast::pure_fn))
+ let trait_did_opt = translated_parent_item_opt(cnum, item);
+ dl_def(ast::def_static_method(did, trait_did_opt, ast::pure_fn))
}
Type | ForeignType => dl_def(ast::def_ty(did)),
Mod => dl_def(ast::def_mod(did)),
return Some(resulting_methods);
}
+fn get_type_name_if_impl(intr: @ident_interner,
+ cdata: cmd,
+ node_id: ast::node_id) -> Option<ast::ident> {
+ let item = lookup_item(node_id, cdata.data);
+ if item_family(item) != Impl {
+ return None;
+ }
+
+ for ebml::tagged_docs(item, tag_item_impl_type_basename) |doc| {
+ return Some(intr.intern(@str::from_bytes(ebml::doc_data(doc))));
+ }
+
+ return None;
+}
+
+fn get_static_methods_if_impl(intr: @ident_interner,
+ cdata: cmd,
+ node_id: ast::node_id) ->
+ Option<~[StaticMethodInfo]> {
+ let item = lookup_item(node_id, cdata.data);
+ if item_family(item) != Impl {
+ return None;
+ }
+
+ // If this impl has a trait ref, don't consider it.
+ for ebml::tagged_docs(item, tag_impl_trait) |_doc| {
+ return None;
+ }
+
+ let impl_method_ids = DVec();
+ for ebml::tagged_docs(item, tag_item_impl_method) |impl_method_doc| {
+ impl_method_ids.push(parse_def_id(ebml::doc_data(impl_method_doc)));
+ }
+
+ let static_impl_methods = DVec();
+ 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,
+ _ => fail
+ }
+
+ static_impl_methods.push(StaticMethodInfo {
+ ident: item_name(intr, impl_method_doc),
+ def_id: item_def_id(impl_method_doc, cdata),
+ purity: purity
+ });
+ }
+ _ => {}
+ }
+ }
+
+ return Some(dvec::unwrap(move static_impl_methods));
+}
+
fn get_item_attrs(cdata: cmd,
node_id: ast::node_id,
f: fn(~[@ast::meta_item])) {
ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
}
+fn encode_impl_type_basename(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
+ name: ident) {
+ ebml_w.wr_tagged_str(tag_item_impl_type_basename,
+ ecx.tcx.sess.str_of(name));
+}
+
fn encode_def_id(ebml_w: ebml::Serializer, id: def_id) {
ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
}
ecx.tcx.sess.str_of(m.ident), all_tps.len());
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(m.id));
- encode_family(ebml_w, purity_fn_family(m.purity));
+ match m.self_ty.node {
+ ast::sty_static => {
+ encode_family(ebml_w, purity_static_method_family(m.purity));
+ }
+ _ => encode_family(ebml_w, purity_fn_family(m.purity))
+ }
encode_type_param_bounds(ebml_w, ecx, all_tps);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
encode_name(ecx, ebml_w, m.ident);
encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag();
}
- item_impl(tps, opt_trait, _, methods) => {
+ item_impl(tps, opt_trait, ty, methods) => {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ecx, ebml_w, item.ident);
encode_attributes(ebml_w, item.attrs);
+ match ty.node {
+ ast::ty_path(path, _) if path.idents.len() == 1 => {
+ encode_impl_type_basename(ecx, ebml_w,
+ ast_util::path_to_ident(path));
+ }
+ _ => {}
+ }
for methods.each |m| {
ebml_w.start_tag(tag_item_impl_method);
ebml_w.writer.write(str::to_bytes(def_to_str(local_def(m.id))));
fn tr(xcx: extended_decode_ctxt) -> ast::def {
match self {
ast::def_fn(did, p) => { ast::def_fn(did.tr(xcx), p) }
- ast::def_static_method(did, did2, p) => {
- ast::def_static_method(did.tr(xcx), did2.tr(xcx), p)
+ ast::def_static_method(did, did2_opt, p) => {
+ ast::def_static_method(did.tr(xcx),
+ did2_opt.map(|did2| did2.tr(xcx)),
+ p)
}
ast::def_self(nid) => { ast::def_self(xcx.tr_id(nid)) }
ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) }
use driver::session::Session;
use metadata::csearch::{each_path, get_method_names_if_trait};
+use metadata::csearch::{get_static_methods_if_impl, get_type_name_if_impl};
use metadata::cstore::find_use_stmt_cnum;
use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
use middle::lang_items::LanguageItems;
fn build_reduced_graph_for_item(item: @item,
parent: ReducedGraphParent,
&&visitor: vt<ReducedGraphParent>) {
-
let ident = item.ident;
let sp = item.span;
let legacy = match parent {
self.add_child(ident, new_parent,
ForbidDuplicateValues, ty_m.span);
let def = def_static_method(local_def(ty_m.id),
- local_def(item.id),
+ Some(local_def(item.id)),
ty_m.purity);
(*method_name_bindings).define_value
(Public, def, ty_m.span);
current_module = (*child_name_bindings).get_module();
}
- // Add the new child item.
- let (child_name_bindings, new_parent) =
- self.add_child(final_ident,
- ModuleReducedGraphParent(current_module),
- OverwriteDuplicates,
- dummy_sp());
-
match path_entry.def_like {
dl_def(def) => {
+ // Add the new child item.
+ let (child_name_bindings, new_parent) =
+ self.add_child(final_ident,
+ ModuleReducedGraphParent(
+ current_module),
+ OverwriteDuplicates,
+ dummy_sp());
+
self.handle_external_def(def, modules,
child_name_bindings,
self.session.str_of(final_ident),
final_ident, new_parent);
}
- dl_impl(_) => {
+ dl_impl(def) => {
// We only process static methods of impls here.
debug!("(building reduced graph for external crate) \
processing impl %s", final_ident_str);
- // FIXME (#3786): Cross-crate static methods in anonymous
- // traits.
+ match get_type_name_if_impl(self.session.cstore, def) {
+ None => {}
+ Some(final_ident) => {
+ let static_methods_opt =
+ get_static_methods_if_impl(
+ self.session.cstore, def);
+ match static_methods_opt {
+ Some(static_methods) if
+ static_methods.len() >= 1 => {
+ debug!("(building reduced graph for \
+ external crate) processing \
+ static methods for type name %s",
+ self.session.str_of(final_ident));
+
+ let (child_name_bindings, new_parent) =
+ self.add_child(final_ident,
+ ModuleReducedGraphParent(
+ current_module),
+ OverwriteDuplicates,
+ dummy_sp());
+
+ // Process the static methods. First,
+ // create the module.
+ let type_module;
+ match copy child_name_bindings.type_def {
+ Some(TypeNsDef {
+ module_def: Some(copy module_def),
+ _
+ }) => {
+ // We already have a module. This
+ // is OK.
+ type_module = module_def;
+ }
+ Some(_) | None => {
+ let parent_link =
+ self.get_parent_link(
+ new_parent, final_ident);
+ child_name_bindings.define_module(
+ Public,
+ parent_link,
+ Some(def),
+ false,
+ dummy_sp());
+ type_module =
+ child_name_bindings.
+ get_module();
+ }
+ }
+
+ // Add each static method to the module.
+ let new_parent = ModuleReducedGraphParent(
+ type_module);
+ for static_methods.each
+ |static_method_info| {
+ let ident = static_method_info.ident;
+ debug!("(building reduced graph for \
+ external crate) creating \
+ static method '%s'",
+ self.session.str_of(ident));
+
+ let (method_name_bindings, _) =
+ self.add_child(
+ ident,
+ new_parent,
+ OverwriteDuplicates,
+ dummy_sp());
+ let def = def_fn(
+ static_method_info.def_id,
+ static_method_info.purity);
+ method_name_bindings.define_value(
+ Public, def, dummy_sp());
+ }
+ }
+
+ // Otherwise, do nothing.
+ Some(_) | None => {}
+ }
+ }
+ }
}
dl_field => {
debug!("(building reduced graph for external crate) \
module_path: @DVec<ident>,
subclass: @ImportDirectiveSubclass,
span: span) {
-
let directive = @ImportDirective(privacy, module_path,
subclass, span);
module_.imports.push(directive);
xray: XrayFlag,
span: span)
-> ResolveResult<@Module> {
-
let mut search_module = module_;
let mut index = index;
let module_path_len = (*module_path).len();
fn resolve_module_in_lexical_scope(module_: @Module, name: ident)
-> ResolveResult<@Module> {
-
match self.resolve_item_in_lexical_scope(module_, name, TypeNS) {
Success(target) => {
match target.bindings.type_def {
match self.resolve_path(path, TypeNS, true, visitor) {
Some(def) => {
debug!("(resolving type) resolved `%s` to \
- type",
+ type %?",
self.session.str_of(
- path.idents.last()));
+ path.idents.last()),
+ def);
result_def = Some(def);
}
None => {
fn trans_def(bcx: block, def: ast::def, ref_expr: @ast::expr) -> Callee {
match def {
- ast::def_fn(did, _) => {
+ ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id))
}
- ast::def_static_method(impl_did, trait_did, _) => {
+ ast::def_static_method(impl_did, Some(trait_did), _) => {
fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did,
trait_did,
ref_expr.id))
};
match def {
- ast::def_fn(did, _) => {
+ ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id);
return fn_data_to_datum(bcx, did, fn_data, lldest);
}
- ast::def_static_method(impl_did, trait_did, _) => {
+ ast::def_static_method(impl_did, Some(trait_did), _) => {
let fn_data = meth::trans_static_method_callee(bcx, impl_did,
trait_did,
ref_expr.id);
--- /dev/null
+pub struct Foo {
+ x: int
+}
+
+pub impl Foo {
+ static fn new() -> Foo {
+ Foo { x: 3 }
+ }
+}
+
--- /dev/null
+// xfail-fast - check-fast doesn't understand aux-build
+// aux-build:anon_trait_static_method_lib.rs
+
+extern mod anon_trait_static_method_lib;
+use anon_trait_static_method_lib::Foo;
+
+fn main() {
+ let x = Foo::new();
+ io::println(x.x.to_str());
+}
+
+
+