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.
This commit is contained in:
commit
8d2e7161ee
8 changed files with 98 additions and 31 deletions
|
@ -227,3 +227,9 @@ pub static tag_region_param_def_index: uint = 0x94;
|
||||||
pub static tag_unboxed_closures: uint = 0x95;
|
pub static tag_unboxed_closures: uint = 0x95;
|
||||||
pub static tag_unboxed_closure: uint = 0x96;
|
pub static tag_unboxed_closure: uint = 0x96;
|
||||||
pub static tag_unboxed_closure_type: uint = 0x97;
|
pub static tag_unboxed_closure_type: uint = 0x97;
|
||||||
|
|
||||||
|
pub static tag_struct_fields: uint = 0x98;
|
||||||
|
pub static tag_struct_field: uint = 0x99;
|
||||||
|
pub static tag_struct_field_id: uint = 0x9a;
|
||||||
|
|
||||||
|
pub static tag_attribute_is_sugared_doc: uint = 0x9b;
|
||||||
|
|
|
@ -29,6 +29,8 @@ use syntax::attr;
|
||||||
use syntax::diagnostic::expect;
|
use syntax::diagnostic::expect;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
|
||||||
|
use std::collections::hashmap::HashMap;
|
||||||
|
|
||||||
pub struct StaticMethodInfo {
|
pub struct StaticMethodInfo {
|
||||||
pub ident: ast::Ident,
|
pub ident: ast::Ident,
|
||||||
pub def_id: ast::DefId,
|
pub def_id: ast::DefId,
|
||||||
|
@ -192,6 +194,12 @@ pub fn get_struct_fields(cstore: &cstore::CStore,
|
||||||
decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
|
decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: ast::DefId) -> HashMap<ast::NodeId,
|
||||||
|
Vec<ast::Attribute>> {
|
||||||
|
let cdata = cstore.get_crate_data(def.krate);
|
||||||
|
decoder::get_struct_field_attrs(&*cdata)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_type(tcx: &ty::ctxt,
|
pub fn get_type(tcx: &ty::ctxt,
|
||||||
def: ast::DefId)
|
def: ast::DefId)
|
||||||
-> ty::Polytype {
|
-> ty::Polytype {
|
||||||
|
|
|
@ -34,6 +34,7 @@ use std::hash::Hash;
|
||||||
use std::hash;
|
use std::hash;
|
||||||
use std::io::extensions::u64_from_be_bytes;
|
use std::io::extensions::u64_from_be_bytes;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::collections::hashmap::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::u64;
|
use std::u64;
|
||||||
use serialize::ebml::reader;
|
use serialize::ebml::reader;
|
||||||
|
@ -963,6 +964,19 @@ pub fn get_item_attrs(cdata: Cmd,
|
||||||
f(get_attributes(item));
|
f(get_attributes(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<ast::Attribute>> {
|
||||||
|
let data = ebml::Doc::new(cdata.data());
|
||||||
|
let fields = reader::get_doc(data, tag_struct_fields);
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
reader::tagged_docs(fields, tag_struct_field, |field| {
|
||||||
|
let id = reader::doc_as_u32(reader::get_doc(field, tag_struct_field_id));
|
||||||
|
let attrs = get_attributes(field);
|
||||||
|
map.insert(id, attrs);
|
||||||
|
true
|
||||||
|
});
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
|
fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
|
||||||
match family {
|
match family {
|
||||||
PublicField => ast::Public,
|
PublicField => ast::Public,
|
||||||
|
@ -1042,6 +1056,9 @@ fn get_attributes(md: ebml::Doc) -> Vec<ast::Attribute> {
|
||||||
match reader::maybe_get_doc(md, tag_attributes) {
|
match reader::maybe_get_doc(md, tag_attributes) {
|
||||||
Some(attrs_d) => {
|
Some(attrs_d) => {
|
||||||
reader::tagged_docs(attrs_d, tag_attribute, |attr_doc| {
|
reader::tagged_docs(attrs_d, tag_attribute, |attr_doc| {
|
||||||
|
let is_sugared_doc = reader::doc_as_u8(
|
||||||
|
reader::get_doc(attr_doc, tag_attribute_is_sugared_doc)
|
||||||
|
) == 1;
|
||||||
let meta_items = get_meta_items(attr_doc);
|
let meta_items = get_meta_items(attr_doc);
|
||||||
// Currently it's only possible to have a single meta item on
|
// Currently it's only possible to have a single meta item on
|
||||||
// an attribute
|
// an attribute
|
||||||
|
@ -1053,7 +1070,7 @@ fn get_attributes(md: ebml::Doc) -> Vec<ast::Attribute> {
|
||||||
id: attr::mk_attr_id(),
|
id: attr::mk_attr_id(),
|
||||||
style: ast::AttrOuter,
|
style: ast::AttrOuter,
|
||||||
value: meta_item,
|
value: meta_item,
|
||||||
is_sugared_doc: false,
|
is_sugared_doc: is_sugared_doc,
|
||||||
},
|
},
|
||||||
span: codemap::DUMMY_SP
|
span: codemap::DUMMY_SP
|
||||||
});
|
});
|
||||||
|
|
|
@ -1490,6 +1490,7 @@ fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
|
||||||
ebml_w.start_tag(tag_attributes);
|
ebml_w.start_tag(tag_attributes);
|
||||||
for attr in attrs.iter() {
|
for attr in attrs.iter() {
|
||||||
ebml_w.start_tag(tag_attribute);
|
ebml_w.start_tag(tag_attribute);
|
||||||
|
ebml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
|
||||||
encode_meta_item(ebml_w, attr.node.value);
|
encode_meta_item(ebml_w, attr.node.value);
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
@ -1644,6 +1645,29 @@ fn encode_unboxed_closures<'a>(
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_struct_field_attrs(ebml_w: &mut Encoder, krate: &Crate) {
|
||||||
|
struct StructFieldVisitor<'a, 'b> {
|
||||||
|
ebml_w: &'a mut Encoder<'b>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> Visitor<()> for StructFieldVisitor<'a, 'b> {
|
||||||
|
fn visit_struct_field(&mut self, field: &ast::StructField, _: ()) {
|
||||||
|
self.ebml_w.start_tag(tag_struct_field);
|
||||||
|
self.ebml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
|
||||||
|
encode_attributes(self.ebml_w, field.node.attrs.as_slice());
|
||||||
|
self.ebml_w.end_tag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ebml_w.start_tag(tag_struct_fields);
|
||||||
|
visit::walk_crate(&mut StructFieldVisitor {
|
||||||
|
ebml_w: ebml_w
|
||||||
|
}, krate, ());
|
||||||
|
ebml_w.end_tag();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ImplVisitor<'a,'b,'c> {
|
struct ImplVisitor<'a,'b,'c> {
|
||||||
ecx: &'a EncodeContext<'b>,
|
ecx: &'a EncodeContext<'b>,
|
||||||
ebml_w: &'a mut Encoder<'c>,
|
ebml_w: &'a mut Encoder<'c>,
|
||||||
|
@ -1928,6 +1952,8 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
|
||||||
stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
|
stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
|
|
||||||
|
encode_struct_field_attrs(&mut ebml_w, krate);
|
||||||
|
|
||||||
stats.total_bytes = ebml_w.writer.tell().unwrap();
|
stats.total_bytes = ebml_w.writer.tell().unwrap();
|
||||||
|
|
||||||
if tcx.sess.meta_stats() {
|
if tcx.sess.meta_stats() {
|
||||||
|
|
|
@ -4071,7 +4071,7 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
|
||||||
|
|
||||||
let len = results.as_slice().iter().map(|x| x.len()).sum();
|
let len = results.as_slice().iter().map(|x| x.len()).sum();
|
||||||
let mut result: Vec<field_ty> = Vec::with_capacity(len);
|
let mut result: Vec<field_ty> = Vec::with_capacity(len);
|
||||||
result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|&f| f)));
|
result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|f| f.clone())));
|
||||||
assert!(result.len() == len);
|
assert!(result.len() == len);
|
||||||
result
|
result
|
||||||
} else {
|
} else {
|
||||||
|
@ -4085,7 +4085,7 @@ pub fn lookup_struct_field(cx: &ctxt,
|
||||||
-> field_ty {
|
-> field_ty {
|
||||||
let r = lookup_struct_fields(cx, parent);
|
let r = lookup_struct_fields(cx, parent);
|
||||||
match r.iter().find(|f| f.id.node == field_id.node) {
|
match r.iter().find(|f| f.id.node == field_id.node) {
|
||||||
Some(t) => *t,
|
Some(t) => t.clone(),
|
||||||
None => cx.sess.bug("struct ID not found in parent's fields")
|
None => cx.sess.bug("struct ID not found in parent's fields")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,7 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
|
||||||
}
|
}
|
||||||
Some(&(index, ref mut used)) => {
|
Some(&(index, ref mut used)) => {
|
||||||
*used = true;
|
*used = true;
|
||||||
let class_field = *class_fields.get(index);
|
let class_field = class_fields.get(index).clone();
|
||||||
let field_type = ty::lookup_field_type(tcx,
|
let field_type = ty::lookup_field_type(tcx,
|
||||||
class_id,
|
class_id,
|
||||||
class_field.id,
|
class_field.id,
|
||||||
|
|
|
@ -209,7 +209,7 @@ fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
|
||||||
_ => doctree::Plain,
|
_ => doctree::Plain,
|
||||||
},
|
},
|
||||||
generics: (&t.generics, subst::TypeSpace).clean(),
|
generics: (&t.generics, subst::TypeSpace).clean(),
|
||||||
fields: fields.iter().map(|f| f.clean()).collect(),
|
fields: fields.clean(),
|
||||||
fields_stripped: false,
|
fields_stripped: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,18 +347,18 @@ impl Clean<Item> for doctree::Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let items: Vec<Vec<Item> > = vec!(
|
let items: Vec<Vec<Item> > = vec!(
|
||||||
self.structs.clean().move_iter().collect(),
|
self.structs.clean(),
|
||||||
self.enums.clean().move_iter().collect(),
|
self.enums.clean(),
|
||||||
self.fns.clean().move_iter().collect(),
|
self.fns.clean(),
|
||||||
foreigns,
|
foreigns,
|
||||||
self.mods.clean().move_iter().collect(),
|
self.mods.clean(),
|
||||||
self.typedefs.clean().move_iter().collect(),
|
self.typedefs.clean(),
|
||||||
self.statics.clean().move_iter().collect(),
|
self.statics.clean(),
|
||||||
self.traits.clean().move_iter().collect(),
|
self.traits.clean(),
|
||||||
self.impls.clean().move_iter().collect(),
|
self.impls.clean(),
|
||||||
self.view_items.clean().move_iter()
|
self.view_items.clean().move_iter()
|
||||||
.flat_map(|s| s.move_iter()).collect(),
|
.flat_map(|s| s.move_iter()).collect(),
|
||||||
self.macros.clean().move_iter().collect()
|
self.macros.clean(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// determine if we should display the inner contents or
|
// determine if we should display the inner contents or
|
||||||
|
@ -406,7 +406,7 @@ impl Clean<Attribute> for ast::MetaItem {
|
||||||
match self.node {
|
match self.node {
|
||||||
ast::MetaWord(ref s) => Word(s.get().to_string()),
|
ast::MetaWord(ref s) => Word(s.get().to_string()),
|
||||||
ast::MetaList(ref s, ref l) => {
|
ast::MetaList(ref s, ref l) => {
|
||||||
List(s.get().to_string(), l.clean().move_iter().collect())
|
List(s.get().to_string(), l.clean())
|
||||||
}
|
}
|
||||||
ast::MetaNameValue(ref s, ref v) => {
|
ast::MetaNameValue(ref s, ref v) => {
|
||||||
NameValue(s.get().to_string(), lit_to_string(v))
|
NameValue(s.get().to_string(), lit_to_string(v))
|
||||||
|
@ -460,7 +460,7 @@ impl Clean<TyParam> for ast::TyParam {
|
||||||
TyParam {
|
TyParam {
|
||||||
name: self.ident.clean(),
|
name: self.ident.clean(),
|
||||||
did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
|
did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
|
||||||
bounds: self.bounds.clean().move_iter().collect(),
|
bounds: self.bounds.clean(),
|
||||||
default: self.default.clean()
|
default: self.default.clean()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,7 +688,7 @@ impl Clean<Item> for ast::Method {
|
||||||
};
|
};
|
||||||
Item {
|
Item {
|
||||||
name: Some(self.pe_ident().clean()),
|
name: Some(self.pe_ident().clean()),
|
||||||
attrs: self.attrs.clean().move_iter().collect(),
|
attrs: self.attrs.clean(),
|
||||||
source: self.span.clean(),
|
source: self.span.clean(),
|
||||||
def_id: ast_util::local_def(self.id),
|
def_id: ast_util::local_def(self.id),
|
||||||
visibility: self.pe_vis().clean(),
|
visibility: self.pe_vis().clean(),
|
||||||
|
@ -727,7 +727,7 @@ impl Clean<Item> for ast::TypeMethod {
|
||||||
};
|
};
|
||||||
Item {
|
Item {
|
||||||
name: Some(self.ident.clean()),
|
name: Some(self.ident.clean()),
|
||||||
attrs: self.attrs.clean().move_iter().collect(),
|
attrs: self.attrs.clean(),
|
||||||
source: self.span.clean(),
|
source: self.span.clean(),
|
||||||
def_id: ast_util::local_def(self.id),
|
def_id: ast_util::local_def(self.id),
|
||||||
visibility: None,
|
visibility: None,
|
||||||
|
@ -805,7 +805,7 @@ impl Clean<ClosureDecl> for ast::ClosureTy {
|
||||||
onceness: self.onceness,
|
onceness: self.onceness,
|
||||||
fn_style: self.fn_style,
|
fn_style: self.fn_style,
|
||||||
bounds: match self.bounds {
|
bounds: match self.bounds {
|
||||||
Some(ref x) => x.clean().move_iter().collect(),
|
Some(ref x) => x.clean(),
|
||||||
None => Vec::new()
|
None => Vec::new()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1178,7 +1178,7 @@ impl Clean<Type> for ast::Ty {
|
||||||
TyTup(ref tys) => Tuple(tys.iter().map(|x| x.clean()).collect()),
|
TyTup(ref tys) => Tuple(tys.iter().map(|x| x.clean()).collect()),
|
||||||
TyPath(ref p, ref tpbs, id) => {
|
TyPath(ref p, ref tpbs, id) => {
|
||||||
resolve_type(p.clean(),
|
resolve_type(p.clean(),
|
||||||
tpbs.clean().map(|x| x.move_iter().collect()),
|
tpbs.clean().map(|x| x),
|
||||||
id)
|
id)
|
||||||
}
|
}
|
||||||
TyClosure(ref c, region) => Closure(box c.clean(), region.clean()),
|
TyClosure(ref c, region) => Closure(box c.clean(), region.clean()),
|
||||||
|
@ -1307,7 +1307,7 @@ impl Clean<Item> for ast::StructField {
|
||||||
};
|
};
|
||||||
Item {
|
Item {
|
||||||
name: name.clean(),
|
name: name.clean(),
|
||||||
attrs: self.node.attrs.clean().move_iter().collect(),
|
attrs: self.node.attrs.clean(),
|
||||||
source: self.span.clean(),
|
source: self.span.clean(),
|
||||||
visibility: Some(vis),
|
visibility: Some(vis),
|
||||||
stability: get_stability(ast_util::local_def(self.node.id)),
|
stability: get_stability(ast_util::local_def(self.node.id)),
|
||||||
|
@ -1320,16 +1320,26 @@ impl Clean<Item> for ast::StructField {
|
||||||
impl Clean<Item> for ty::field_ty {
|
impl Clean<Item> for ty::field_ty {
|
||||||
fn clean(&self) -> Item {
|
fn clean(&self) -> Item {
|
||||||
use syntax::parse::token::special_idents::unnamed_field;
|
use syntax::parse::token::special_idents::unnamed_field;
|
||||||
|
use rustc::metadata::csearch;
|
||||||
|
|
||||||
|
let cx = get_cx();
|
||||||
|
let attrs;
|
||||||
|
|
||||||
|
let attr_map = csearch::get_struct_field_attrs(&cx.tcx().sess.cstore, self.id);
|
||||||
|
|
||||||
let name = if self.name == unnamed_field.name {
|
let name = if self.name == unnamed_field.name {
|
||||||
|
attrs = None;
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
attrs = Some(attr_map.find(&self.id.node).unwrap());
|
||||||
Some(self.name)
|
Some(self.name)
|
||||||
};
|
};
|
||||||
let cx = get_cx();
|
|
||||||
let ty = ty::lookup_item_type(cx.tcx(), self.id);
|
let ty = ty::lookup_item_type(cx.tcx(), self.id);
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
name: name.clean(),
|
name: name.clean(),
|
||||||
attrs: inline::load_attrs(cx.tcx(), self.id),
|
attrs: attrs.unwrap_or(&Vec::new()).clean(),
|
||||||
source: Span::empty(),
|
source: Span::empty(),
|
||||||
visibility: Some(self.vis),
|
visibility: Some(self.vis),
|
||||||
stability: get_stability(self.id),
|
stability: get_stability(self.id),
|
||||||
|
@ -1388,7 +1398,7 @@ impl Clean<VariantStruct> for syntax::ast::StructDef {
|
||||||
fn clean(&self) -> VariantStruct {
|
fn clean(&self) -> VariantStruct {
|
||||||
VariantStruct {
|
VariantStruct {
|
||||||
struct_type: doctree::struct_type_from_def(self),
|
struct_type: doctree::struct_type_from_def(self),
|
||||||
fields: self.fields.clean().move_iter().collect(),
|
fields: self.fields.clean(),
|
||||||
fields_stripped: false,
|
fields_stripped: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1556,7 +1566,7 @@ impl Clean<Path> for ast::Path {
|
||||||
fn clean(&self) -> Path {
|
fn clean(&self) -> Path {
|
||||||
Path {
|
Path {
|
||||||
global: self.global,
|
global: self.global,
|
||||||
segments: self.segments.clean().move_iter().collect(),
|
segments: self.segments.clean(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1572,8 +1582,8 @@ impl Clean<PathSegment> for ast::PathSegment {
|
||||||
fn clean(&self) -> PathSegment {
|
fn clean(&self) -> PathSegment {
|
||||||
PathSegment {
|
PathSegment {
|
||||||
name: self.identifier.clean(),
|
name: self.identifier.clean(),
|
||||||
lifetimes: self.lifetimes.clean().move_iter().collect(),
|
lifetimes: self.lifetimes.clean(),
|
||||||
types: self.types.clean().move_iter().collect()
|
types: self.types.clean(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1640,7 +1650,7 @@ impl Clean<BareFunctionDecl> for ast::BareFnTy {
|
||||||
BareFunctionDecl {
|
BareFunctionDecl {
|
||||||
fn_style: self.fn_style,
|
fn_style: self.fn_style,
|
||||||
generics: Generics {
|
generics: Generics {
|
||||||
lifetimes: self.lifetimes.clean().move_iter().collect(),
|
lifetimes: self.lifetimes.clean(),
|
||||||
type_params: Vec::new(),
|
type_params: Vec::new(),
|
||||||
},
|
},
|
||||||
decl: self.decl.clean(),
|
decl: self.decl.clean(),
|
||||||
|
@ -1745,7 +1755,7 @@ impl Clean<Vec<Item>> for ast::ViewItem {
|
||||||
let convert = |node: &ast::ViewItem_| {
|
let convert = |node: &ast::ViewItem_| {
|
||||||
Item {
|
Item {
|
||||||
name: None,
|
name: None,
|
||||||
attrs: self.attrs.clean().move_iter().collect(),
|
attrs: self.attrs.clean(),
|
||||||
source: self.span.clean(),
|
source: self.span.clean(),
|
||||||
def_id: ast_util::local_def(0),
|
def_id: ast_util::local_def(0),
|
||||||
visibility: self.vis.clean(),
|
visibility: self.vis.clean(),
|
||||||
|
@ -1840,7 +1850,7 @@ impl Clean<ViewPath> for ast::ViewPath {
|
||||||
GlobImport(resolve_use_source(p.clean(), id)),
|
GlobImport(resolve_use_source(p.clean(), id)),
|
||||||
ast::ViewPathList(ref p, ref pl, id) => {
|
ast::ViewPathList(ref p, ref pl, id) => {
|
||||||
ImportList(resolve_use_source(p.clean(), id),
|
ImportList(resolve_use_source(p.clean(), id),
|
||||||
pl.clean().move_iter().collect())
|
pl.clean())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1893,7 +1903,7 @@ impl Clean<Item> for ast::ForeignItem {
|
||||||
};
|
};
|
||||||
Item {
|
Item {
|
||||||
name: Some(self.ident.clean()),
|
name: Some(self.ident.clean()),
|
||||||
attrs: self.attrs.clean().move_iter().collect(),
|
attrs: self.attrs.clean(),
|
||||||
source: self.span.clean(),
|
source: self.span.clean(),
|
||||||
def_id: ast_util::local_def(self.id),
|
def_id: ast_util::local_def(self.id),
|
||||||
visibility: self.vis.clean(),
|
visibility: self.vis.clean(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue