Skip to content

Allow inheritance between structs. #12562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,22 @@ struct Cookie;
let c = [Cookie, Cookie, Cookie, Cookie];
~~~~

By using the `struct_inherit` feature gate, structures may use single inheritance. A Structure may only
inherit from a single other structure, called the _super-struct_. The inheriting structure (sub-struct)
acts as if all fields in the super-struct were present in the sub-struct. Fields declared in a sub-struct
must not have the same name as any field in any (transitive) super-struct. All fields (both declared
and inherited) must be specified in any initializers. Inheritance between structures does not give
subtyping or coercion. The super-struct and sub-struct must be defined in the same crate. The super-struct
must be declared using the `virtual` keyword.
For example:

~~~~ {.ignore}
virtual struct Sup { x: int }
struct Sub : Sup { y: int }
let s = Sub {x: 10, y: 11};
let sx = s.x;
~~~~

### Enumerations

An _enumeration_ is a simultaneous definition of a nominal [enumerated type](#enumerated-types) as well as a set of *constructors*,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/front/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ fn fold_struct(cx: &Context, def: &ast::StructDef) -> @ast::StructDef {
@ast::StructDef {
fields: fields.collect(),
ctor_id: def.ctor_id,
super_struct: def.super_struct.clone(),
is_virtual: def.is_virtual,
}
}

Expand Down
14 changes: 13 additions & 1 deletion src/librustc/front/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
("default_type_params", Active),
("quote", Active),
("linkage", Active),
("struct_inherit", Active),

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

