Skip to content

Commit 91fe6d6

Browse files
committed
Allow inheritance between structs.
No subtyping, no interaction with traits. Partially addresses rust-lang#9912.
1 parent 123eb4e commit 91fe6d6

21 files changed

+500
-50
lines changed

src/doc/rust.md

+15
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,21 @@ struct Cookie;
11691169
let c = [Cookie, Cookie, Cookie, Cookie];
11701170
~~~~
11711171

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

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

src/librustc/driver/driver.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
276276
last_private_map: last_private_map
277277
} =
278278
time(time_passes, "resolution", (), |_|
279-
middle::resolve::resolve_crate(sess, lang_items, krate));
279+
middle::resolve::resolve_crate(sess, lang_items, &ast_map, krate));
280280

281281
let named_region_map = time(time_passes, "lifetime resolution", (),
282282
|_| middle::resolve_lifetime::krate(sess, krate));

src/librustc/front/config.rs

+1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ fn fold_struct(cx: &Context, def: &ast::StructDef) -> @ast::StructDef {
152152
@ast::StructDef {
153153
fields: fields.collect(),
154154
ctor_id: def.ctor_id,
155+
super_struct: def.super_struct.clone(),
155156
}
156157
}
157158

src/librustc/front/feature_gate.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
5252
("simd", Active),
5353
("default_type_params", Active),
5454
("quote", Active),
55+
("struct_inherit", Active),
5556

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

190-
ast::ItemStruct(..) => {
191+
ast::ItemStruct(struct_definition, _) => {
191192
if attr::contains_name(i.attrs, "simd") {
192193
self.gate_feature("simd", i.span,
193194
"SIMD types are experimental and possibly buggy");
194195
}
196+
match struct_definition.super_struct{
197+
Some(ref path) => self.gate_feature("struct_inherit", path.span,
198+
"struct inheritance is experimental \
199+
and possibly buggy"),
200+
None => {}
201+
}
195202
}
196203

197204
_ => {}

src/librustc/metadata/encoder.rs

+37-3
Original file line numberDiff line numberDiff line change
@@ -1007,12 +1007,43 @@ fn encode_info_for_item(ecx: &EncodeContext,
10071007
generics);
10081008
}
10091009
ItemStruct(struct_def, _) => {
1010+
// Create a list of all structs which compose this struct. That is, the
1011+
// reflexive, transitive closure over struct_def's super-struct.
1012+
let mut cur_struct = struct_def;
1013+
let mut structs: ~[@StructDef] = ~[];
1014+
loop {
1015+
structs.push(cur_struct);
1016+
match cur_struct.super_struct {
1017+
Some(t) => match t.node {
1018+
ast::TyPath(_, _, path_id) => {
1019+
let def_map = tcx.def_map.borrow();
1020+
match def_map.get().find(&path_id) {
1021+
Some(&DefStruct(def_id)) => {
1022+
cur_struct = match tcx.map.find(def_id.node) {
1023+
Some(ast_map::NodeItem(i)) => {
1024+
match i.node {
1025+
ast::ItemStruct(struct_def, _) => struct_def,
1026+
_ => ecx.diag.handler().bug("Expected ItemStruct"),
1027+
}
1028+
},
1029+
_ => ecx.diag.handler().bug("Expected NodeItem"),
1030+
};
1031+
},
1032+
_ => ecx.diag.handler().bug("Expected DefStruct"),
1033+
}
1034+
}
1035+
_ => ecx.diag.handler().bug("Expected TyPath"),
1036+
},
1037+
None => break,
1038+
}
1039+
}
1040+
10101041
/* First, encode the fields
10111042
These come first because we need to write them to make
10121043
the index, and the index needs to be in the item for the
10131044
class itself */
1014-
let idx = encode_info_for_struct(ecx, ebml_w,
1015-
struct_def.fields, index);
1045+
let idx = structs.iter().fold(~[], |a: ~[entry<i64>], &s|
1046+
a + encode_info_for_struct(ecx, ebml_w, s.fields, index));
10161047

10171048
/* Index the class*/
10181049
add_to_index(item, ebml_w, index);
@@ -1032,7 +1063,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
10321063
/* Encode def_ids for each field and method
10331064
for methods, write all the stuff get_trait_method
10341065
needs to know*/
1035-
encode_struct_fields(ebml_w, struct_def);
1066+
structs.iter().advance(|&s| {
1067+
encode_struct_fields(ebml_w, s);
1068+
true
1069+
});
10361070

10371071
(ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
10381072

0 commit comments

Comments
 (0)