Skip to content

Commit 754704e

Browse files
committed
rustc: Implement intra-crate static methods on anonymous trait implementations. r=nmatsakis
1 parent eeae552 commit 754704e

File tree

12 files changed

+276
-61
lines changed

12 files changed

+276
-61
lines changed

src/libsyntax/ast.rs

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,6 @@ use std::serialization::{Serializable,
77
use codemap::{span, filename};
88
use parse::token;
99

10-
#[cfg(stage0)]
11-
impl span: Serializable {
12-
/* Note #1972 -- spans are serialized but not deserialized */
13-
fn serialize<S: Serializer>(&self, _s: &S) { }
14-
}
15-
16-
#[cfg(stage0)]
17-
impl span: Deserializable {
18-
static fn deserialize<D: Deserializer>(_d: &D) -> span {
19-
ast_util::dummy_sp()
20-
}
21-
}
22-
23-
#[cfg(stage1)]
24-
#[cfg(stage2)]
25-
impl<S: Serializer> span: Serializable<S> {
26-
/* Note #1972 -- spans are serialized but not deserialized */
27-
fn serialize(&self, _s: &S) { }
28-
}
29-
30-
#[cfg(stage1)]
31-
#[cfg(stage2)]
32-
impl<D: Deserializer> span: Deserializable<D> {
33-
static fn deserialize(_d: &D) -> span {
34-
ast_util::dummy_sp()
35-
}
36-
}
37-
3810
#[auto_serialize]
3911
#[auto_deserialize]
4012
type spanned<T> = {node: T, span: span};
@@ -168,7 +140,7 @@ type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]};
168140
enum def {
169141
def_fn(def_id, purity),
170142
def_static_method(/* method */ def_id,
171-
/* trait */ def_id,
143+
/* trait */ Option<def_id>,
172144
purity),
173145
def_self(node_id),
174146
def_mod(def_id),

src/libsyntax/codemap.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
use dvec::DVec;
2+
use std::serialization::{Serializable,
3+
Deserializable,
4+
Serializer,
5+
Deserializer};
26

37
export filename;
48
export filemap;
@@ -178,6 +182,34 @@ impl span : cmp::Eq {
178182
pure fn ne(other: &span) -> bool { !self.eq(other) }
179183
}
180184

185+
#[cfg(stage0)]
186+
impl span: Serializable {
187+
/* Note #1972 -- spans are serialized but not deserialized */
188+
fn serialize<S: Serializer>(&self, _s: &S) { }
189+
}
190+
191+
#[cfg(stage0)]
192+
impl span: Deserializable {
193+
static fn deserialize<D: Deserializer>(_d: &D) -> span {
194+
ast_util::dummy_sp()
195+
}
196+
}
197+
198+
#[cfg(stage1)]
199+
#[cfg(stage2)]
200+
impl<S: Serializer> span: Serializable<S> {
201+
/* Note #1972 -- spans are serialized but not deserialized */
202+
fn serialize(&self, _s: &S) { }
203+
}
204+
205+
#[cfg(stage1)]
206+
#[cfg(stage2)]
207+
impl<D: Deserializer> span: Deserializable<D> {
208+
static fn deserialize(_d: &D) -> span {
209+
ast_util::dummy_sp()
210+
}
211+
}
212+
181213
fn span_to_str_no_adj(sp: span, cm: CodeMap) -> ~str {
182214
let lo = lookup_char_pos(cm, sp.lo);
183215
let hi = lookup_char_pos(cm, sp.hi);

src/rustc/metadata/common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f
126126

127127
const tag_item_trait_method_sort: uint = 0x70;
128128

129+
const tag_item_impl_type_basename: uint = 0x71;
130+
129131
type link_meta = {name: ~str, vers: ~str, extras_hash: ~str};
130132

src/rustc/metadata/csearch.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export get_impls_for_mod;
2525
export get_trait_methods;
2626
export get_provided_trait_methods;
2727
export get_method_names_if_trait;
28+
export get_type_name_if_impl;
29+
export get_static_methods_if_impl;
2830
export get_item_attrs;
2931
export each_path;
3032
export get_type;
@@ -33,12 +35,19 @@ export get_impl_method;
3335
export get_item_path;
3436
export maybe_get_item_ast, found_ast, found, found_parent, not_found;
3537
export ProvidedTraitMethodInfo;
38+
export StaticMethodInfo;
3639

3740
struct ProvidedTraitMethodInfo {
3841
ty: ty::method,
3942
def_id: ast::def_id
4043
}
4144

45+
struct StaticMethodInfo {
46+
ident: ast::ident,
47+
def_id: ast::def_id,
48+
purity: ast::purity
49+
}
50+
4251
fn get_symbol(cstore: cstore::CStore, def: ast::def_id) -> ~str {
4352
let cdata = cstore::get_crate_data(cstore, def.crate).data;
4453
return decoder::get_symbol(cdata, def.node);
@@ -120,6 +129,18 @@ fn get_method_names_if_trait(cstore: cstore::CStore, def: ast::def_id)
120129
return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node);
121130
}
122131

132+
fn get_type_name_if_impl(cstore: cstore::CStore, def: ast::def_id) ->
133+
Option<ast::ident> {
134+
let cdata = cstore::get_crate_data(cstore, def.crate);
135+
decoder::get_type_name_if_impl(cstore.intr, cdata, def.node)
136+
}
137+
138+
fn get_static_methods_if_impl(cstore: cstore::CStore, def: ast::def_id) ->
139+
Option<~[StaticMethodInfo]> {
140+
let cdata = cstore::get_crate_data(cstore, def.crate);
141+
decoder::get_static_methods_if_impl(cstore.intr, cdata, def.node)
142+
}
143+
123144
fn get_item_attrs(cstore: cstore::CStore,
124145
def_id: ast::def_id,
125146
f: fn(~[@ast::meta_item])) {

src/rustc/metadata/decoder.rs

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use syntax::diagnostic::span_handler;
1919
use common::*;
2020
use syntax::parse::token::ident_interner;
2121
use hash::{Hash, HashUtil};
22-
use csearch::ProvidedTraitMethodInfo;
22+
use csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
2323

2424
export class_dtor;
2525
export get_class_fields;
@@ -31,6 +31,7 @@ export get_type_param_count;
3131
export get_impl_traits;
3232
export get_class_method;
3333
export get_impl_method;
34+
export get_static_methods_if_impl;
3435
export lookup_def;
3536
export resolve_path;
3637
export get_crate_attributes;
@@ -43,6 +44,7 @@ export get_impls_for_mod;
4344
export get_trait_methods;
4445
export get_provided_trait_methods;
4546
export get_method_names_if_trait;
47+
export get_type_name_if_impl;
4648
export get_item_attrs;
4749
export get_crate_module_paths;
4850
export def_like;
@@ -185,6 +187,12 @@ fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
185187
None
186188
}
187189

190+
fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) ->
191+
Option<ast::def_id> {
192+
let trait_did_opt = item_parent_item(d);
193+
trait_did_opt.map(|trait_did| {crate: cnum, node: trait_did.node})
194+
}
195+
188196
fn item_reqd_and_translated_parent_item(cnum: ast::crate_num,
189197
d: ebml::Doc) -> ast::def_id {
190198
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)
321329
PureFn => dl_def(ast::def_fn(did, ast::pure_fn)),
322330
ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)),
323331
UnsafeStaticMethod => {
324-
let trait_did = item_reqd_and_translated_parent_item(cnum, item);
325-
dl_def(ast::def_static_method(did, trait_did, ast::unsafe_fn))
332+
let trait_did_opt = translated_parent_item_opt(cnum, item);
333+
dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn))
326334
}
327335
StaticMethod => {
328-
let trait_did = item_reqd_and_translated_parent_item(cnum, item);
329-
dl_def(ast::def_static_method(did, trait_did, ast::impure_fn))
336+
let trait_did_opt = translated_parent_item_opt(cnum, item);
337+
dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn))
330338
}
331339
PureStaticMethod => {
332-
let trait_did = item_reqd_and_translated_parent_item(cnum, item);
333-
dl_def(ast::def_static_method(did, trait_did, ast::pure_fn))
340+
let trait_did_opt = translated_parent_item_opt(cnum, item);
341+
dl_def(ast::def_static_method(did, trait_did_opt, ast::pure_fn))
334342
}
335343
Type | ForeignType => dl_def(ast::def_ty(did)),
336344
Mod => dl_def(ast::def_mod(did)),
@@ -783,6 +791,67 @@ fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd,
783791
return Some(resulting_methods);
784792
}
785793

