From 403cd40e6a29cc0f897e4b3d80e1e2bcf38f8875 Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Sat, 11 Oct 2014 19:24:58 +0200 Subject: [PATCH] Remove `virtual` structs from the language --- src/librustc/diagnostics.rs | 5 -- src/librustc/middle/resolve.rs | 39 ------------- src/librustc/middle/ty.rs | 70 +++++------------------- src/librustc/middle/typeck/check/mod.rs | 58 -------------------- src/librustc/middle/typeck/collect.rs | 42 -------------- src/libsyntax/ast.rs | 4 -- src/libsyntax/config.rs | 4 +- src/libsyntax/feature_gate.rs | 13 +---- src/libsyntax/fold.rs | 4 +- src/libsyntax/parse/parser.rs | 30 +++------- src/libsyntax/print/pprust.rs | 10 ---- src/libsyntax/visit.rs | 4 -- src/test/compile-fail/virtual-structs.rs | 20 +++++++ 13 files changed, 43 insertions(+), 260 deletions(-) create mode 100644 src/test/compile-fail/virtual-structs.rs diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index b39c4152168..31dff0b1471 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -56,7 +56,6 @@ register_diagnostics!( E0038, E0039, E0040, - E0041, E0044, E0045, E0046, @@ -123,7 +122,6 @@ register_diagnostics!( E0121, E0122, E0124, - E0126, E0127, E0128, E0129, @@ -141,9 +139,6 @@ register_diagnostics!( E0141, E0152, E0153, - E0154, - E0155, - E0156, E0157, E0158, E0159, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index d40c252d5f5..c1c5c1af681 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -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; @@ -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()); } @@ -4505,7 +4503,6 @@ impl<'a> Resolver<'a> { fn resolve_struct(&mut self, id: NodeId, generics: &Generics, - super_struct: &Option>, fields: &[StructField]) { // If applicable, create a rib for the type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, @@ -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); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index cea74c6573d..071f6b12684 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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}; @@ -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; @@ -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; @@ -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>, - pub superstructs: RefCell>>, pub struct_fields: RefCell>>>, /// 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()), 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()), @@ -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 { 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 = 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) } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 68bb3fcf945..ed663cb85a2 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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; @@ -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); } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 0b5c86fea71..100dffb547b 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -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) => { @@ -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); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 274bb2e39e0..44b327745ed 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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, - /// Super struct, if specified. - pub super_struct: Option>, - /// True iff the struct may be inherited from. - pub is_virtual: bool, } /* diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 9b4748f88ab..a53be6097fd 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -158,14 +158,12 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ { } fn fold_struct(cx: &mut Context, def: P) -> P { - 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, } }) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c3c36d04442..590157d677d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -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") { 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"); - } } ast::ItemImpl(_, _, _, ref items) => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 32e226361e9..3e16bca72ef 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -801,11 +801,9 @@ pub fn noop_fold_associated_type(at: AssociatedType, folder: &mut T) } pub fn noop_fold_struct_def(struct_def: P, fld: &mut T) -> P { - 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)), ctor_id: ctor_id.map(|cid| fld.new_id(cid)), - super_struct: super_struct.map(|t| fld.fold_ty(t)), - is_virtual: is_virtual }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e7f40cf0722..daaf6744d9d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4540,24 +4540,14 @@ impl<'a> Parser<'a> { } /// 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 mut generics = self.parse_generics(); - let super_struct = if self.eat(&token::COLON) { + if self.eat(&token::COLON) { let ty = self.parse_ty(true); - match ty.node { - TyPath(_, None, _) => { - Some(ty) - } - _ => { - self.span_err(ty.span, "not a struct"); - None - } - } - } else { - None - }; + self.span_err(ty.span, "`virtual` structs have been removed from the language"); + } self.parse_where_clause(&mut generics); @@ -4618,8 +4608,6 @@ impl<'a> Parser<'a> { ItemStruct(P(ast::StructDef { fields: fields, ctor_id: if is_tuple_like { Some(new_id) } else { None }, - super_struct: super_struct, - is_virtual: is_virtual, }), generics), None) } @@ -5090,8 +5078,6 @@ impl<'a> Parser<'a> { P(StructDef { fields: fields, ctor_id: None, - super_struct: None, - is_virtual: false, }) } @@ -5288,11 +5274,9 @@ impl<'a> Parser<'a> { token_str).as_slice()); } - let is_virtual = self.eat_keyword(keywords::Virtual); - if is_virtual && !self.is_keyword(keywords::Struct) { + if self.eat_keyword(keywords::Virtual) { let span = self.span; - self.span_err(span, - "`virtual` keyword may only be used with `struct`"); + self.span_err(span, "`virtual` structs have been removed from the language"); } // the rest are all guaranteed to be items: @@ -5427,7 +5411,7 @@ impl<'a> Parser<'a> { } if self.eat_keyword(keywords::Struct) { // 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 item = self.mk_item(lo, last_span.hi, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e1a2b2aeefe..c9a6354bf97 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -826,9 +826,6 @@ impl<'a> State<'a> { )); } 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.print_struct(&**struct_def, generics, item.ident, item.span)); } @@ -968,13 +965,6 @@ impl<'a> State<'a> { span: codemap::Span) -> IoResult<()> { try!(self.print_ident(ident)); 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 !struct_def.fields.is_empty() { try!(self.popen()); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 5c7b144f4ab..c98c3bffcb6 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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, struct_definition: &'v StructDef) { - match struct_definition.super_struct { - Some(ref t) => visitor.visit_ty(&**t), - None => {}, - } for field in struct_definition.fields.iter() { visitor.visit_struct_field(field) } diff --git a/src/test/compile-fail/virtual-structs.rs b/src/test/compile-fail/virtual-structs.rs new file mode 100644 index 00000000000..69125bab2ce --- /dev/null +++ b/src/test/compile-fail/virtual-structs.rs @@ -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 or the MIT license +// , 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() {}