ast::ItemStruct(..) => {
ast::ItemStruct(struct_definition, _) => {
if attr::contains_name(i.attrs.as_slice(), "simd") {
self.gate_feature("simd", i.span,
"SIMD types are experimental and possibly buggy");
}
match struct_definition.super_struct {
Some(ref path) => self.gate_feature("struct_inherit", path.span,
"struct inheritance is experimental \
and possibly buggy"),
None => {}
}
if struct_definition.is_virtual {
self.gate_feature("struct_inherit", i.span,
"struct inheritance (`virtual` keyword) is \
experimental and possibly buggy");
}
}

_ => {}
Expand Down
117 changes: 59 additions & 58 deletions src/librustc/metadata/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub static tag_path_len: uint = 0x25;
pub static tag_path_elem_mod: uint = 0x26;
pub static tag_path_elem_name: uint = 0x27;
pub static tag_item_field: uint = 0x28;
pub static tag_item_field_origin: uint = 0x29;

pub static tag_item_variances: uint = 0x2a;
/*
Expand All @@ -102,43 +103,43 @@ pub static tag_item_variances: uint = 0x2a;
both, tag_item_trait_method and tag_item_impl_method have to be two
different tags.
*/
pub static tag_item_impl_method: uint = 0x2c;
pub static tag_item_trait_method_explicit_self: uint = 0x2d;
pub static tag_item_impl_method: uint = 0x30;
pub static tag_item_trait_method_explicit_self: uint = 0x31;


// Reexports are found within module tags. Each reexport contains def_ids
// and names.
pub static tag_items_data_item_reexport: uint = 0x2f;
pub static tag_items_data_item_reexport_def_id: uint = 0x30;
pub static tag_items_data_item_reexport_name: uint = 0x31;
pub static tag_items_data_item_reexport: uint = 0x38;
pub static tag_items_data_item_reexport_def_id: uint = 0x39;
pub static tag_items_data_item_reexport_name: uint = 0x3a;

// used to encode crate_ctxt side tables
#[deriving(Eq)]
#[repr(uint)]
pub enum astencode_tag { // Reserves 0x32 -- 0x45
tag_ast = 0x32,

tag_tree = 0x33,

tag_id_range = 0x34,

tag_table = 0x35,
tag_table_id = 0x36,
tag_table_val = 0x37,
tag_table_def = 0x38,
tag_table_node_type = 0x39,
tag_table_node_type_subst = 0x3a,
tag_table_freevars = 0x3b,
tag_table_tcache = 0x3c,
tag_table_param_defs = 0x3d,
tag_table_mutbl = 0x3e,
tag_table_last_use = 0x3f,
tag_table_spill = 0x40,
tag_table_method_map = 0x41,
tag_table_vtable_map = 0x42,
tag_table_adjustments = 0x43,
tag_table_moves_map = 0x44,
tag_table_capture_map = 0x45
pub enum astencode_tag { // Reserves 0x40 -- 0x5f
tag_ast = 0x40,

tag_tree = 0x41,

tag_id_range = 0x42,

tag_table = 0x43,
tag_table_id = 0x44,
tag_table_val = 0x45,
tag_table_def = 0x46,
tag_table_node_type = 0x47,
tag_table_node_type_subst = 0x48,
tag_table_freevars = 0x49,
tag_table_tcache = 0x4a,
tag_table_param_defs = 0x4b,
tag_table_mutbl = 0x4c,
tag_table_last_use = 0x4d,
tag_table_spill = 0x4e,
tag_table_method_map = 0x4f,
tag_table_vtable_map = 0x50,
tag_table_adjustments = 0x51,
tag_table_moves_map = 0x52,
tag_table_capture_map = 0x53
}
static first_astencode_tag: uint = tag_ast as uint;
static last_astencode_tag: uint = tag_table_capture_map as uint;
Expand All @@ -151,9 +152,9 @@ impl astencode_tag {
}
}

pub static tag_item_trait_method_sort: uint = 0x46;
pub static tag_item_trait_method_sort: uint = 0x60;

pub static tag_item_impl_type_basename: uint = 0x47;
pub static tag_item_impl_type_basename: uint = 0x61;

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

pub static tag_lang_items: uint = 0x48;
pub static tag_lang_items_item: uint = 0x49;
pub static tag_lang_items_item_id: uint = 0x4a;
pub static tag_lang_items_item_node_id: uint = 0x4b;
pub static tag_lang_items: uint = 0x70;
pub static tag_lang_items_item: uint = 0x71;
pub static tag_lang_items_item_id: uint = 0x72;
pub static tag_lang_items_item_node_id: uint = 0x73;

pub static tag_item_unnamed_field: uint = 0x4c;
pub static tag_items_data_item_visibility: uint = 0x4e;
pub static tag_item_unnamed_field: uint = 0x74;
pub static tag_items_data_item_visibility: uint = 0x76;

pub static tag_item_method_tps: uint = 0x51;
pub static tag_item_method_fty: uint = 0x52;
pub static tag_item_method_tps: uint = 0x79;
pub static tag_item_method_fty: uint = 0x7a;

pub static tag_mod_child: uint = 0x53;
pub static tag_misc_info: uint = 0x54;
pub static tag_misc_info_crate_items: uint = 0x55;
pub static tag_mod_child: uint = 0x7b;
pub static tag_misc_info: uint = 0x7c;
pub static tag_misc_info_crate_items: uint = 0x7d;

pub static tag_item_method_provided_source: uint = 0x56;
pub static tag_item_impl_vtables: uint = 0x57;
pub static tag_item_method_provided_source: uint = 0x7e;
pub static tag_item_impl_vtables: uint = 0x7f;

pub static tag_impls: uint = 0x58;
pub static tag_impls_impl: uint = 0x59;
pub static tag_impls: uint = 0x80;
pub static tag_impls_impl: uint = 0x81;

pub static tag_items_data_item_inherent_impl: uint = 0x5a;
pub static tag_items_data_item_extension_impl: uint = 0x5b;
pub static tag_items_data_item_inherent_impl: uint = 0x82;
pub static tag_items_data_item_extension_impl: uint = 0x83;

pub static tag_region_param_def: uint = 0x5c;
pub static tag_region_param_def_ident: uint = 0x5d;
pub static tag_region_param_def_def_id: uint = 0x5e;
pub static tag_region_param_def: uint = 0x84;
pub static tag_region_param_def_ident: uint = 0x85;
pub static tag_region_param_def_def_id: uint = 0x86;

pub static tag_native_libraries: uint = 0x5f;
pub static tag_native_libraries_lib: uint = 0x60;
pub static tag_native_libraries_name: uint = 0x61;
pub static tag_native_libraries_kind: uint = 0x62;
pub static tag_native_libraries: uint = 0x87;
pub static tag_native_libraries_lib: uint = 0x88;
pub static tag_native_libraries_name: uint = 0x89;
pub static tag_native_libraries_kind: uint = 0x8a;

pub static tag_macro_registrar_fn: uint = 0x63;
pub static tag_exported_macros: uint = 0x64;
pub static tag_macro_def: uint = 0x65;
pub static tag_macro_registrar_fn: uint = 0x8b;
pub static tag_exported_macros: uint = 0x8c;
pub static tag_macro_def: uint = 0x8d;

#[deriving(Clone, Show)]
pub struct LinkMeta {
Expand Down
10 changes: 8 additions & 2 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -975,21 +975,27 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
// FIXME #6993: name should be of type Name, not Ident
let name = item_name(&*intr, an_item);
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
result.push(ty::field_ty {
name: name.name,
id: did, vis:
struct_field_family_to_visibility(f),
id: did,
vis: struct_field_family_to_visibility(f),
origin: origin_id,
});
}
true
});
reader::tagged_docs(item, tag_item_unnamed_field, |an_item| {
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let f = item_family(an_item);
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
result.push(ty::field_ty {
name: special_idents::unnamed_field.name,
id: did,
vis: struct_field_family_to_visibility(f),
origin: origin_id,
});
true
});
Expand Down
63 changes: 32 additions & 31 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,23 +290,22 @@ fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
}

