Skip to content

Commit b80481d

Browse files
committed
Allow inheritance between structs.
No subtyping, no interaction with traits. Partially addresses rust-lang#9912.
1 parent 6f1c06d commit b80481d

30 files changed

+803
-208
lines changed

src/doc/rust.md

+16
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,22 @@ struct Cookie;
11701170
let c = [Cookie, Cookie, Cookie, Cookie];
11711171
~~~~
11721172

1173+
By using the `struct_inherit` feature gate, structures may use single inheritance. A Structure may only
1174+
inherit from a single other structure, called the _super-struct_. The inheriting structure (sub-struct)
1175+
acts as if all fields in the super-struct were present in the sub-struct. Fields declared in a sub-struct
1176+
must not have the same name as any field in any (transitive) super-struct. All fields (both declared
1177+
and inherited) must be specified in any initializers. Inheritance between structures does not give
1178+
subtyping or coercion. The super-struct and sub-struct must be defined in the same crate. The super-struct
1179+
must be declared using the `virtual` keyword.
1180+
For example:
1181+
1182+
~~~~ {.ignore}
1183+
virtual struct Sup { x: int }
1184+
struct Sub : Sup { y: int }
1185+
let s = Sub {x: 10, y: 11};
1186+
let sx = s.x;
1187+
~~~~
1188+
11731189
### Enumerations
11741190

11751191
An _enumeration_ is a simultaneous definition of a nominal [enumerated type](#enumerated-types) as well as a set of *constructors*,

src/librustc/front/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ fn fold_struct(cx: &Context, def: &ast::StructDef) -> @ast::StructDef {
151151
@ast::StructDef {
152152
fields: fields.collect(),
153153
ctor_id: def.ctor_id,
154+
super_struct: def.super_struct.clone(),
155+
is_virtual: def.is_virtual,
154156
}
155157
}
156158

src/librustc/front/feature_gate.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
5353
("default_type_params", Active),
5454
("quote", Active),
5555
("linkage", Active),
56+
("struct_inherit", Active),
5657

5758
// These are used to test this portion of the compiler, they don't actually
5859
// mean anything
@@ -188,11 +189,22 @@ impl<'a> Visitor<()> for Context<'a> {
188189
}
189190
}
190191

