Skip to content

Commit ff04aa8

Browse files
committed
Allow inheritance between structs.
No subtyping, no interaction with traits. Partially addresses #9912.
1 parent 3757f01 commit ff04aa8

30 files changed

+803
-208
lines changed

src/doc/rust.md

+16
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,22 @@ struct Cookie;
12141214
let c = [Cookie, Cookie, Cookie, Cookie];
12151215
~~~~
12161216

1217+
By using the `struct_inherit` feature gate, structures may use single inheritance. A Structure may only
1218+
inherit from a single other structure, called the _super-struct_. The inheriting structure (sub-struct)
1219+
acts as if all fields in the super-struct were present in the sub-struct. Fields declared in a sub-struct
1220+
must not have the same name as any field in any (transitive) super-struct. All fields (both declared
1221+
and inherited) must be specified in any initializers. Inheritance between structures does not give
1222+
subtyping or coercion. The super-struct and sub-struct must be defined in the same crate. The super-struct
1223+
must be declared using the `virtual` keyword.
1224+
For example:
1225+
1226+
~~~~ {.ignore}
1227+
virtual struct Sup { x: int }
1228+
struct Sub : Sup { y: int }
1229+
let s = Sub {x: 10, y: 11};
1230+
let sx = s.x;
1231+
~~~~
1232+
12171233
### Enumerations
12181234

12191235
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
@@ -55,6 +55,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
5555
("default_type_params", Active),
5656
("quote", Active),
5757
("linkage", Active),
58+
("struct_inherit", Active),
5859

5960
// These are used to test this portion of the compiler, they don't actually
6061
// mean anything
@@ -190,11 +191,22 @@ impl<'a> Visitor<()> for Context<'a> {
190191
}
191192
}
192193

193-
ast::ItemStruct(..) => {
194+
ast::ItemStruct(struct_definition, _) => {
194195
if attr::contains_name(i.attrs.as_slice(), "simd") {
195196
self.gate_feature("simd", i.span,
196197
"SIMD types are experimental and possibly buggy");
197198
}
199+
match struct_definition.super_struct {
200+
Some(ref path) => self.gate_feature("struct_inherit", path.span,
201+
"struct inheritance is experimental \
202+
and possibly buggy"),
203+
None => {}
204+
}
205+
if struct_definition.is_virtual {
206+
self.gate_feature("struct_inherit", i.span,
207+
"struct inheritance (`virtual` keyword) is \
208+
experimental and possibly buggy");
209+
}
198210
}
199211

200212
_ => {}

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
@@ -975,21 +975,27 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
975975
// FIXME #6993: name should be of type Name, not Ident
976976
let name = item_name(&*intr, an_item);
977977
let did = item_def_id(an_item, cdata);
978+
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
979+
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
978980
result.push(ty::field_ty {
979981
name: name.name,
980-
id: did, vis:
981-
struct_field_family_to_visibility(f),
982+
id: did,
983+
vis: struct_field_family_to_visibility(f),
984+
origin: origin_id,
982985
});
983986
}
984987
true
985988
});
986989
reader::tagged_docs(item, tag_item_unnamed_field, |an_item| {
987990
let did = item_def_id(an_item, cdata);
991+
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
988992
let f = item_family(an_item);
993+
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
989994
result.push(ty::field_ty {
990995
name: special_idents::unnamed_field.name,
991996
id: did,
992997
vis: struct_field_family_to_visibility(f),
998+
origin: origin_id,
993999
});
9941000
true
9951001
});

src/librustc/metadata/encoder.rs

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

