Skip to content

Commit 7a6d342

Browse files
committed
Add DatatypeDef
Add a DatatypeDef type that contains information for both structs and enums. Most places already treated structs like single-variant enums or vice-versa, so this actually simplifies a lot of code.
1 parent a5214e4 commit 7a6d342

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1541
-1496
lines changed

src/librustc/lint/builtin.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -601,8 +601,8 @@ impl LintPass for RawPointerDerive {
601601
}
602602

603603
match ty::node_id_to_type(cx.tcx, item.id).sty {
604-
ty::ty_enum(did, _) => did,
605-
ty::ty_struct(did, _) => did,
604+
ty::ty_enum(def, _) |
605+
ty::ty_struct(def, _) => def.def_id,
606606
_ => return,
607607
}
608608
}
@@ -727,15 +727,15 @@ impl LintPass for UnusedResults {
727727
match t.sty {
728728
ty::ty_tup(ref tys) if tys.is_empty() => return,
729729
ty::ty_bool => return,
730-
ty::ty_struct(did, _) |
731-
ty::ty_enum(did, _) => {
732-
if ast_util::is_local(did) {
733-
if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) {
730+
ty::ty_struct(def, _) |
731+
ty::ty_enum(def, _) => {
732+
if ast_util::is_local(def.def_id) {
733+
if let ast_map::NodeItem(it) = cx.tcx.map.get(def.def_id.node) {
734734
warned |= check_must_use(cx, &it.attrs, s.span);
735735
}
736736
} else {
737-
let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
738-
warned |= check_must_use(cx, &attrs[..], s.span);
737+
let attrs = csearch::get_item_attrs(&cx.sess().cstore, def.def_id);
738+
warned |= check_must_use(cx, &attrs, s.span);
739739
}
740740
}
741741
_ => {}
@@ -1626,16 +1626,18 @@ impl LintPass for MissingCopyImplementations {
16261626
if ast_generics.is_parameterized() {
16271627
return
16281628
}
1629+
let def = ty::lookup_datatype_def(cx.tcx, ast_util::local_def(item.id));
16291630
ty::mk_struct(cx.tcx,
1630-
ast_util::local_def(item.id),
1631+
def,
16311632
cx.tcx.mk_substs(Substs::empty()))
16321633
}
16331634
ast::ItemEnum(_, ref ast_generics) => {
16341635
if ast_generics.is_parameterized() {
16351636
return
16361637
}
1638+
let def = ty::lookup_datatype_def(cx.tcx, ast_util::local_def(item.id));
16371639
ty::mk_enum(cx.tcx,
1638-
ast_util::local_def(item.id),
1640+
def,
16391641
cx.tcx.mk_substs(Substs::empty()))
16401642
}
16411643
_ => return,

src/librustc/metadata/csearch.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ pub struct MethodInfo {
3636
pub vis: ast::Visibility,
3737
}
3838

39+
#[derive(Copy)]
40+
pub struct FieldInfo {
41+
pub name: ast::Name,
42+
pub def_id: ast::DefId,
43+
pub vis: ast::Visibility,
44+
pub origin: ast::DefId,
45+
}
46+
3947
pub fn get_symbol(cstore: &cstore::CStore, def: ast::DefId) -> String {
4048
let cdata = cstore.get_crate_data(def.krate);
4149
decoder::get_symbol(cdata.data(), def.node)
@@ -114,19 +122,6 @@ pub fn maybe_get_item_ast<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId,
114122
decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item)
115123
}
116124

117-
pub fn get_enum_variant_defs(cstore: &cstore::CStore, enum_id: ast::DefId)
118-
-> Vec<(def::Def, ast::Name, ast::Visibility)> {
119-
let cdata = cstore.get_crate_data(enum_id.krate);
120-
decoder::get_enum_variant_defs(&*cstore.intr, &*cdata, enum_id.node)
121-
}
122-
123-
pub fn get_enum_variants<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
124-
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
125-
let cstore = &tcx.sess.cstore;
126-
let cdata = cstore.get_crate_data(def.krate);
127-
decoder::get_enum_variants(cstore.intr.clone(), &*cdata, def.node, tcx)
128-
}
129-
130125
/// Returns information about the given implementation.
131126
pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: ast::DefId)
132127
-> Vec<ty::ImplOrTraitItemId> {
@@ -203,9 +198,16 @@ pub fn get_item_attrs(cstore: &cstore::CStore,
203198
decoder::get_item_attrs(&*cdata, def_id.node)
204199
}
205200

206-
pub fn get_struct_fields(cstore: &cstore::CStore,
207-
def: ast::DefId)
208-
-> Vec<ty::field_ty> {
201+
pub fn get_datatype_def<'tcx>(tcx: &ty::ctxt<'tcx>,
202+
def: ast::DefId) -> &'tcx ty::DatatypeDef<'tcx> {
203+
let cstore = &tcx.sess.cstore;
204+
let cdata = cstore.get_crate_data(def.krate);
205+
decoder::get_datatype_def(tcx, cstore.intr.clone(), &*cdata, def.node)
206+
}
207+
208+
/// Get the fields for the struct. Use this when you don't have a type context to
209+
/// pass to `ty::lookup_struct_def`.
210+
pub fn get_struct_fields(cstore: &cstore::CStore, def: ast::DefId) -> Vec<FieldInfo> {
209211
let cdata = cstore.get_crate_data(def.krate);
210212
decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
211213
}

src/librustc/metadata/decoder.rs

Lines changed: 144 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use self::Family::*;
1818
use back::svh::Svh;
1919
use metadata::cstore::crate_metadata;
2020
use metadata::common::*;
21-
use metadata::csearch::MethodInfo;
21+
use metadata::csearch::{FieldInfo, MethodInfo};
2222
use metadata::csearch;
2323
use metadata::cstore;
2424
use metadata::tydecode::{parse_ty_data, parse_region_data, parse_def_id,
@@ -727,72 +727,6 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
727727
}
728728
}
729729

730-
pub fn get_enum_variant_defs(intr: &IdentInterner,
731-
cdata: Cmd,
732-
id: ast::NodeId)
733-
-> Vec<(def::Def, ast::Name, ast::Visibility)> {
734-
let data = cdata.data();
735-
let items = reader::get_doc(rbml::Doc::new(data), tag_items);
736-
let item = find_item(id, items);
737-
enum_variant_ids(item, cdata).iter().map(|did| {
738-
let item = find_item(did.node, items);
739-
let name = item_name(intr, item);
740-
let visibility = item_visibility(item);
741-
match item_to_def_like(item, *did, cdata.cnum) {
742-
DlDef(def @ def::DefVariant(..)) => (def, name, visibility),
743-
_ => unreachable!()
744-
}
745-
}).collect()
746-
}
747-
748-
pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
749-
tcx: &ty::ctxt<'tcx>) -> Vec<Rc<ty::VariantInfo<'tcx>>> {
750-
let data = cdata.data();
751-
let items = reader::get_doc(rbml::Doc::new(data), tag_items);
752-
let item = find_item(id, items);
753-
let mut disr_val = 0;
754-
enum_variant_ids(item, cdata).iter().map(|did| {
755-
let item = find_item(did.node, items);
756-
let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
757-
item, tcx, cdata);
758-
let name = item_name(&*intr, item);
759-
let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty {
760-
ty::ty_bare_fn(_, ref f) =>
761-
(Some(ctor_ty), f.sig.0.inputs.clone(), None),
762-
_ => { // Nullary or struct enum variant.
763-
let mut arg_names = Vec::new();
764-
let arg_tys = get_struct_fields(intr.clone(), cdata, did.node)
765-
.iter()
766-
.map(|field_ty| {
767-
arg_names.push(ast::Ident::new(field_ty.name));
768-
get_type(cdata, field_ty.id.node, tcx).ty
769-
})
770-
.collect();
771-
let arg_names = if arg_names.len() == 0 { None } else { Some(arg_names) };
772-
773-
(None, arg_tys, arg_names)
774-
}
775-
};
776-
match variant_disr_val(item) {
777-
Some(val) => { disr_val = val; }
778-
_ => { /* empty */ }
779-
}
780-
let old_disr_val = disr_val;
781-
disr_val += 1;
782-
Rc::new(ty::VariantInfo {
783-
args: arg_tys,
784-
arg_names: arg_names,
785-
ctor_ty: ctor_ty,
786-
name: name,
787-
// I'm not even sure if we encode visibility
788-
// for variants -- TEST -- tjc
789-
id: *did,
790-
disr_val: old_disr_val,
791-
vis: ast::Inherited
792-
})
793-
}).collect()
794-
}
795-
796730
fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
797731
fn get_mutability(ch: u8) -> ast::Mutability {
798732
match ch as char {
@@ -1089,40 +1023,166 @@ fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
10891023
}
10901024
}
10911025

