Skip to content

Commit 8d2e716

Browse files
committed
auto merge of #16025 : cmr/rust/plugin-fields, r=alexcrichton
Some minor changes to the compiler to expose this information. Very inconvenient since struct fields aren't an item.
2 parents f4ef36e + 8876ce4 commit 8d2e716

File tree

8 files changed

+98
-31
lines changed

8 files changed

+98
-31
lines changed

src/librustc/metadata/common.rs

+6
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,9 @@ 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;
234+
235+
pub static tag_attribute_is_sugared_doc: uint = 0x9b;

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

+18-1
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,
@@ -1042,6 +1056,9 @@ fn get_attributes(md: ebml::Doc) -> Vec<ast::Attribute> {
10421056
match reader::maybe_get_doc(md, tag_attributes) {
10431057
Some(attrs_d) => {
10441058
reader::tagged_docs(attrs_d, tag_attribute, |attr_doc| {
1059+
let is_sugared_doc = reader::doc_as_u8(
1060+
reader::get_doc(attr_doc, tag_attribute_is_sugared_doc)
1061+
) == 1;
10451062
let meta_items = get_meta_items(attr_doc);
10461063
// Currently it's only possible to have a single meta item on
10471064
// an attribute
@@ -1053,7 +1070,7 @@ fn get_attributes(md: ebml::Doc) -> Vec<ast::Attribute> {
10531070
id: attr::mk_attr_id(),
10541071
style: ast::AttrOuter,
10551072
value: meta_item,
1056-
is_sugared_doc: false,
1073+
is_sugared_doc: is_sugared_doc,
10571074
},
10581075
span: codemap::DUMMY_SP
10591076
});

src/librustc/metadata/encoder.rs

+26
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,7 @@ fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
14901490
ebml_w.start_tag(tag_attributes);
14911491
for attr in attrs.iter() {
14921492
ebml_w.start_tag(tag_attribute);
1493+
ebml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
14931494
encode_meta_item(ebml_w, attr.node.value);
14941495
ebml_w.end_tag();
14951496
}
@@ -1644,6 +1645,29 @@ fn encode_unboxed_closures<'a>(
16441645
ebml_w.end_tag();
16451646
}
16461647

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

1955+
encode_struct_field_attrs(&mut ebml_w, krate);
1956+
19311957
stats.total_bytes = ebml_w.writer.tell().unwrap();
19321958

19331959
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

+36-26
Original file line numberDiff line numberDiff line change
@@ -347,18 +347,18 @@ impl Clean<Item> for doctree::Module {
347347
}
348348
}
349349
let items: Vec<Vec<Item> > = vec!(
350-
self.structs.clean().move_iter().collect(),
351-
self.enums.clean().move_iter().collect(),
352-
self.fns.clean().move_iter().collect(),
350+
self.structs.clean(),
351+
self.enums.clean(),
352+
self.fns.clean(),
353353
foreigns,
354-
self.mods.clean().move_iter().collect(),
355-
self.typedefs.clean().move_iter().collect(),
356-
self.statics.clean().move_iter().collect(),
357-
self.traits.clean().move_iter().collect(),
358-
self.impls.clean().move_iter().collect(),
354+
self.mods.clean(),
355+
self.typedefs.clean(),
356+
self.statics.clean(),
357+
self.traits.clean(),
358+
self.impls.clean(),
359359
self.view_items.clean().move_iter()
360360
.flat_map(|s| s.move_iter()).collect(),
361-
self.macros.clean().move_iter().collect()
361+
self.macros.clean(),
362362
);
363363

364364
// determine if we should display the inner contents or
@@ -406,7 +406,7 @@ impl Clean<Attribute> for ast::MetaItem {
406406
match self.node {
407407
ast::MetaWord(ref s) => Word(s.get().to_string()),
408408
ast::MetaList(ref s, ref l) => {
409-
List(s.get().to_string(), l.clean().move_iter().collect())
409+
List(s.get().to_string(), l.clean())
410410
}
411411
ast::MetaNameValue(ref s, ref v) => {
412412
NameValue(s.get().to_string(), lit_to_string(v))
@@ -460,7 +460,7 @@ impl Clean<TyParam> for ast::TyParam {
460460
TyParam {
461461
name: self.ident.clean(),
462462
did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
463-
bounds: self.bounds.clean().move_iter().collect(),
463+
bounds: self.bounds.clean(),
464464
default: self.default.clean()
465465
}
466466
}
@@ -688,7 +688,7 @@ impl Clean<Item> for ast::Method {
688688
};
689689
Item {
690690
name: Some(self.pe_ident().clean()),
691-
attrs: self.attrs.clean().move_iter().collect(),
691+
attrs: self.attrs.clean(),
692692
source: self.span.clean(),
693693
def_id: ast_util::local_def(self.id),
694694
visibility: self.pe_vis().clean(),
@@ -727,7 +727,7 @@ impl Clean<Item> for ast::TypeMethod {
727727
};
728728
Item {
729729
name: Some(self.ident.clean()),
730-
attrs: self.attrs.clean().move_iter().collect(),
730+
attrs: self.attrs.clean(),
731731
source: self.span.clean(),
732732
def_id: ast_util::local_def(self.id),
733733
visibility: None,
@@ -805,7 +805,7 @@ impl Clean<ClosureDecl> for ast::ClosureTy {
805805
onceness: self.onceness,
806806
fn_style: self.fn_style,
807807
bounds: match self.bounds {
808-
Some(ref x) => x.clean().move_iter().collect(),
808+
Some(ref x) => x.clean(),
809809
None => Vec::new()
810810
},
811811
}
@@ -1178,7 +1178,7 @@ impl Clean<Type> for ast::Ty {
11781178
TyTup(ref tys) => Tuple(tys.iter().map(|x| x.clean()).collect()),
11791179
TyPath(ref p, ref tpbs, id) => {
11801180
resolve_type(p.clean(),
1181-
tpbs.clean().map(|x| x.move_iter().collect()),
1181+
tpbs.clean().map(|x| x),
11821182
id)
11831183
}
11841184
TyClosure(ref c, region) => Closure(box c.clean(), region.clean()),
@@ -1307,7 +1307,7 @@ impl Clean<Item> for ast::StructField {
13071307
};
13081308
Item {
13091309
name: name.clean(),
1310-
attrs: self.node.attrs.clean().move_iter().collect(),
1310+
attrs: self.node.attrs.clean(),
13111311
source: self.span.clean(),
13121312
visibility: Some(vis),
13131313
stability: get_stability(ast_util::local_def(self.node.id)),
@@ -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),
@@ -1388,7 +1398,7 @@ impl Clean<VariantStruct> for syntax::ast::StructDef {
13881398
fn clean(&self) -> VariantStruct {
13891399
VariantStruct {
13901400
struct_type: doctree::struct_type_from_def(self),
1391-
fields: self.fields.clean().move_iter().collect(),
1401+
fields: self.fields.clean(),
13921402
fields_stripped: false,
13931403
}
13941404
}
@@ -1556,7 +1566,7 @@ impl Clean<Path> for ast::Path {
15561566
fn clean(&self) -> Path {
15571567
Path {
15581568
global: self.global,
1559-
segments: self.segments.clean().move_iter().collect(),
1569+
segments: self.segments.clean(),
15601570
}
15611571
}
15621572
}
@@ -1572,8 +1582,8 @@ impl Clean<PathSegment> for ast::PathSegment {
15721582
fn clean(&self) -> PathSegment {
15731583
PathSegment {
15741584
name: self.identifier.clean(),
1575-
lifetimes: self.lifetimes.clean().move_iter().collect(),
1576-
types: self.types.clean().move_iter().collect()
1585+
lifetimes: self.lifetimes.clean(),
1586+
types: self.types.clean(),
15771587
}
15781588
}
15791589
}
@@ -1640,7 +1650,7 @@ impl Clean<BareFunctionDecl> for ast::BareFnTy {
16401650
BareFunctionDecl {
16411651
fn_style: self.fn_style,
16421652
generics: Generics {
1643-
lifetimes: self.lifetimes.clean().move_iter().collect(),
1653+
lifetimes: self.lifetimes.clean(),
16441654
type_params: Vec::new(),
16451655
},
16461656
decl: self.decl.clean(),
@@ -1745,7 +1755,7 @@ impl Clean<Vec<Item>> for ast::ViewItem {
17451755
let convert = |node: &ast::ViewItem_| {
17461756
Item {
17471757
name: None,
1748-
attrs: self.attrs.clean().move_iter().collect(),
1758+
attrs: self.attrs.clean(),
17491759
source: self.span.clean(),
17501760
def_id: ast_util::local_def(0),
17511761
visibility: self.vis.clean(),
@@ -1840,7 +1850,7 @@ impl Clean<ViewPath> for ast::ViewPath {
18401850
GlobImport(resolve_use_source(p.clean(), id)),
18411851
ast::ViewPathList(ref p, ref pl, id) => {
18421852
ImportList(resolve_use_source(p.clean(), id),
1843-
pl.clean().move_iter().collect())
1853+
pl.clean())
18441854
}
18451855
}
18461856
}
@@ -1893,7 +1903,7 @@ impl Clean<Item> for ast::ForeignItem {
18931903
};
18941904
Item {
18951905
name: Some(self.ident.clean()),
1896-
attrs: self.attrs.clean().move_iter().collect(),
1906+
attrs: self.attrs.clean(),
18971907
source: self.span.clean(),
18981908
def_id: ast_util::local_def(self.id),
18991909
visibility: self.vis.clean(),

0 commit comments

Comments
 (0)