mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 07:44:10 +00:00
Remove virtual
structs from the language
This commit is contained in:
parent
9b98332992
commit
403cd40e6a
@ -56,7 +56,6 @@ register_diagnostics!(
|
|||||||
E0038,
|
E0038,
|
||||||
E0039,
|
E0039,
|
||||||
E0040,
|
E0040,
|
||||||
E0041,
|
|
||||||
E0044,
|
E0044,
|
||||||
E0045,
|
E0045,
|
||||||
E0046,
|
E0046,
|
||||||
@ -123,7 +122,6 @@ register_diagnostics!(
|
|||||||
E0121,
|
E0121,
|
||||||
E0122,
|
E0122,
|
||||||
E0124,
|
E0124,
|
||||||
E0126,
|
|
||||||
E0127,
|
E0127,
|
||||||
E0128,
|
E0128,
|
||||||
E0129,
|
E0129,
|
||||||
@ -141,9 +139,6 @@ register_diagnostics!(
|
|||||||
E0141,
|
E0141,
|
||||||
E0152,
|
E0152,
|
||||||
E0153,
|
E0153,
|
||||||
E0154,
|
|
||||||
E0155,
|
|
||||||
E0156,
|
|
||||||
E0157,
|
E0157,
|
||||||
E0158,
|
E0158,
|
||||||
E0159,
|
E0159,
|
||||||
|
@ -54,7 +54,6 @@ use syntax::parse::token::special_idents;
|
|||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::codemap::{Span, DUMMY_SP, Pos};
|
use syntax::codemap::{Span, DUMMY_SP, Pos};
|
||||||
use syntax::owned_slice::OwnedSlice;
|
use syntax::owned_slice::OwnedSlice;
|
||||||
use syntax::ptr::P;
|
|
||||||
use syntax::visit;
|
use syntax::visit;
|
||||||
use syntax::visit::Visitor;
|
use syntax::visit::Visitor;
|
||||||
|
|
||||||
@ -4179,7 +4178,6 @@ impl<'a> Resolver<'a> {
|
|||||||
ItemStruct(ref struct_def, ref generics) => {
|
ItemStruct(ref struct_def, ref generics) => {
|
||||||
self.resolve_struct(item.id,
|
self.resolve_struct(item.id,
|
||||||
generics,
|
generics,
|
||||||
&struct_def.super_struct,
|
|
||||||
struct_def.fields.as_slice());
|
struct_def.fields.as_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4505,7 +4503,6 @@ impl<'a> Resolver<'a> {
|
|||||||
fn resolve_struct(&mut self,
|
fn resolve_struct(&mut self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
super_struct: &Option<P<Ty>>,
|
|
||||||
fields: &[StructField]) {
|
fields: &[StructField]) {
|
||||||
// If applicable, create a rib for the type parameters.
|
// If applicable, create a rib for the type parameters.
|
||||||
self.with_type_parameter_rib(HasTypeParameters(generics,
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
||||||
@ -4517,42 +4514,6 @@ impl<'a> Resolver<'a> {
|
|||||||
this.resolve_type_parameters(&generics.ty_params);
|
this.resolve_type_parameters(&generics.ty_params);
|
||||||
this.resolve_where_clause(&generics.where_clause);
|
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.
|
// Resolve fields.
|
||||||
for field in fields.iter() {
|
for field in fields.iter() {
|
||||||
this.resolve_type(&*field.node.ty);
|
this.resolve_type(&*field.node.ty);
|
||||||
|
@ -24,13 +24,11 @@ use middle::mem_categorization as mc;
|
|||||||
use middle::resolve;
|
use middle::resolve;
|
||||||
use middle::resolve_lifetime;
|
use middle::resolve_lifetime;
|
||||||
use middle::stability;
|
use middle::stability;
|
||||||
use middle::subst::{Subst, Substs, VecPerParamSpace};
|
use middle::subst::{mod, Subst, Substs, VecPerParamSpace};
|
||||||
use middle::subst;
|
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::typeck;
|
use middle::typeck;
|
||||||
use middle::ty_fold;
|
use middle::ty_fold::{mod, TypeFoldable,TypeFolder};
|
||||||
use middle::ty_fold::{TypeFoldable,TypeFolder};
|
|
||||||
use middle;
|
use middle;
|
||||||
use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
|
use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
|
||||||
use util::ppaux::{trait_store_to_string, ty_to_string};
|
use util::ppaux::{trait_store_to_string, ty_to_string};
|
||||||
@ -40,10 +38,8 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet, FnvHashMap};
|
|||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt::Show;
|
use std::fmt::{mod, Show};
|
||||||
use std::fmt;
|
|
||||||
use std::hash::{Hash, sip, Writer};
|
use std::hash::{Hash, sip, Writer};
|
||||||
use std::iter::AdditiveIterator;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -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::{MutImmutable, MutMutable, Name, NamedField, NodeId};
|
||||||
use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
|
use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
|
||||||
use syntax::ast::{Visibility};
|
use syntax::ast::{Visibility};
|
||||||
use syntax::ast_util::{PostExpansionMethod, is_local, lit_is_str};
|
use syntax::ast_util::{mod, PostExpansionMethod, is_local, lit_is_str};
|
||||||
use syntax::ast_util;
|
use syntax::attr::{mod, AttrMetaMethods};
|
||||||
use syntax::attr;
|
|
||||||
use syntax::attr::AttrMetaMethods;
|
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token::{mod, InternedString};
|
||||||
use syntax::parse::token::InternedString;
|
|
||||||
use syntax::{ast, ast_map};
|
use syntax::{ast, ast_map};
|
||||||
use syntax::util::small_vector::SmallVector;
|
|
||||||
use std::collections::enum_set::{EnumSet, CLike};
|
use std::collections::enum_set::{EnumSet, CLike};
|
||||||
|
|
||||||
pub type Disr = u64;
|
pub type Disr = u64;
|
||||||
@ -493,7 +485,6 @@ pub struct ctxt<'tcx> {
|
|||||||
pub lang_items: middle::lang_items::LanguageItems,
|
pub lang_items: middle::lang_items::LanguageItems,
|
||||||
/// A mapping of fake provided method def_ids to the default implementation
|
/// A mapping of fake provided method def_ids to the default implementation
|
||||||
pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
|
pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
|
||||||
pub superstructs: RefCell<DefIdMap<Option<ast::DefId>>>,
|
|
||||||
pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,
|
pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,
|
||||||
|
|
||||||
/// Maps from def-id of a type or region parameter to its
|
/// Maps from def-id of a type or region parameter to its
|
||||||
@ -1512,7 +1503,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
|||||||
normalized_cache: RefCell::new(HashMap::new()),
|
normalized_cache: RefCell::new(HashMap::new()),
|
||||||
lang_items: lang_items,
|
lang_items: lang_items,
|
||||||
provided_method_sources: RefCell::new(DefIdMap::new()),
|
provided_method_sources: RefCell::new(DefIdMap::new()),
|
||||||
superstructs: RefCell::new(DefIdMap::new()),
|
|
||||||
struct_fields: RefCell::new(DefIdMap::new()),
|
struct_fields: RefCell::new(DefIdMap::new()),
|
||||||
destructor_for_type: RefCell::new(DefIdMap::new()),
|
destructor_for_type: RefCell::new(DefIdMap::new()),
|
||||||
destructors: RefCell::new(DefIdSet::new()),
|
destructors: RefCell::new(DefIdSet::new()),
|
||||||
@ -4539,53 +4529,19 @@ pub fn lookup_field_type(tcx: &ctxt,
|
|||||||
t.subst(tcx, substs)
|
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.
|
// Look up the list of field names and IDs for a given struct.
|
||||||
// Fails if the id is not bound to a struct.
|
// Fails if the id is not bound to a struct.
|
||||||
pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
|
pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
|
||||||
if did.krate == ast::LOCAL_CRATE {
|
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 struct_fields = cx.struct_fields.borrow();
|
||||||
let mut results: SmallVector<&[field_ty]> = SmallVector::zero();
|
match struct_fields.find(&did) {
|
||||||
each_super_struct(cx, did, |s| {
|
Some(fields) => (**fields).clone(),
|
||||||
match struct_fields.find(&s) {
|
_ => {
|
||||||
Some(fields) => results.push(fields.as_slice()),
|
cx.sess.bug(
|
||||||
_ => {
|
format!("ID not mapped to struct fields: {}",
|
||||||
cx.sess.bug(
|
cx.map.node_to_string(did.node)).as_slice());
|
||||||
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 {
|
} else {
|
||||||
csearch::get_struct_fields(&cx.sess.cstore, did)
|
csearch::get_struct_fields(&cx.sess.cstore, did)
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,6 @@ use std::rc::Rc;
|
|||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem};
|
use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast_map;
|
|
||||||
use syntax::ast_util::{local_def, PostExpansionMethod};
|
use syntax::ast_util::{local_def, PostExpansionMethod};
|
||||||
use syntax::ast_util;
|
use syntax::ast_util;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
@ -602,69 +601,12 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
|
|||||||
fcx
|
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) {
|
pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
|
||||||
let tcx = ccx.tcx;
|
let tcx = ccx.tcx;
|
||||||
|
|
||||||
check_representable(tcx, span, id, "struct");
|
check_representable(tcx, span, id, "struct");
|
||||||
check_instantiable(tcx, span, id);
|
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)) {
|
if ty::lookup_simd(tcx, local_def(id)) {
|
||||||
check_simd(tcx, span, id);
|
check_simd(tcx, span, id);
|
||||||
}
|
}
|
||||||
|
@ -1235,15 +1235,6 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
|||||||
|
|
||||||
tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
|
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);
|
convert_struct(ccx, &**struct_def, pty, it.id);
|
||||||
},
|
},
|
||||||
ast::ItemTy(_, ref generics) => {
|
ast::ItemTy(_, ref generics) => {
|
||||||
@ -1295,39 +1286,6 @@ pub fn convert_struct(ccx: &CrateCtxt,
|
|||||||
|
|
||||||
tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
|
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 substs = mk_item_substs(ccx, &pty.generics);
|
||||||
let selfty = ty::mk_struct(tcx, local_def(id), substs);
|
let selfty = ty::mk_struct(tcx, local_def(id), substs);
|
||||||
|
|
||||||
|
@ -1286,10 +1286,6 @@ pub struct StructDef {
|
|||||||
/// ID of the constructor. This is only used for tuple- or enum-like
|
/// ID of the constructor. This is only used for tuple- or enum-like
|
||||||
/// structs.
|
/// structs.
|
||||||
pub ctor_id: Option<NodeId>,
|
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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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> {
|
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 {
|
ast::StructDef {
|
||||||
fields: fields.into_iter().filter(|m| {
|
fields: fields.into_iter().filter(|m| {
|
||||||
(cx.in_cfg)(m.node.attrs.as_slice())
|
(cx.in_cfg)(m.node.attrs.as_slice())
|
||||||
}).collect(),
|
}).collect(),
|
||||||
ctor_id: ctor_id,
|
ctor_id: ctor_id,
|
||||||
super_struct: super_struct,
|
|
||||||
is_virtual: is_virtual,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -218,22 +218,11 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ItemStruct(ref struct_definition, _) => {
|
ast::ItemStruct(..) => {
|
||||||
if attr::contains_name(i.attrs.as_slice(), "simd") {
|
if attr::contains_name(i.attrs.as_slice(), "simd") {
|
||||||
self.gate_feature("simd", i.span,
|
self.gate_feature("simd", i.span,
|
||||||
"SIMD types are experimental and possibly buggy");
|
"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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ItemImpl(_, _, _, ref items) => {
|
ast::ItemImpl(_, _, _, ref items) => {
|
||||||
|
@ -801,11 +801,9 @@ pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
|
pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
|
||||||
struct_def.map(|StructDef {fields, ctor_id, super_struct, is_virtual}| StructDef {
|
struct_def.map(|StructDef { fields, ctor_id }| StructDef {
|
||||||
fields: fields.move_map(|f| fld.fold_struct_field(f)),
|
fields: fields.move_map(|f| fld.fold_struct_field(f)),
|
||||||
ctor_id: ctor_id.map(|cid| fld.new_id(cid)),
|
ctor_id: ctor_id.map(|cid| fld.new_id(cid)),
|
||||||
super_struct: super_struct.map(|t| fld.fold_ty(t)),
|
|
||||||
is_virtual: is_virtual
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4540,24 +4540,14 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse struct Foo { ... }
|
/// Parse struct Foo { ... }
|
||||||
fn parse_item_struct(&mut self, is_virtual: bool) -> ItemInfo {
|
fn parse_item_struct(&mut self) -> ItemInfo {
|
||||||
let class_name = self.parse_ident();
|
let class_name = self.parse_ident();
|
||||||
let mut generics = self.parse_generics();
|
let mut generics = self.parse_generics();
|
||||||
|
|
||||||
let super_struct = if self.eat(&token::COLON) {
|
if self.eat(&token::COLON) {
|
||||||
let ty = self.parse_ty(true);
|
let ty = self.parse_ty(true);
|
||||||
match ty.node {
|
self.span_err(ty.span, "`virtual` structs have been removed from the language");
|
||||||
TyPath(_, None, _) => {
|
}
|
||||||
Some(ty)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.span_err(ty.span, "not a struct");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
self.parse_where_clause(&mut generics);
|
self.parse_where_clause(&mut generics);
|
||||||
|
|
||||||
@ -4618,8 +4608,6 @@ impl<'a> Parser<'a> {
|
|||||||
ItemStruct(P(ast::StructDef {
|
ItemStruct(P(ast::StructDef {
|
||||||
fields: fields,
|
fields: fields,
|
||||||
ctor_id: if is_tuple_like { Some(new_id) } else { None },
|
ctor_id: if is_tuple_like { Some(new_id) } else { None },
|
||||||
super_struct: super_struct,
|
|
||||||
is_virtual: is_virtual,
|
|
||||||
}), generics),
|
}), generics),
|
||||||
None)
|
None)
|
||||||
}
|
}
|
||||||
@ -5090,8 +5078,6 @@ impl<'a> Parser<'a> {
|
|||||||
P(StructDef {
|
P(StructDef {
|
||||||
fields: fields,
|
fields: fields,
|
||||||
ctor_id: None,
|
ctor_id: None,
|
||||||
super_struct: None,
|
|
||||||
is_virtual: false,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5288,11 +5274,9 @@ impl<'a> Parser<'a> {
|
|||||||
token_str).as_slice());
|
token_str).as_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_virtual = self.eat_keyword(keywords::Virtual);
|
if self.eat_keyword(keywords::Virtual) {
|
||||||
if is_virtual && !self.is_keyword(keywords::Struct) {
|
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
self.span_err(span,
|
self.span_err(span, "`virtual` structs have been removed from the language");
|
||||||
"`virtual` keyword may only be used with `struct`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the rest are all guaranteed to be items:
|
// the rest are all guaranteed to be items:
|
||||||
@ -5427,7 +5411,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
if self.eat_keyword(keywords::Struct) {
|
if self.eat_keyword(keywords::Struct) {
|
||||||
// STRUCT ITEM
|
// STRUCT ITEM
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_struct(is_virtual);
|
let (ident, item_, extra_attrs) = self.parse_item_struct();
|
||||||
let last_span = self.last_span;
|
let last_span = self.last_span;
|
||||||
let item = self.mk_item(lo,
|
let item = self.mk_item(lo,
|
||||||
last_span.hi,
|
last_span.hi,
|
||||||
|
@ -826,9 +826,6 @@ impl<'a> State<'a> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
ast::ItemStruct(ref struct_def, ref generics) => {
|
ast::ItemStruct(ref struct_def, ref generics) => {
|
||||||
if struct_def.is_virtual {
|
|
||||||
try!(self.word_space("virtual"));
|
|
||||||
}
|
|
||||||
try!(self.head(visibility_qualified(item.vis,"struct").as_slice()));
|
try!(self.head(visibility_qualified(item.vis,"struct").as_slice()));
|
||||||
try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
|
try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
|
||||||
}
|
}
|
||||||
@ -968,13 +965,6 @@ impl<'a> State<'a> {
|
|||||||
span: codemap::Span) -> IoResult<()> {
|
span: codemap::Span) -> IoResult<()> {
|
||||||
try!(self.print_ident(ident));
|
try!(self.print_ident(ident));
|
||||||
try!(self.print_generics(generics));
|
try!(self.print_generics(generics));
|
||||||
match struct_def.super_struct {
|
|
||||||
Some(ref t) => {
|
|
||||||
try!(self.word_space(":"));
|
|
||||||
try!(self.print_type(&**t));
|
|
||||||
},
|
|
||||||
None => {},
|
|
||||||
}
|
|
||||||
if ast_util::struct_def_is_tuple_like(struct_def) {
|
if ast_util::struct_def_is_tuple_like(struct_def) {
|
||||||
if !struct_def.fields.is_empty() {
|
if !struct_def.fields.is_empty() {
|
||||||
try!(self.popen());
|
try!(self.popen());
|
||||||
|
@ -603,10 +603,6 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_method: &'v Tr
|
|||||||
|
|
||||||
pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V,
|
pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||||
struct_definition: &'v StructDef) {
|
struct_definition: &'v StructDef) {
|
||||||
match struct_definition.super_struct {
|
|
||||||
Some(ref t) => visitor.visit_ty(&**t),
|
|
||||||
None => {},
|
|
||||||
}
|
|
||||||
for field in struct_definition.fields.iter() {
|
for field in struct_definition.fields.iter() {
|
||||||
visitor.visit_struct_field(field)
|
visitor.visit_struct_field(field)
|
||||||
}
|
}
|
||||||
|
20
src/test/compile-fail/virtual-structs.rs
Normal file
20
src/test/compile-fail/virtual-structs.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Test diagnostics for the removed struct inheritance feature.
|
||||||
|
#![feature(struct_inherit)]
|
||||||
|
|
||||||
|
virtual struct SuperStruct { //~ ERROR `virtual` structs have been removed from the language
|
||||||
|
f1: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Struct : SuperStruct; //~ ERROR `virtual` structs have been removed from the language
|
||||||
|
|
||||||
|
pub fn main() {}
|
Loading…
Reference in New Issue
Block a user