Skip to content

Commit

Permalink
Remove virtual structs from the language
Browse files Browse the repository at this point in the history
  • Loading branch information
Jakub Wieczorek committed Oct 11, 2014
1 parent 9b98332 commit 403cd40
Show file tree
Hide file tree
Showing 13 changed files with 43 additions and 260 deletions.
5 changes: 0 additions & 5 deletions src/librustc/diagnostics.rs
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
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
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
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
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
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
4 changes: 1 addition & 3 deletions src/libsyntax/config.rs
Expand Up @@ -158,14 +158,12 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ {
}

fn fold_struct(cx: &mut Context, def: P<ast::StructDef>) -> P<ast::StructDef> {
def.map(|ast::StructDef {fields, ctor_id, super_struct, is_virtual}| {
def.map(|ast::StructDef { fields, ctor_id }| {
ast::StructDef {
fields: fields.into_iter().filter(|m| {
(cx.in_cfg)(m.node.attrs.as_slice())
}).collect(),
ctor_id: ctor_id,
super_struct: super_struct,
is_virtual: is_virtual,
}
})
}
Expand Down

0 comments on commit 403cd40

Please sign in to comment.