292292
fn encode_struct_fields(ebml_w: &mut Encoder,
293-
def: @StructDef) {
294-
for f in def.fields.iter() {
295-
match f.node.kind {
296-
NamedField(ident, vis) => {
297-
ebml_w.start_tag(tag_item_field);
298-
encode_struct_field_family(ebml_w, vis);
299-
encode_name(ebml_w, ident.name);
300-
encode_def_id(ebml_w, local_def(f.node.id));
301-
ebml_w.end_tag();
302-
}
303-
UnnamedField(vis) => {
304-
ebml_w.start_tag(tag_item_unnamed_field);
305-
encode_struct_field_family(ebml_w, vis);
306-
encode_def_id(ebml_w, local_def(f.node.id));
307-
ebml_w.end_tag();
308-
}
293+
fields: &Vec<ty::field_ty>,
294+
origin: DefId) {
295+
for f in fields.iter() {
296+
if f.name == special_idents::unnamed_field.name {
297+
ebml_w.start_tag(tag_item_unnamed_field);
298+
} else {
299+
ebml_w.start_tag(tag_item_field);
300+
encode_name(ebml_w, f.name);
309301
}
302+
encode_struct_field_family(ebml_w, f.vis);
303+
encode_def_id(ebml_w, f.id);
304+
ebml_w.start_tag(tag_item_field_origin);
305+
let s = def_to_str(origin);
306+
ebml_w.writer.write(s.as_bytes());
307+
ebml_w.end_tag();
308+
ebml_w.end_tag();
310309
}
311310
}
312311

@@ -344,12 +343,13 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
344343
encode_symbol(ecx, ebml_w, variant.node.id);
345344
}
346345
ast::TupleVariantKind(_) => {},
347-
ast::StructVariantKind(def) => {
346+
ast::StructVariantKind(_) => {
347+
let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
348348
let idx = encode_info_for_struct(ecx,
349349
ebml_w,
350-
def.fields.as_slice(),
350+
&fields,
351351
index);
352-
encode_struct_fields(ebml_w, def);
352+
encode_struct_fields(ebml_w, &fields, def_id);
353353
let bkts = create_index(idx);
354354
encode_index(ebml_w, bkts, write_i64);
355355
}
@@ -666,7 +666,7 @@ fn encode_provided_source(ebml_w: &mut Encoder,
666666
/* Returns an index of items in this class */
667667
fn encode_info_for_struct(ecx: &EncodeContext,
668668
ebml_w: &mut Encoder,
669-
fields: &[StructField],
669+
fields: &Vec<ty::field_ty>,
670670
global_index: @RefCell<Vec<entry<i64>> >)
671671
-> Vec<entry<i64>> {
672672
/* Each class has its own index, since different classes
@@ -676,22 +676,19 @@ fn encode_info_for_struct(ecx: &EncodeContext,
676676
/* We encode both private and public fields -- need to include
677677
private fields to get the offsets right */
678678
for field in fields.iter() {
679-
let (nm, vis) = match field.node.kind {
680-
NamedField(nm, vis) => (nm, vis),
681-
UnnamedField(vis) => (special_idents::unnamed_field, vis)
682-
};
679+
let nm = field.name;
680+
let id = field.id.node;
683681

684-
let id = field.node.id;
685682
index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
686683
global_index.borrow_mut().push(entry {
687684
val: id as i64,
688685
pos: ebml_w.writer.tell().unwrap(),
689686
});
690687
ebml_w.start_tag(tag_items_data_item);
691688
debug!("encode_info_for_struct: doing {} {}",
692-
token::get_ident(nm), id);
693-
encode_struct_field_family(ebml_w, vis);
694-
encode_name(ebml_w, nm.name);
689+
token::get_name(nm), id);
690+
encode_struct_field_family(ebml_w, field.vis);
691+
encode_name(ebml_w, nm);
695692
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
696693
encode_def_id(ebml_w, local_def(id));
697694
ebml_w.end_tag();
@@ -983,12 +980,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
983980
generics);
984981
}
985982
ItemStruct(struct_def, _) => {
983+
let fields = ty::lookup_struct_fields(tcx, def_id);
984+
986985
/* First, encode the fields
987986
These come first because we need to write them to make
988987
the index, and the index needs to be in the item for the
989988
class itself */
990-
let idx = encode_info_for_struct(ecx, ebml_w,
991-
struct_def.fields.as_slice(), index);
989+
let idx = encode_info_for_struct(ecx,
990+
ebml_w,
991+
&fields,
992+
index);
992993

993994
/* Index the class*/
994995
add_to_index(item, ebml_w, index);
@@ -1008,7 +1009,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
10081009
/* Encode def_ids for each field and method
10091010
for methods, write all the stuff get_trait_method
10101011
needs to know*/
1011-
encode_struct_fields(ebml_w, struct_def);
1012+
encode_struct_fields(ebml_w, &fields, def_id);
10121013

10131014
(ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
10141015

0 commit comments

Comments
 (0)