提交 754704ea 编写于 作者: P Patrick Walton

rustc: Implement intra-crate static methods on anonymous trait implementations. r=nmatsakis

上级 eeae5520
......@@ -7,34 +7,6 @@
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};
......@@ -168,7 +140,7 @@ enum ty_param_bound {
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;
......@@ -178,6 +182,34 @@ impl span : cmp::Eq {
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);
......
......@@ -126,5 +126,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f
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};
......@@ -25,6 +25,8 @@
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;
......@@ -33,12 +35,19 @@
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);
......@@ -120,6 +129,18 @@ fn get_method_names_if_trait(cstore: cstore::CStore, def: ast::def_id)
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])) {
......
......@@ -19,7 +19,7 @@
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;
......@@ -31,6 +31,7 @@
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;
......@@ -43,6 +44,7 @@
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;
......@@ -185,6 +187,12 @@ fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
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");
......@@ -321,16 +329,16 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
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)),
......@@ -783,6 +791,67 @@ fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd,
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])) {
......
......@@ -90,6 +90,12 @@ fn encode_name(ecx: @encode_ctxt, ebml_w: ebml::Serializer, name: ident) {
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));
}
......@@ -484,7 +490,12 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
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);
......@@ -701,7 +712,7 @@ fn add_to_index_(item: @item, ebml_w: ebml::Serializer,
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));
......@@ -711,6 +722,13 @@ fn add_to_index_(item: @item, ebml_w: ebml::Serializer,
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))));
......
......@@ -326,8 +326,10 @@ impl ast::def: tr {
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;
......@@ -1082,7 +1083,6 @@ fn get_parent_link(parent: ReducedGraphParent,
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 {
......@@ -1276,7 +1276,7 @@ fn build_reduced_graph_for_item(item: @item,
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);
......@@ -1734,27 +1734,105 @@ fn build_reduced_graph_for_external_crate(root: @Module) {
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) \
......@@ -1770,7 +1848,6 @@ fn build_import_directive(privacy: Privacy,
module_path: @DVec<ident>,
subclass: @ImportDirectiveSubclass,
span: span) {
let directive = @ImportDirective(privacy, module_path,
subclass, span);
module_.imports.push(directive);
......@@ -2453,7 +2530,6 @@ fn resolve_module_path_from_root(module_: @Module,
xray: XrayFlag,
span: span)
-> ResolveResult<@Module> {
let mut search_module = module_;
let mut index = index;
let module_path_len = (*module_path).len();
......@@ -2648,7 +2724,6 @@ fn resolve_item_in_lexical_scope(module_: @Module,
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 {
......@@ -4035,9 +4110,10 @@ fn resolve_type(ty: @Ty, visitor: ResolveVisitor) {
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 => {
......
......@@ -75,10 +75,10 @@ fn fn_callee(bcx: block, fd: FnData) -> Callee {
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))
......
......@@ -637,11 +637,11 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr,
};
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);
......
pub struct Foo {
x: int
}
pub impl Foo {
static fn new() -> Foo {
Foo { x: 3 }
}
}
// 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());
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册