fn encode_struct_fields(ebml_w: &mut Encoder,
def: @StructDef) {
for f in def.fields.iter() {
match f.node.kind {
NamedField(ident, vis) => {
ebml_w.start_tag(tag_item_field);
encode_struct_field_family(ebml_w, vis);
encode_name(ebml_w, ident.name);
encode_def_id(ebml_w, local_def(f.node.id));
ebml_w.end_tag();
}
UnnamedField(vis) => {
ebml_w.start_tag(tag_item_unnamed_field);
encode_struct_field_family(ebml_w, vis);
encode_def_id(ebml_w, local_def(f.node.id));
ebml_w.end_tag();
}
fields: &Vec<ty::field_ty>,
origin: DefId) {
for f in fields.iter() {
if f.name == special_idents::unnamed_field.name {
ebml_w.start_tag(tag_item_unnamed_field);
} else {
ebml_w.start_tag(tag_item_field);
encode_name(ebml_w, f.name);
}
encode_struct_field_family(ebml_w, f.vis);
encode_def_id(ebml_w, f.id);
ebml_w.start_tag(tag_item_field_origin);
let s = def_to_str(origin);
ebml_w.writer.write(s.as_bytes());
ebml_w.end_tag();
ebml_w.end_tag();
}
}

Expand Down Expand Up @@ -344,12 +343,13 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
encode_symbol(ecx, ebml_w, variant.node.id);
}
ast::TupleVariantKind(_) => {},
ast::StructVariantKind(def) => {
ast::StructVariantKind(_) => {
let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
let idx = encode_info_for_struct(ecx,
ebml_w,
def.fields.as_slice(),
&fields,
index);
encode_struct_fields(ebml_w, def);
encode_struct_fields(ebml_w, &fields, def_id);
let bkts = create_index(idx);
encode_index(ebml_w, bkts, write_i64);
}
Expand Down Expand Up @@ -666,7 +666,7 @@ fn encode_provided_source(ebml_w: &mut Encoder,
/* Returns an index of items in this class */
fn encode_info_for_struct(ecx: &EncodeContext,
ebml_w: &mut Encoder,
fields: &[StructField],
fields: &Vec<ty::field_ty>,
global_index: @RefCell<Vec<entry<i64>> >)
-> Vec<entry<i64>> {
/* Each class has its own index, since different classes
Expand All @@ -676,22 +676,19 @@ fn encode_info_for_struct(ecx: &EncodeContext,
/* We encode both private and public fields -- need to include
private fields to get the offsets right */
for field in fields.iter() {
let (nm, vis) = match field.node.kind {
NamedField(nm, vis) => (nm, vis),
UnnamedField(vis) => (special_idents::unnamed_field, vis)
};
let nm = field.name;
let id = field.id.node;

let id = field.node.id;
index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
global_index.borrow_mut().push(entry {
val: id as i64,
pos: ebml_w.writer.tell().unwrap(),
});
ebml_w.start_tag(tag_items_data_item);
debug!("encode_info_for_struct: doing {} {}",
token::get_ident(nm), id);
encode_struct_field_family(ebml_w, vis);
encode_name(ebml_w, nm.name);
token::get_name(nm), id);
encode_struct_field_family(ebml_w, field.vis);
encode_name(ebml_w, nm);
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
encode_def_id(ebml_w, local_def(id));
ebml_w.end_tag();
Expand Down Expand Up @@ -983,12 +980,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
generics);
}
ItemStruct(struct_def, _) => {
let fields = ty::lookup_struct_fields(tcx, def_id);

/* First, encode the fields
These come first because we need to write them to make
the index, and the index needs to be in the item for the
class itself */
let idx = encode_info_for_struct(ecx, ebml_w,
struct_def.fields.as_slice(), index);
let idx = encode_info_for_struct(ecx,
ebml_w,
&fields,
index);

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

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

Expand Down
Loading