794+
fn get_type_name_if_impl(intr: @ident_interner,
795+
cdata: cmd,
796+
node_id: ast::node_id) -> Option<ast::ident> {
797+
let item = lookup_item(node_id, cdata.data);
798+
if item_family(item) != Impl {
799+
return None;
800+
}
801+
802+
for ebml::tagged_docs(item, tag_item_impl_type_basename) |doc| {
803+
return Some(intr.intern(@str::from_bytes(ebml::doc_data(doc))));
804+
}
805+
806+
return None;
807+
}
808+
809+
fn get_static_methods_if_impl(intr: @ident_interner,
810+
cdata: cmd,
811+
node_id: ast::node_id) ->
812+
Option<~[StaticMethodInfo]> {
813+
let item = lookup_item(node_id, cdata.data);
814+
if item_family(item) != Impl {
815+
return None;
816+
}
817+
818+
// If this impl has a trait ref, don't consider it.
819+
for ebml::tagged_docs(item, tag_impl_trait) |_doc| {
820+
return None;
821+
}
822+
823+
let impl_method_ids = DVec();
824+
for ebml::tagged_docs(item, tag_item_impl_method) |impl_method_doc| {
825+
impl_method_ids.push(parse_def_id(ebml::doc_data(impl_method_doc)));
826+
}
827+
828+
let static_impl_methods = DVec();
829+
for impl_method_ids.each |impl_method_id| {
830+
let impl_method_doc = lookup_item(impl_method_id.node, cdata.data);
831+
let family = item_family(impl_method_doc);
832+
match family {
833+
StaticMethod | UnsafeStaticMethod | PureStaticMethod => {
834+
let purity;
835+
match item_family(impl_method_doc) {
836+
StaticMethod => purity = ast::impure_fn,
837+
UnsafeStaticMethod => purity = ast::unsafe_fn,
838+
PureStaticMethod => purity = ast::pure_fn,
839+
_ => fail
840+
}
841+
842+
static_impl_methods.push(StaticMethodInfo {
843+
ident: item_name(intr, impl_method_doc),
844+
def_id: item_def_id(impl_method_doc, cdata),
845+
purity: purity
846+
});
847+
}
848+
_ => {}
849+
}
850+
}
851+
852+
return Some(dvec::unwrap(move static_impl_methods));
853+
}
854+
786855
fn get_item_attrs(cdata: cmd,
787856
node_id: ast::node_id,
788857
f: fn(~[@ast::meta_item])) {

src/rustc/metadata/encoder.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ fn encode_name(ecx: @encode_ctxt, ebml_w: ebml::Serializer, name: ident) {
9090
ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
9191
}
9292

93+
fn encode_impl_type_basename(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
94+
name: ident) {
95+
ebml_w.wr_tagged_str(tag_item_impl_type_basename,
96+
ecx.tcx.sess.str_of(name));
97+
}
98+
9399
fn encode_def_id(ebml_w: ebml::Serializer, id: def_id) {
94100
ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
95101
}
@@ -484,7 +490,12 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
484490
ecx.tcx.sess.str_of(m.ident), all_tps.len());
485491
ebml_w.start_tag(tag_items_data_item);
486492
encode_def_id(ebml_w, local_def(m.id));
487-
encode_family(ebml_w, purity_fn_family(m.purity));
493+
match m.self_ty.node {
494+
ast::sty_static => {
495+
encode_family(ebml_w, purity_static_method_family(m.purity));
496+
}
497+
_ => encode_family(ebml_w, purity_fn_family(m.purity))
498+
}
488499
encode_type_param_bounds(ebml_w, ecx, all_tps);
489500
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
490501
encode_name(ecx, ebml_w, m.ident);
@@ -701,7 +712,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
701712
encode_index(ebml_w, bkts, write_int);
702713
ebml_w.end_tag();
703714
}
704-
item_impl(tps, opt_trait, _, methods) => {
715+
item_impl(tps, opt_trait, ty, methods) => {
705716
add_to_index();
706717
ebml_w.start_tag(tag_items_data_item);
707718
encode_def_id(ebml_w, local_def(item.id));
@@ -711,6 +722,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
711722
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
712723
encode_name(ecx, ebml_w, item.ident);
713724
encode_attributes(ebml_w, item.attrs);
725+
match ty.node {
726+
ast::ty_path(path, _) if path.idents.len() == 1 => {
727+
encode_impl_type_basename(ecx, ebml_w,
728+
ast_util::path_to_ident(path));
729+
}
730+
_ => {}
731+
}
714732
for methods.each |m| {
715733
ebml_w.start_tag(tag_item_impl_method);
716734
ebml_w.writer.write(str::to_bytes(def_to_str(local_def(m.id))));

src/rustc/middle/astencode.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,10 @@ impl ast::def: tr {
326326
fn tr(xcx: extended_decode_ctxt) -> ast::def {
327327
match self {
328328
ast::def_fn(did, p) => { ast::def_fn(did.tr(xcx), p) }
329-
ast::def_static_method(did, did2, p) => {
330-
ast::def_static_method(did.tr(xcx), did2.tr(xcx), p)
329+
ast::def_static_method(did, did2_opt, p) => {
330+
ast::def_static_method(did.tr(xcx),
331+
did2_opt.map(|did2| did2.tr(xcx)),
332+
p)
331333
}
332334
ast::def_self(nid) => { ast::def_self(xcx.tr_id(nid)) }
333335
ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) }

0 commit comments

Comments
 (0)