191-
ast::ItemStruct(..) => {
192+
ast::ItemStruct(struct_definition, _) => {
192193
if attr::contains_name(i.attrs.as_slice(), "simd") {
193194
self.gate_feature("simd", i.span,
194195
"SIMD types are experimental and possibly buggy");
195196
}
197+
match struct_definition.super_struct {
198+
Some(ref path) => self.gate_feature("struct_inherit", path.span,
199+
"struct inheritance is experimental \
200+
and possibly buggy"),
201+
None => {}
202+
}
203+
if struct_definition.is_virtual {
204+
self.gate_feature("struct_inherit", i.span,
205+
"struct inheritance (`virtual` keyword) is \
206+
experimental and possibly buggy");
207+
}
196208
}
197209

198210
_ => {}

src/librustc/metadata/common.rs

+59-58
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ pub static tag_path_len: uint = 0x25;
9292
pub static tag_path_elem_mod: uint = 0x26;
9393
pub static tag_path_elem_name: uint = 0x27;
9494
pub static tag_item_field: uint = 0x28;
95+
pub static tag_item_field_origin: uint = 0x29;
9596

9697
pub static tag_item_variances: uint = 0x2a;
9798
/*
@@ -102,43 +103,43 @@ pub static tag_item_variances: uint = 0x2a;
102103
both, tag_item_trait_method and tag_item_impl_method have to be two
103104
different tags.
104105
*/
105-
pub static tag_item_impl_method: uint = 0x2c;
106-
pub static tag_item_trait_method_explicit_self: uint = 0x2d;
106+
pub static tag_item_impl_method: uint = 0x30;
107+
pub static tag_item_trait_method_explicit_self: uint = 0x31;
107108

108109

109110
// Reexports are found within module tags. Each reexport contains def_ids
110111
// and names.
111-
pub static tag_items_data_item_reexport: uint = 0x2f;
112-
pub static tag_items_data_item_reexport_def_id: uint = 0x30;
113-
pub static tag_items_data_item_reexport_name: uint = 0x31;
112+
pub static tag_items_data_item_reexport: uint = 0x38;
113+
pub static tag_items_data_item_reexport_def_id: uint = 0x39;
114+
pub static tag_items_data_item_reexport_name: uint = 0x3a;
114115

115116
// used to encode crate_ctxt side tables
116117
#[deriving(Eq)]
117118
#[repr(uint)]
118-
pub enum astencode_tag { // Reserves 0x32 -- 0x45
119-
tag_ast = 0x32,
120-
121-
tag_tree = 0x33,
122-
123-
tag_id_range = 0x34,
124-
125-
tag_table = 0x35,
126-
tag_table_id = 0x36,
127-
tag_table_val = 0x37,
128-
tag_table_def = 0x38,
129-
tag_table_node_type = 0x39,
130-
tag_table_node_type_subst = 0x3a,
131-
tag_table_freevars = 0x3b,
132-
tag_table_tcache = 0x3c,
133-
tag_table_param_defs = 0x3d,
134-
tag_table_mutbl = 0x3e,
135-
tag_table_last_use = 0x3f,
136-
tag_table_spill = 0x40,
137-
tag_table_method_map = 0x41,
138-
tag_table_vtable_map = 0x42,
139-
tag_table_adjustments = 0x43,
140-
tag_table_moves_map = 0x44,
141-
tag_table_capture_map = 0x45
119+
pub enum astencode_tag { // Reserves 0x40 -- 0x5f
120+
tag_ast = 0x40,
121+
122+
tag_tree = 0x41,
123+
124+
tag_id_range = 0x42,
125+
126+
tag_table = 0x43,
127+
tag_table_id = 0x44,
128+
tag_table_val = 0x45,
129+
tag_table_def = 0x46,
130+
tag_table_node_type = 0x47,
131+
tag_table_node_type_subst = 0x48,
132+
tag_table_freevars = 0x49,
133+
tag_table_tcache = 0x4a,
134+
tag_table_param_defs = 0x4b,
135+
tag_table_mutbl = 0x4c,
136+
tag_table_last_use = 0x4d,
137+
tag_table_spill = 0x4e,
138+
tag_table_method_map = 0x4f,
139+
tag_table_vtable_map = 0x50,
140+
tag_table_adjustments = 0x51,
141+
tag_table_moves_map = 0x52,
142+
tag_table_capture_map = 0x53
142143
}
143144
static first_astencode_tag: uint = tag_ast as uint;
144145
static last_astencode_tag: uint = tag_table_capture_map as uint;
@@ -151,9 +152,9 @@ impl astencode_tag {
151152
}
152153
}
153154

154-
pub static tag_item_trait_method_sort: uint = 0x46;
155+
pub static tag_item_trait_method_sort: uint = 0x60;
155156

156-
pub static tag_item_impl_type_basename: uint = 0x47;
157+
pub static tag_item_impl_type_basename: uint = 0x61;
157158

158159
// Language items are a top-level directory (for speed). Hierarchy:
159160
//
@@ -162,42 +163,42 @@ pub static tag_item_impl_type_basename: uint = 0x47;
162163
// - tag_lang_items_item_id: u32
163164
// - tag_lang_items_item_node_id: u32
164165

165-
pub static tag_lang_items: uint = 0x48;
166-
pub static tag_lang_items_item: uint = 0x49;
167-
pub static tag_lang_items_item_id: uint = 0x4a;
168-
pub static tag_lang_items_item_node_id: uint = 0x4b;
166+
pub static tag_lang_items: uint = 0x70;
167+
pub static tag_lang_items_item: uint = 0x71;
168+
pub static tag_lang_items_item_id: uint = 0x72;
169+
pub static tag_lang_items_item_node_id: uint = 0x73;
169170

170-
pub static tag_item_unnamed_field: uint = 0x4c;
171-
pub static tag_items_data_item_visibility: uint = 0x4e;
171+
pub static tag_item_unnamed_field: uint = 0x74;
172+
pub static tag_items_data_item_visibility: uint = 0x76;
172173

173-
pub static tag_item_method_tps: uint = 0x51;
174-
pub static tag_item_method_fty: uint = 0x52;
174+
pub static tag_item_method_tps: uint = 0x79;
175+
pub static tag_item_method_fty: uint = 0x7a;
175176

176-
pub static tag_mod_child: uint = 0x53;
177-
pub static tag_misc_info: uint = 0x54;
178-
pub static tag_misc_info_crate_items: uint = 0x55;
177+
pub static tag_mod_child: uint = 0x7b;
178+
pub static tag_misc_info: uint = 0x7c;
179+
pub static tag_misc_info_crate_items: uint = 0x7d;
179180

180-
pub static tag_item_method_provided_source: uint = 0x56;
181-
pub static tag_item_impl_vtables: uint = 0x57;
181+
pub static tag_item_method_provided_source: uint = 0x7e;
182+
pub static tag_item_impl_vtables: uint = 0x7f;
182183

183-
pub static tag_impls: uint = 0x58;
184-
pub static tag_impls_impl: uint = 0x59;
184+
pub static tag_impls: uint = 0x80;
185+
pub static tag_impls_impl: uint = 0x81;
185186

186-
pub static tag_items_data_item_inherent_impl: uint = 0x5a;
187-
pub static tag_items_data_item_extension_impl: uint = 0x5b;
187+
pub static tag_items_data_item_inherent_impl: uint = 0x82;
188+
pub static tag_items_data_item_extension_impl: uint = 0x83;
188189

189-
pub static tag_region_param_def: uint = 0x5c;
190-
pub static tag_region_param_def_ident: uint = 0x5d;
191-
pub static tag_region_param_def_def_id: uint = 0x5e;
190+
pub static tag_region_param_def: uint = 0x84;
191+
pub static tag_region_param_def_ident: uint = 0x85;
192+
pub static tag_region_param_def_def_id: uint = 0x86;
192193

193-
pub static tag_native_libraries: uint = 0x5f;
194-
pub static tag_native_libraries_lib: uint = 0x60;
195-
pub static tag_native_libraries_name: uint = 0x61;
196-
pub static tag_native_libraries_kind: uint = 0x62;
194+
pub static tag_native_libraries: uint = 0x87;
195+
pub static tag_native_libraries_lib: uint = 0x88;
196+
pub static tag_native_libraries_name: uint = 0x89;
197+
pub static tag_native_libraries_kind: uint = 0x8a;
197198

198-
pub static tag_macro_registrar_fn: uint = 0x63;
199-
pub static tag_exported_macros: uint = 0x64;
200-
pub static tag_macro_def: uint = 0x65;
199+
pub static tag_macro_registrar_fn: uint = 0x8b;
200+
pub static tag_exported_macros: uint = 0x8c;
201+
pub static tag_macro_def: uint = 0x8d;
201202

202203
#[deriving(Clone, Show)]
203204
pub struct LinkMeta {

src/librustc/metadata/decoder.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -976,21 +976,27 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
976976
// FIXME #6993: name should be of type Name, not Ident
977977
let name = item_name(&*intr, an_item);
978978
let did = item_def_id(an_item, cdata);
979+
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
980+
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
979981
result.push(ty::field_ty {
980982
name: name.name,
981-
id: did, vis:
982-
struct_field_family_to_visibility(f),
983+
id: did,
984+
vis: struct_field_family_to_visibility(f),
985+
origin: origin_id,
983986
});
984987
}
985988
true
986989
});
987990
reader::tagged_docs(item, tag_item_unnamed_field, |an_item| {
988991
let did = item_def_id(an_item, cdata);
992+
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
989993
let f = item_family(an_item);
994+
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
990995
result.push(ty::field_ty {
991996
name: special_idents::unnamed_field.name,
992997
id: did,
993998
vis: struct_field_family_to_visibility(f),
999+
origin: origin_id,
9941000
});
9951001
true
9961002
});

src/librustc/metadata/encoder.rs

+32-31
Original file line numberDiff line numberDiff line change
@@ -302,23 +302,22 @@ fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
302302
}
303303

