Skip to content

Commit 531a3c6

Browse files
committed
rustdoc: show struct field docs when inlined
Some minor changes to the compiler to expose this information. Very inconvenient since struct fields aren't an item. Adds (yet another) table to metadata. Closes #15739
1 parent 79e9f14 commit 531a3c6

File tree

8 files changed

+67
-6
lines changed

8 files changed

+67
-6
lines changed

src/librustc/metadata/common.rs

+4
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,7 @@ pub static tag_region_param_def_index: uint = 0x94;
227227
pub static tag_unboxed_closures: uint = 0x95;
228228
pub static tag_unboxed_closure: uint = 0x96;
229229
pub static tag_unboxed_closure_type: uint = 0x97;
230+
231+
pub static tag_struct_fields: uint = 0x98;
232+
pub static tag_struct_field: uint = 0x99;
233+
pub static tag_struct_field_id: uint = 0x9a;

src/librustc/metadata/csearch.rs

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use syntax::attr;
2929
use syntax::diagnostic::expect;
3030
use syntax::parse::token;
3131

32+
use std::collections::hashmap::HashMap;
33+
3234
pub struct StaticMethodInfo {
3335
pub ident: ast::Ident,
3436
pub def_id: ast::DefId,
@@ -192,6 +194,12 @@ pub fn get_struct_fields(cstore: &cstore::CStore,
192194
decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
193195
}
194196

197+
pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: ast::DefId) -> HashMap<ast::NodeId,
198+
Vec<ast::Attribute>> {
199+
let cdata = cstore.get_crate_data(def.krate);
200+
decoder::get_struct_field_attrs(&*cdata)
201+
}
202+
195203
pub fn get_type(tcx: &ty::ctxt,
196204
def: ast::DefId)
197205
-> ty::Polytype {

src/librustc/metadata/decoder.rs

+14
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use std::hash::Hash;
3434
use std::hash;
3535
use std::io::extensions::u64_from_be_bytes;
3636
use std::io;
37+
use std::collections::hashmap::HashMap;
3738
use std::rc::Rc;
3839
use std::u64;
3940
use serialize::ebml::reader;
@@ -963,6 +964,19 @@ pub fn get_item_attrs(cdata: Cmd,
963964
f(get_attributes(item));
964965
}
965966

967+
pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<ast::Attribute>> {
968+
let data = ebml::Doc::new(cdata.data());
969+
let fields = reader::get_doc(data, tag_struct_fields);
970+
let mut map = HashMap::new();
971+
reader::tagged_docs(fields, tag_struct_field, |field| {
972+
let id = reader::doc_as_u32(reader::get_doc(field, tag_struct_field_id));
973+
let attrs = get_attributes(field);
974+
map.insert(id, attrs);
975+
true
976+
});
977+
map
978+
}
979+
966980
fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
967981
match family {
968982
PublicField => ast::Public,

src/librustc/metadata/encoder.rs

+25
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,29 @@ fn encode_unboxed_closures<'a>(
16441644
ebml_w.end_tag();
16451645
}
16461646

1647+
fn encode_struct_field_attrs(ebml_w: &mut Encoder, krate: &Crate) {
1648+
struct StructFieldVisitor<'a, 'b> {
1649+
ebml_w: &'a mut Encoder<'b>,
1650+
}
1651+
1652+
impl<'a, 'b> Visitor<()> for StructFieldVisitor<'a, 'b> {
1653+
fn visit_struct_field(&mut self, field: &ast::StructField, _: ()) {
1654+
self.ebml_w.start_tag(tag_struct_field);
1655+
self.ebml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1656+
encode_attributes(self.ebml_w, field.node.attrs.as_slice());
1657+
self.ebml_w.end_tag();
1658+
}
1659+
}
1660+
1661+
ebml_w.start_tag(tag_struct_fields);
1662+
visit::walk_crate(&mut StructFieldVisitor {
1663+
ebml_w: ebml_w
1664+
}, krate, ());
1665+
ebml_w.end_tag();
1666+
}
1667+
1668+
1669+
16471670
struct ImplVisitor<'a,'b,'c> {
16481671
ecx: &'a EncodeContext<'b>,
16491672
ebml_w: &'a mut Encoder<'c>,
@@ -1928,6 +1951,8 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
19281951
stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
19291952
ebml_w.end_tag();
19301953

1954+
encode_struct_field_attrs(&mut ebml_w, krate);
1955+
19311956
stats.total_bytes = ebml_w.writer.tell().unwrap();
19321957

19331958
if tcx.sess.meta_stats() {

src/librustc/middle/ty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4071,7 +4071,7 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
40714071

40724072
let len = results.as_slice().iter().map(|x| x.len()).sum();
40734073
let mut result: Vec<field_ty> = Vec::with_capacity(len);
4074-
result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|&f| f)));
4074+
result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|f| f.clone())));
40754075
assert!(result.len() == len);
40764076
result
40774077
} else {
@@ -4085,7 +4085,7 @@ pub fn lookup_struct_field(cx: &ctxt,
40854085
-> field_ty {
40864086
let r = lookup_struct_fields(cx, parent);
40874087
match r.iter().find(|f| f.id.node == field_id.node) {
4088-
Some(t) => *t,
4088+
Some(t) => t.clone(),
40894089
None => cx.sess.bug("struct ID not found in parent's fields")
40904090
}
40914091
}

src/librustc/middle/typeck/check/_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
322322
}
323323
Some(&(index, ref mut used)) => {
324324
*used = true;
325-
let class_field = *class_fields.get(index);
325+
let class_field = class_fields.get(index).clone();
326326
let field_type = ty::lookup_field_type(tcx,
327327
class_id,
328328
class_field.id,

src/librustdoc/clean/inline.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
209209
_ => doctree::Plain,
210210
},
211211
generics: (&t.generics, subst::TypeSpace).clean(),
212-
fields: fields.iter().map(|f| f.clean()).collect(),
212+
fields: fields.clean(),
213213
fields_stripped: false,
214214
}
215215
}

src/librustdoc/clean/mod.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1320,16 +1320,26 @@ impl Clean<Item> for ast::StructField {
13201320
impl Clean<Item> for ty::field_ty {
13211321
fn clean(&self) -> Item {
13221322
use syntax::parse::token::special_idents::unnamed_field;
1323+
use rustc::metadata::csearch;
1324+
1325+
let cx = get_cx();
1326+
let attrs;
1327+
1328+
let attr_map = csearch::get_struct_field_attrs(&cx.tcx().sess.cstore, self.id);
1329+
13231330
let name = if self.name == unnamed_field.name {
1331+
attrs = None;
13241332
None
13251333
} else {
1334+
attrs = Some(attr_map.find(&self.id.node).unwrap());
13261335
Some(self.name)
13271336
};
1328-
let cx = get_cx();
1337+
13291338
let ty = ty::lookup_item_type(cx.tcx(), self.id);
1339+
13301340
Item {
13311341
name: name.clean(),
1332-
attrs: inline::load_attrs(cx.tcx(), self.id),
1342+
attrs: attrs.unwrap_or(&Vec::new()).clean(),
13331343
source: Span::empty(),
13341344
visibility: Some(self.vis),
13351345
stability: get_stability(self.id),

0 commit comments

Comments
 (0)