Skip to content

Remove virtual structs #17952

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

Merged
merged 3 commits into from Oct 12, 2014
Merged
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
17 changes: 0 additions & 17 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1328,23 +1328,6 @@ let c = [Cookie, Cookie, Cookie, Cookie];
The precise memory layout of a structure is not specified. One can specify a
particular layout using the [`repr` attribute](#ffi-attributes).

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
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ register_diagnostics!(
E0038,
E0039,
E0040,
E0041,
E0044,
E0045,
E0046,
Expand Down Expand Up @@ -123,7 +122,6 @@ register_diagnostics!(
E0121,
E0122,
E0124,
E0126,
E0127,
E0128,
E0129,
Expand All @@ -141,9 +139,6 @@ register_diagnostics!(
E0141,
E0152,
E0153,
E0154,
E0155,
E0156,
E0157,
E0158,
E0159,
Expand Down
39 changes: 0 additions & 39 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ use syntax::parse::token::special_idents;
use syntax::parse::token;
use syntax::codemap::{Span, DUMMY_SP, Pos};
use syntax::owned_slice::OwnedSlice;
use syntax::ptr::P;
use syntax::visit;
use syntax::visit::Visitor;

Expand Down Expand Up @@ -4179,7 +4178,6 @@ impl<'a> Resolver<'a> {
ItemStruct(ref struct_def, ref generics) => {
self.resolve_struct(item.id,
generics,
&struct_def.super_struct,
struct_def.fields.as_slice());
}

Expand Down Expand Up @@ -4505,7 +4503,6 @@ impl<'a> Resolver<'a> {
fn resolve_struct(&mut self,
id: NodeId,
generics: &Generics,
super_struct: &Option<P<Ty>>,
fields: &[StructField]) {
// If applicable, create a rib for the type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics,
Expand All @@ -4517,42 +4514,6 @@ impl<'a> Resolver<'a> {
this.resolve_type_parameters(&generics.ty_params);
this.resolve_where_clause(&generics.where_clause);

// Resolve the super struct.
match *super_struct {
Some(ref t) => match t.node {
TyPath(ref path, None, path_id) => {
match this.resolve_path(id, path, TypeNS, true) {
Some((DefTy(def_id, _), lp)) if this.structs.contains_key(&def_id) => {
let def = DefStruct(def_id);
debug!("(resolving struct) resolved `{}` to type {:?}",
token::get_ident(path.segments
.last().unwrap()
.identifier),
def);
debug!("(resolving struct) writing resolution for `{}` (id {})",
this.path_idents_to_string(path),
path_id);
this.record_def(path_id, (def, lp));
}
Some((DefStruct(_), _)) => {
span_err!(this.session, t.span, E0154,
"super-struct is defined in a different crate");
},
Some(_) => {
span_err!(this.session, t.span, E0155,
"super-struct is not a struct type");
}
None => {
span_err!(this.session, t.span, E0156,
"super-struct could not be resolved");
}
}
},
_ => this.session.span_bug(t.span, "path not mapped to a TyPath")
},
None => {}
}

// Resolve fields.
for field in fields.iter() {
this.resolve_type(&*field.node.ty);
Expand Down
70 changes: 13 additions & 57 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@ use middle::mem_categorization as mc;
use middle::resolve;
use middle::resolve_lifetime;
use middle::stability;
use middle::subst::{Subst, Substs, VecPerParamSpace};
use middle::subst;
use middle::subst::{mod, Subst, Substs, VecPerParamSpace};
use middle::traits;
use middle::ty;
use middle::typeck;
use middle::ty_fold;
use middle::ty_fold::{TypeFoldable,TypeFolder};
use middle::ty_fold::{mod, TypeFoldable,TypeFolder};
use middle;
use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
use util::ppaux::{trait_store_to_string, ty_to_string};
Expand All @@ -40,10 +38,8 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet, FnvHashMap};

use std::cell::{Cell, RefCell};
use std::cmp;
use std::fmt::Show;
use std::fmt;
use std::fmt::{mod, Show};
use std::hash::{Hash, sip, Writer};
use std::iter::AdditiveIterator;
use std::mem;
use std::ops;
use std::rc::Rc;
Expand All @@ -55,15 +51,11 @@ use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE};
use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
use syntax::ast::{Visibility};
use syntax::ast_util::{PostExpansionMethod, is_local, lit_is_str};
use syntax::ast_util;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::ast_util::{mod, PostExpansionMethod, is_local, lit_is_str};
use syntax::attr::{mod, AttrMetaMethods};
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::parse::token::InternedString;
use syntax::parse::token::{mod, InternedString};
use syntax::{ast, ast_map};
use syntax::util::small_vector::SmallVector;
use std::collections::enum_set::{EnumSet, CLike};

pub type Disr = u64;
Expand Down Expand Up @@ -493,7 +485,6 @@ pub struct ctxt<'tcx> {
pub lang_items: middle::lang_items::LanguageItems,
/// A mapping of fake provided method def_ids to the default implementation
pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
pub superstructs: RefCell<DefIdMap<Option<ast::DefId>>>,
pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,

/// Maps from def-id of a type or region parameter to its
Expand Down Expand Up @@ -1512,7 +1503,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
normalized_cache: RefCell::new(HashMap::new()),
lang_items: lang_items,
provided_method_sources: RefCell::new(DefIdMap::new()),
superstructs: RefCell::new(DefIdMap::new()),
struct_fields: RefCell::new(DefIdMap::new()),
destructor_for_type: RefCell::new(DefIdMap::new()),
destructors: RefCell::new(DefIdSet::new()),
Expand Down Expand Up @@ -4539,53 +4529,19 @@ pub fn lookup_field_type(tcx: &ctxt,
t.subst(tcx, substs)
}

// Lookup all ancestor structs of a struct indicated by did. That is the reflexive,
// transitive closure of doing a single lookup in cx.superstructs.
fn each_super_struct(cx: &ctxt, mut did: ast::DefId, f: |ast::DefId|) {
let superstructs = cx.superstructs.borrow();

loop {
f(did);
match superstructs.find(&did) {
Some(&Some(def_id)) => {
did = def_id;
},
Some(&None) => break,
None => {
cx.sess.bug(
format!("ID not mapped to super-struct: {}",
cx.map.node_to_string(did.node)).as_slice());
}
}
}
}

// Look up the list of field names and IDs for a given struct.
// Fails if the id is not bound to a struct.
pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
if did.krate == ast::LOCAL_CRATE {
// We store the fields which are syntactically in each struct in cx. So
// we have to walk the inheritance chain of the struct to get all the
// fields (explicit and inherited) for a struct. If this is expensive
// we could cache the whole list of fields here.
let struct_fields = cx.struct_fields.borrow();
let mut results: SmallVector<&[field_ty]> = SmallVector::zero();
each_super_struct(cx, did, |s| {
match struct_fields.find(&s) {
Some(fields) => results.push(fields.as_slice()),
_ => {
cx.sess.bug(
format!("ID not mapped to struct fields: {}",
cx.map.node_to_string(did.node)).as_slice());
}
match struct_fields.find(&did) {
Some(fields) => (**fields).clone(),
_ => {
cx.sess.bug(
format!("ID not mapped to struct fields: {}",
cx.map.node_to_string(did.node)).as_slice());
}
});

let len = results.as_slice().iter().map(|x| x.len()).sum();
let mut result: Vec<field_ty> = Vec::with_capacity(len);
result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|f| f.clone())));
assert!(result.len() == len);
result
}
} else {
csearch::get_struct_fields(&cx.sess.cstore, did)
}
Expand Down
58 changes: 0 additions & 58 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ use std::rc::Rc;
use syntax::abi;
use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem};
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::{local_def, PostExpansionMethod};
use syntax::ast_util;
use syntax::attr;
Expand Down Expand Up @@ -602,69 +601,12 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
fcx
}

fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
assert!(field.id.krate == ast::LOCAL_CRATE);
let item = match tcx.map.find(struct_id.node) {
Some(ast_map::NodeItem(item)) => item,
None => fail!("node not in ast map: {}", struct_id.node),
_ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
};

match item.node {
ast::ItemStruct(ref struct_def, _) => {
match struct_def.fields.iter().find(|f| match f.node.kind {
ast::NamedField(ident, _) => ident.name == field.name,
_ => false,
}) {
Some(f) => f.span,
None => {
tcx.sess
.bug(format!("Could not find field {}",
token::get_name(field.name)).as_slice())
}
}
},
_ => tcx.sess.bug("Field found outside of a struct?"),
}
}

// Check struct fields are uniquely named wrt parents.
fn check_for_field_shadowing(tcx: &ty::ctxt,
id: ast::DefId) {
let struct_fields = tcx.struct_fields.borrow();
let fields = struct_fields.get(&id);

let superstructs = tcx.superstructs.borrow();
let super_struct = superstructs.get(&id);
match *super_struct {
Some(parent_id) => {
let super_fields = ty::lookup_struct_fields(tcx, parent_id);
for f in fields.iter() {
match super_fields.iter().find(|sf| f.name == sf.name) {
Some(prev_field) => {
span_err!(tcx.sess, span_for_field(tcx, f, id), E0041,
"field `{}` hides field declared in super-struct",
token::get_name(f.name));
span_note!(tcx.sess, span_for_field(tcx, prev_field, parent_id),
"previously declared here");
},
None => {}
}
}
},
None => {}
}
}

pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
let tcx = ccx.tcx;

check_representable(tcx, span, id, "struct");
check_instantiable(tcx, span, id);

// Check there are no overlapping fields in super-structs
check_for_field_shadowing(tcx, local_def(id));

if ty::lookup_simd(tcx, local_def(id)) {
check_simd(tcx, span, id);
}
Expand Down
42 changes: 0 additions & 42 deletions src/librustc/middle/typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,15 +1235,6 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {

tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());

// Write the super-struct type, if it exists.
match struct_def.super_struct {
Some(ref ty) => {
let supserty = ccx.to_ty(&ExplicitRscope, &**ty);
write_ty_to_tcx(tcx, it.id, supserty);
},
_ => {},
}

convert_struct(ccx, &**struct_def, pty, it.id);
},
ast::ItemTy(_, ref generics) => {
Expand Down Expand Up @@ -1295,39 +1286,6 @@ pub fn convert_struct(ccx: &CrateCtxt,

tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));

let super_struct = match struct_def.super_struct {
Some(ref t) => match t.node {
ast::TyPath(_, _, path_id) => {
let def_map = tcx.def_map.borrow();
match def_map.find(&path_id) {
Some(&def::DefStruct(def_id)) => {
// FIXME(#12511) Check for cycles in the inheritance hierarchy.
// Check super-struct is virtual.
match tcx.map.find(def_id.node) {
Some(ast_map::NodeItem(i)) => match i.node {
ast::ItemStruct(ref struct_def, _) => {
if !struct_def.is_virtual {
span_err!(tcx.sess, t.span, E0126,
"struct inheritance is only \
allowed from virtual structs");
}
},
_ => {},
},
_ => {},
}

Some(def_id)
},
_ => None,
}
}
_ => None,
},
None => None,
};
tcx.superstructs.borrow_mut().insert(local_def(id), super_struct);

let substs = mk_item_substs(ccx, &pty.generics);
let selfty = ty::mk_struct(tcx, local_def(id), substs);

Expand Down
4 changes: 0 additions & 4 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1286,10 +1286,6 @@ pub struct StructDef {
/// ID of the constructor. This is only used for tuple- or enum-like
/// structs.
pub ctor_id: Option<NodeId>,
/// Super struct, if specified.
pub super_struct: Option<P<Ty>>,
/// True iff the struct may be inherited from.
pub is_virtual: bool,
}

/*
Expand Down
Loading