304304
fn encode_struct_fields(ebml_w: &mut Encoder,
305-
def: @StructDef) {
306-
for f in def.fields.iter() {
307-
match f.node.kind {
308-
NamedField(ident, vis) => {
309-
ebml_w.start_tag(tag_item_field);
310-
encode_struct_field_family(ebml_w, vis);
311-
encode_name(ebml_w, ident.name);
312-
encode_def_id(ebml_w, local_def(f.node.id));
313-
ebml_w.end_tag();
314-
}
315-
UnnamedField(vis) => {
316-
ebml_w.start_tag(tag_item_unnamed_field);
317-
encode_struct_field_family(ebml_w, vis);
318-
encode_def_id(ebml_w, local_def(f.node.id));
319-
ebml_w.end_tag();
320-
}
305+
fields: &Vec<ty::field_ty>,
306+
origin: DefId) {
307+
for f in fields.iter() {
308+
if f.name == special_idents::unnamed_field.name {
309+
ebml_w.start_tag(tag_item_unnamed_field);
310+
} else {
311+
ebml_w.start_tag(tag_item_field);
312+
encode_name(ebml_w, f.name);
321313
}
314+
encode_struct_field_family(ebml_w, f.vis);
315+
encode_def_id(ebml_w, f.id);
316+
ebml_w.start_tag(tag_item_field_origin);
317+
let s = def_to_str(origin);
318+
ebml_w.writer.write(s.as_bytes());
319+
ebml_w.end_tag();
320+
ebml_w.end_tag();
322321
}
323322
}
324323

@@ -356,12 +355,13 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
356355
encode_symbol(ecx, ebml_w, variant.node.id);
357356
}
358357
ast::TupleVariantKind(_) => {},
359-
ast::StructVariantKind(def) => {
358+
ast::StructVariantKind(_) => {
359+
let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
360360
let idx = encode_info_for_struct(ecx,
361361
ebml_w,
362-
def.fields.as_slice(),
362+
&fields,
363363
index);
364-
encode_struct_fields(ebml_w, def);
364+
encode_struct_fields(ebml_w, &fields, def_id);
365365
let bkts = create_index(idx);
366366
encode_index(ebml_w, bkts, write_i64);
367367
}
@@ -680,7 +680,7 @@ fn encode_provided_source(ebml_w: &mut Encoder,
680680
/* Returns an index of items in this class */
681681
fn encode_info_for_struct(ecx: &EncodeContext,
682682
ebml_w: &mut Encoder,
683-
fields: &[StructField],
683+
fields: &Vec<ty::field_ty>,
684684
global_index: @RefCell<Vec<entry<i64>> >)
685685
-> Vec<entry<i64>> {
686686
/* Each class has its own index, since different classes
@@ -690,22 +690,19 @@ fn encode_info_for_struct(ecx: &EncodeContext,
690690
/* We encode both private and public fields -- need to include
691691
private fields to get the offsets right */
692692
for field in fields.iter() {
693-
let (nm, vis) = match field.node.kind {
694-
NamedField(nm, vis) => (nm, vis),
695-
UnnamedField(vis) => (special_idents::unnamed_field, vis)
696-
};
693+
let nm = field.name;
694+
let id = field.id.node;
697695

698-
let id = field.node.id;
699696
index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
700697
global_index.borrow_mut().push(entry {
701698
val: id as i64,
702699
pos: ebml_w.writer.tell().unwrap(),
703700
});
704701
ebml_w.start_tag(tag_items_data_item);
705702
debug!("encode_info_for_struct: doing {} {}",
706-
token::get_ident(nm), id);
707-
encode_struct_field_family(ebml_w, vis);
708-
encode_name(ebml_w, nm.name);
703+
token::get_name(nm), id);
704+
encode_struct_field_family(ebml_w, field.vis);
705+
encode_name(ebml_w, nm);
709706
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
710707
encode_def_id(ebml_w, local_def(id));
711708
ebml_w.end_tag();
@@ -997,12 +994,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
997994
generics);
998995
}
999996
ItemStruct(struct_def, _) => {
997+
let fields = ty::lookup_struct_fields(tcx, def_id);
998+
1000999
/* First, encode the fields
10011000
These come first because we need to write them to make
10021001
the index, and the index needs to be in the item for the
10031002
class itself */
1004-
let idx = encode_info_for_struct(ecx, ebml_w,
1005-
struct_def.fields.as_slice(), index);
1003+
let idx = encode_info_for_struct(ecx,
1004+
ebml_w,
1005+
&fields,
1006+
index);
10061007

10071008
/* Index the class*/
10081009
add_to_index(item, ebml_w, index);
@@ -1022,7 +1023,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
10221023
/* Encode def_ids for each field and method
10231024
for methods, write all the stuff get_trait_method
10241025
needs to know*/
1025-
encode_struct_fields(ebml_w, struct_def);
1026+
encode_struct_fields(ebml_w, &fields, def_id);
10261027

10271028
(ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
10281029

0 commit comments

Comments
 (0)