1092-
pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
1093-
-> Vec<ty::field_ty> {
1026+
pub fn get_datatype_def<'tcx>(tcx: &ty::ctxt<'tcx>, intr: Rc<IdentInterner>,
1027+
cdata: Cmd, id: ast::NodeId) -> &'tcx ty::DatatypeDef<'tcx> {
10941028
let data = cdata.data();
10951029
let item = lookup_item(id, data);
1096-
let mut result = Vec::new();
1030+
1031+
let family = item_family(item);
1032+
match family {
1033+
Enum => get_enum_datatype_def(tcx, &*intr, cdata, id),
1034+
Struct => get_struct_datatype_def(tcx, &*intr, cdata, id),
1035+
_ => tcx.sess.bug("Non data-type item family in get_datatype_def")
1036+
}
1037+
}
1038+
1039+
fn get_struct_datatype_def<'tcx>(tcx: &ty::ctxt<'tcx>, intr: &IdentInterner,
1040+
cdata: Cmd, id: ast::NodeId) -> &'tcx ty::DatatypeDef<'tcx> {
1041+
let data = cdata.data();
1042+
let item = lookup_item(id, data);
1043+
1044+
let name = item_name(intr, item);
1045+
let def_id = item_def_id(item, cdata);
1046+
1047+
let fields = get_variant_fields(tcx, intr, cdata, item);
1048+
let def = tcx.mk_datatype_def(ty::DatatypeDef {
1049+
def_id: def_id,
1050+
variants: vec![ty::VariantDef {
1051+
id: def_id,
1052+
name: name,
1053+
disr_val: 0,
1054+
fields: fields,
1055+
vis: ast::Public,
1056+
}]
1057+
});
1058+
1059+
tcx.datatype_defs.borrow_mut().insert(def_id, def);
1060+
1061+
for fld in def.variants.iter().flat_map(|v| v.fields.iter()) {
1062+
// FIXME(aatch) I shouldn't have to use get_type here, but using item_type seems
1063+
// to break things (Like cause infinite recursion in trans)
1064+
let ty = get_type(cdata, fld.id.node, tcx).ty;
1065+
fld.set_ty(ty);
1066+
}
1067+
1068+
def
1069+
}
1070+
1071+
fn get_enum_datatype_def<'tcx>(tcx: &ty::ctxt<'tcx>, intr: &IdentInterner,
1072+
cdata: Cmd, id: ast::NodeId) -> &'tcx ty::DatatypeDef<'tcx> {
1073+
let data = cdata.data();
1074+
let item = lookup_item(id, data);
1075+
1076+
let def_id = item_def_id(item, cdata);
1077+
1078+
let variants_doc = reader::get_doc(rbml::Doc::new(data), tag_items);
1079+
1080+
let mut disr_val = 0;
1081+
let variants = enum_variant_ids(item, cdata).iter().map(|did| {
1082+
let item = find_item(did.node, variants_doc);
1083+
let vname = item_name(intr, item);
1084+
match variant_disr_val(item) {
1085+
Some(val) => { disr_val = val; }
1086+
_ => {}
1087+
}
1088+
1089+
let fields = get_variant_fields(tcx, intr, cdata, item);
1090+
1091+
ty::VariantDef {
1092+
id: *did,
1093+
name: vname,
1094+
disr_val: disr_val,
1095+
fields: fields,
1096+
vis: ast::Public,
1097+
}
1098+
}).collect();
1099+
1100+
let def = tcx.mk_datatype_def(ty::DatatypeDef {
1101+
def_id: def_id,
1102+
variants: variants,
1103+
});
1104+
1105+
tcx.datatype_defs.borrow_mut().insert(def_id, def);
1106+
for fld in def.variants.iter().flat_map(|v| v.fields.iter()) {
1107+
// FIXME(aatch) I shouldn't have to use get_type here, but using item_type seems
1108+
// to break things (Like cause infinite recursion in trans)
1109+
let ty = get_type(cdata, fld.id.node, tcx).ty;
1110+
fld.set_ty(ty);
1111+
}
1112+
1113+
def
1114+
}
1115+
1116+
fn get_variant_fields<'tcx>(tcx: &ty::ctxt<'tcx>, intr: &IdentInterner, cdata: Cmd,
1117+
item: rbml::Doc) -> Vec<ty::FieldTy<'tcx>> {
1118+
1119+
let mut fields = Vec::new();
10971120
reader::tagged_docs(item, tag_item_field, |an_item| {
10981121
let f = item_family(an_item);
1099-
if f == PublicField || f == InheritedField {
1100-
let name = item_name(&*intr, an_item);
1101-
let did = item_def_id(an_item, cdata);
1102-
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
1103-
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
1104-
result.push(ty::field_ty {
1105-
name: name,
1106-
id: did,
1107-
vis: struct_field_family_to_visibility(f),
1108-
origin: origin_id,
1109-
});
1110-
}
1122+
let name = item_name(intr, an_item);
1123+
let did = item_def_id(an_item, cdata);
1124+
1125+
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
1126+
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
1127+
let fld = ty::FieldTy::new(tcx, did, name,
1128+
struct_field_family_to_visibility(f),
1129+
origin_id);
1130+
fields.push(fld);
11111131
true
11121132
});
1133+
11131134
reader::tagged_docs(item, tag_item_unnamed_field, |an_item| {
11141135
let did = item_def_id(an_item, cdata);
11151136
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
11161137
let f = item_family(an_item);
11171138
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
1118-
result.push(ty::field_ty {
1139+
let fld = ty::FieldTy::new(tcx, did, special_idents::unnamed_field.name,
1140+
struct_field_family_to_visibility(f),
1141+
origin_id);
1142+
fields.push(fld);
1143+
true
1144+
});
1145+
1146+
return fields;
1147+
}
1148+
1149+
pub fn get_struct_fields(intr: Rc<IdentInterner>,
1150+
cdata: Cmd, id: ast::NodeId) -> Vec<FieldInfo> {
1151+
let data = cdata.data();
1152+
let item = lookup_item(id, data);
1153+
let mut result = Vec::new();
1154+
reader::tagged_docs(item, tag_item_field, |an_item| {
1155+
let f = item_family(an_item);
1156+
let name = item_name(&*intr, an_item);
1157+
let did = item_def_id(an_item, cdata);
1158+
1159+
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
1160+
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
1161+
1162+
result.push(FieldInfo {
1163+
name: name,
1164+
def_id: did,
1165+
vis: struct_field_family_to_visibility(f),
1166+
origin: origin_id,
1167+
});
1168+
true
1169+
});
1170+
reader::tagged_docs(item, tag_item_unnamed_field, |an_item| {
1171+
let did = item_def_id(an_item, cdata);
1172+
let f = item_family(an_item);
1173+
1174+
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
1175+
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
1176+
1177+
result.push(FieldInfo {
11191178
name: special_idents::unnamed_field.name,
1120-
id: did,
1179+
def_id: did,
11211180
vis: struct_field_family_to_visibility(f),
11221181
origin: origin_id,
11231182
});
11241183
true
11251184
});
1185+
11261186
result
11271187
}
11281188

0 commit comments

Comments
 (0)