From 40aa09e4c9f4c3f0fa2b088895c8f5125325eaa4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 8 Oct 2015 23:45:46 +0300 Subject: [PATCH] Merge struct fields and struct kind --- src/librustc/front/map/collector.rs | 6 ++-- src/librustc/front/map/mod.rs | 7 ++-- src/librustc/metadata/encoder.rs | 6 ++-- src/librustc/middle/astencode.rs | 2 +- src/librustc/middle/dead.rs | 4 +-- src/librustc/middle/stability.rs | 2 +- src/librustc_front/fold.rs | 13 ++++++-- src/librustc_front/hir.rs | 36 ++++++++++++++++---- src/librustc_front/lowering.rs | 13 +++++--- src/librustc_front/print/pprust.rs | 10 +++--- src/librustc_front/visit.rs | 2 +- src/librustc_lint/bad_style.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_privacy/lib.rs | 10 +++--- src/librustc_resolve/build_reduced_graph.rs | 24 ++++++------- src/librustc_trans/save/dump_csv.rs | 4 +-- src/librustc_trans/trans/base.rs | 17 +++++----- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/inline.rs | 13 ++++---- src/librustc_trans/trans/monomorphize.rs | 2 +- src/librustc_typeck/check/wf.rs | 3 +- src/librustc_typeck/check/wfcheck.rs | 3 +- src/librustc_typeck/collect.rs | 10 +++--- src/librustdoc/clean/mod.rs | 8 ++--- src/librustdoc/doctree.rs | 4 +-- src/librustdoc/visit_ast.rs | 2 +- src/libsyntax/ast.rs | 36 ++++++++++++++++---- src/libsyntax/config.rs | 19 ++++++++--- src/libsyntax/ext/build.rs | 11 +++--- src/libsyntax/ext/deriving/generic/mod.rs | 10 +++--- src/libsyntax/ext/deriving/primitive.rs | 2 +- src/libsyntax/feature_gate.rs | 6 ++-- src/libsyntax/fold.rs | 13 ++++++-- src/libsyntax/parse/parser.rs | 37 +++++++++------------ src/libsyntax/print/pprust.rs | 27 ++++++++++----- src/libsyntax/visit.rs | 2 +- 36 files changed, 222 insertions(+), 148 deletions(-) diff --git a/src/librustc/front/map/collector.rs b/src/librustc/front/map/collector.rs index a3542ff9b10..aa5d482b89a 100644 --- a/src/librustc/front/map/collector.rs +++ b/src/librustc/front/map/collector.rs @@ -138,7 +138,7 @@ fn visit_item(&mut self, i: &'ast Item) { NodeVariant(&**v), DefPathData::EnumVariant(v.node.name)); - for field in &v.node.data.fields { + for field in v.node.data.fields() { self.create_def_with_parent( Some(variant_def_index), field.node.id, @@ -150,13 +150,13 @@ fn visit_item(&mut self, i: &'ast Item) { } ItemStruct(ref struct_def, _) => { // If this is a tuple-like struct, register the constructor. - if struct_def.kind != VariantKind::Struct { + if !struct_def.is_struct() { self.insert_def(struct_def.id, NodeStructCtor(&**struct_def), DefPathData::StructCtor); } - for field in &struct_def.fields { + for field in struct_def.fields() { self.create_def(field.node.id, DefPathData::Field(field.node.kind)); } } diff --git a/src/librustc/front/map/mod.rs b/src/librustc/front/map/mod.rs index 1e31bfe9aca..028e1ad5ce9 100644 --- a/src/librustc/front/map/mod.rs +++ b/src/librustc/front/map/mod.rs @@ -480,9 +480,10 @@ pub fn expect_struct(&self, id: NodeId) -> &'ast VariantData { } } Some(NodeVariant(variant)) => { - match variant.node.data.kind { - VariantKind::Struct => &variant.node.data, - _ => panic!("struct ID bound to enum variant that isn't struct-like"), + if variant.node.data.is_struct() { + &variant.node.data + } else { + panic!("struct ID bound to enum variant that isn't struct-like") } } _ => panic!(format!("expected struct, found {}", self.node_to_string(id))), diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 2bee3f296c9..81305099705 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -381,7 +381,7 @@ fn each_auxiliary_node_id(item: &hir::Item, callback: F) -> bool where match item.node { hir::ItemStruct(ref struct_def, _) => { // If this is a newtype struct, return the constructor. - if struct_def.kind == hir::VariantKind::Tuple { + if struct_def.is_tuple() { continue_ = callback(struct_def.id); } } @@ -1068,7 +1068,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, // Encode inherent implementations for this structure. encode_inherent_implementations(ecx, rbml_w, def_id); - if struct_def.kind != hir::VariantKind::Struct { + if !struct_def.is_struct() { let ctor_did = ecx.tcx.map.local_def_id(struct_def.id); rbml_w.wr_tagged_u64(tag_items_data_item_struct_ctor, def_to_u64(ctor_did)); @@ -1081,7 +1081,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, } // If this is a tuple-like struct, encode the type of the constructor. - if struct_def.kind != hir::VariantKind::Struct { + if !struct_def.is_struct() { encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def.id, index, item.id); } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 9bf70cce602..ca05de81e77 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1320,7 +1320,7 @@ fn copy_item_type(dcx: &DecodeContext, } } hir::ItemStruct(ref def, _) => { - if def.kind != hir::VariantKind::Struct { + if !def.is_struct() { let ctor_did = dcx.tcx.lookup_adt_def(orig_did) .struct_variant().did; debug!("astencode: copying ctor {:?} => {:?}", ctor_did, diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index d0d6cf39af7..9d15b53a6d8 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -219,7 +219,7 @@ fn visit_variant_data(&mut self, def: &hir::VariantData, _: ast::Name, _: &hir::Generics, _: ast::NodeId, _: codemap::Span) { let has_extern_repr = self.struct_has_extern_repr; let inherited_pub_visibility = self.inherited_pub_visibility; - let live_fields = def.fields.iter().filter(|f| { + let live_fields = def.fields().filter(|f| { has_extern_repr || inherited_pub_visibility || match f.node.kind { hir::NamedField(_, hir::Public) => true, _ => false @@ -426,7 +426,7 @@ fn find_live(tcx: &ty::ctxt, fn get_struct_ctor_id(item: &hir::Item) -> Option { match item.node { - hir::ItemStruct(ref struct_def, _) if struct_def.kind != hir::VariantKind::Struct => { + hir::ItemStruct(ref struct_def, _) if !struct_def.is_struct() => { Some(struct_def.id) } _ => None diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index df5582e9414..23bb4a1fe39 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -185,7 +185,7 @@ fn visit_item(&mut self, i: &Item) { |v| visit::walk_item(v, i), required); if let hir::ItemStruct(ref sd, _) = i.node { - if sd.kind != hir::VariantKind::Struct { + if !sd.is_struct() { self.annotate(sd.id, true, &i.attrs, i.span, |_| {}, true) } } diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index ecea50f8495..fd69d2007ff 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -694,11 +694,18 @@ pub fn noop_fold_where_predicate(pred: WherePredicate, fld: &mut T) - } pub fn noop_fold_struct_def(struct_def: P, fld: &mut T) -> P { - struct_def.map(|VariantData { fields, id, kind }| { + struct_def.map(|VariantData { data_, id }| { VariantData { - fields: fields.move_map(|f| fld.fold_struct_field(f)), + data_: match data_ { + VariantData_::Struct(fields) => { + VariantData_::Struct(fields.move_map(|f| fld.fold_struct_field(f))) + } + VariantData_::Tuple(fields) => { + VariantData_::Tuple(fields.move_map(|f| fld.fold_struct_field(f))) + } + VariantData_::Unit => VariantData_::Unit + }, id: fld.new_id(id), - kind: kind, } }) } diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index 92a52c38176..b5170b7496b 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -49,6 +49,7 @@ use util; use std::fmt; +use std::{iter, option, slice}; use serialize::{Encodable, Encoder, Decoder}; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] @@ -1160,21 +1161,42 @@ pub fn is_unnamed(&self) -> bool { } } -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum VariantKind { - Struct, - Tuple, +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum VariantData_ { + Struct(Vec), + Tuple(Vec), Unit, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct VariantData { - /// Fields, not including ctor - pub fields: Vec, + pub data_: VariantData_, /// ID of the constructor. This is only used for tuple- or enum-like /// structs. pub id: NodeId, - pub kind: VariantKind, +} + +pub type FieldIter<'a> = iter::FlatMap>, + slice::Iter<'a, StructField>, + fn(&Vec) -> slice::Iter>; + +impl VariantData { + pub fn fields(&self) -> FieldIter { + fn vec_iter(v: &Vec) -> slice::Iter { v.iter() } + match self.data_ { + VariantData_::Struct(ref fields) | VariantData_::Tuple(ref fields) => Some(fields), + _ => None, + }.into_iter().flat_map(vec_iter) + } + pub fn is_struct(&self) -> bool { + if let VariantData_::Struct(..) = self.data_ { true } else { false } + } + pub fn is_tuple(&self) -> bool { + if let VariantData_::Tuple(..) = self.data_ { true } else { false } + } + pub fn is_unit(&self) -> bool { + if let VariantData_::Unit = self.data_ { true } else { false } + } } /* diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index ecbfbd1362e..cd32ad15744 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -500,12 +500,15 @@ pub fn lower_where_predicate(_lctx: &LoweringContext, pub fn lower_struct_def(sd: &VariantData) -> P { P(hir::VariantData { - fields: sd.fields.iter().map(|f| lower_struct_field(_lctx, f)).collect(), id: sd.id, - kind: match sd.kind { - VariantKind::Struct => hir::VariantKind::Struct, - VariantKind::Tuple => hir::VariantKind::Tuple, - VariantKind::Unit => hir::VariantKind::Unit, + data_: match sd.data_ { + VariantData_::Struct(ref fields) => { + hir::VariantData_::Struct(fields.iter().map(|f| lower_struct_field(_lctx, f)).collect()) + } + VariantData_::Tuple(ref fields) => { + hir::VariantData_::Tuple(fields.iter().map(|f| lower_struct_field(_lctx, f)).collect()) + } + VariantData_::Unit => hir::VariantData_::Unit } }) } diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index 948134c8025..5e78aa5fbc1 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -896,11 +896,11 @@ pub fn print_struct(&mut self, -> io::Result<()> { try!(self.print_name(name)); try!(self.print_generics(generics)); - if struct_def.kind != hir::VariantKind::Struct { - if struct_def.kind == hir::VariantKind::Tuple { + if !struct_def.is_struct() { + if struct_def.is_tuple() { try!(self.popen()); - try!(self.commasep(Inconsistent, - &struct_def.fields, + try!(self.commasep_iter(Inconsistent, + struct_def.fields(), |s, field| { match field.node.kind { hir::NamedField(..) => panic!("unexpected named field"), @@ -925,7 +925,7 @@ pub fn print_struct(&mut self, try!(self.bopen()); try!(self.hardbreak_if_not_bol()); - for field in &struct_def.fields { + for field in struct_def.fields() { match field.node.kind { hir::UnnamedField(..) => panic!("unexpected unnamed field"), hir::NamedField(name, visibility) => { diff --git a/src/librustc_front/visit.rs b/src/librustc_front/visit.rs index 8472bef3cd1..00c2c3a3ddd 100644 --- a/src/librustc_front/visit.rs +++ b/src/librustc_front/visit.rs @@ -629,7 +629,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt } pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) { - walk_list!(visitor, visit_struct_field, &struct_definition.fields); + walk_list!(visitor, visit_struct_field, struct_definition.fields()); } pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) { diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 6b6b90b1ba6..693de1740bf 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -282,7 +282,7 @@ fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { fn check_struct_def(&mut self, cx: &LateContext, s: &hir::VariantData, _: ast::Name, _: &hir::Generics, _: ast::NodeId) { - for sf in &s.fields { + for sf in s.fields() { if let hir::StructField_ { kind: hir::NamedField(name, _), .. } = sf.node { self.check_snake_case(cx, "structure field", &name.as_str(), Some(sf.span)); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index df15dbe4d6c..ea8ea4ebf0d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -123,7 +123,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { // If it's a struct, we also have to check the fields' types match it.node { hir::ItemStruct(ref struct_def, _) => { - for struct_field in &struct_def.fields { + for struct_field in struct_def.fields() { self.check_heap_type(cx, struct_field.span, cx.tcx.node_id_to_type(struct_field.node.id)); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index e1e51ae666b..b139b275785 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -132,13 +132,13 @@ fn visit_variant_data(&mut self, s: &hir::VariantData, _: ast::Name, _: &'v hir::Generics, item_id: ast::NodeId, _: Span) { // Struct constructors are parented to their struct definitions because // they essentially are the struct definitions. - if s.kind != hir::VariantKind::Struct { + if !s.is_struct() { self.parents.insert(s.id, item_id); } // While we have the id of the struct definition, go ahead and parent // all the fields. - for field in &s.fields { + for field in s.fields() { self.parents.insert(field.node.id, self.curparent); } visit::walk_struct_def(self, s) @@ -319,11 +319,11 @@ fn visit_item(&mut self, item: &hir::Item) { // Struct constructors are public if the struct is all public. hir::ItemStruct(ref def, _) if public_first => { - if def.kind != hir::VariantKind::Struct { + if !def.is_struct() { self.exported_items.insert(def.id); } // fields can be public or private, so lets check - for field in &def.fields { + for field in def.fields() { let vis = match field.node.kind { hir::NamedField(_, vis) | hir::UnnamedField(vis) => vis }; @@ -1089,7 +1089,7 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: hir::Visibility) { } } let check_struct = |def: &hir::VariantData| { - for f in &def.fields { + for f in def.fields() { match f.node.kind { hir::NamedField(_, p) => check_inherited(tcx, f.span, p), hir::UnnamedField(..) => {} diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 4484cfe9590..43943fbb129 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -492,9 +492,10 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc) -> // These items live in both the type and value namespaces. ItemStruct(ref struct_def, _) => { // Adding to both Type and Value namespaces or just Type? - let (forbid, ctor_id) = match struct_def.kind { - hir::VariantKind::Struct => (ForbidDuplicateTypesAndModules, None), - _ => (ForbidDuplicateTypesAndValues, Some(struct_def.id)), + let (forbid, ctor_id) = if struct_def.is_struct() { + (ForbidDuplicateTypesAndModules, None) + } else { + (ForbidDuplicateTypesAndValues, Some(struct_def.id)) }; let name_bindings = self.add_child(name, parent, forbid, sp); @@ -513,7 +514,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc) -> } // Record the def ID and fields of this struct. - let named_fields = struct_def.fields.iter().filter_map(|f| { + let named_fields = struct_def.fields().filter_map(|f| { match f.node.kind { NamedField(name, _) => Some(name), UnnamedField(_) => None @@ -587,14 +588,13 @@ fn build_reduced_graph_for_variant(&mut self, item_id: DefId, parent: &Rc) { let name = variant.node.name; - let is_exported = match variant.node.data.kind { - hir::VariantKind::Struct => { - // Not adding fields for variants as they are not accessed with a self receiver - let variant_def_id = self.ast_map.local_def_id(variant.node.data.id); - self.structs.insert(variant_def_id, Vec::new()); - true - } - _ => false, + let is_exported = if variant.node.data.is_struct() { + // Not adding fields for variants as they are not accessed with a self receiver + let variant_def_id = self.ast_map.local_def_id(variant.node.data.id); + self.structs.insert(variant_def_id, Vec::new()); + true + } else { + false }; let child = self.add_child(name, parent, diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 5235bd49a28..d31b8b6f0e4 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -473,7 +473,7 @@ fn process_struct(&mut self, &val); // fields - for field in &def.fields { + for field in def.fields() { self.process_struct_field_def(field, item.id); self.visit_ty(&field.node.ty); } @@ -510,7 +510,7 @@ fn process_enum(&mut self, &val, enum_data.id); - for field in &variant.node.data.fields { + for field in variant.node.data.fields() { self.process_struct_field_def(field, variant.node.data.id); self.visit_ty(&*field.node.ty); } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index d7ace6e2541..c692f8a1836 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2428,12 +2428,12 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { hir_map::NodeVariant(ref v) => { let llfn; - let fields = if v.node.data.kind == hir::VariantKind::Struct { + let fields = if v.node.data.is_struct() { ccx.sess().bug("struct variant kind unexpected in get_item_val") } else { - &v.node.data.fields + v.node.data.fields() }; - assert!(!fields.is_empty()); + assert!(fields.count() != 0); let ty = ccx.tcx().node_id_to_type(id); let parent = ccx.tcx().map.get_parent(id); let enm = ccx.tcx().map.expect_item(parent); @@ -2454,12 +2454,11 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { hir_map::NodeStructCtor(struct_def) => { // Only register the constructor if this is a tuple-like struct. - let ctor_id = match struct_def.kind { - hir::VariantKind::Struct => { - ccx.sess().bug("attempt to register a constructor of \ - a non-tuple-like struct") - } - _ => struct_def.id, + let ctor_id = if struct_def.is_struct() { + ccx.sess().bug("attempt to register a constructor of \ + a non-tuple-like struct") + } else { + struct_def.id }; let parent = ccx.tcx().map.get_parent(id); let struct_item = ccx.tcx().map.expect_item(parent); diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 455eb709291..c8525e33e26 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -418,7 +418,7 @@ fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool { match map_node { hir_map::NodeVariant(v) => { - v.node.data.kind == hir::VariantKind::Tuple + v.node.data.is_tuple() } hir_map::NodeStructCtor(_) => true, _ => false diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs index 2f747606e59..923214a5362 100644 --- a/src/librustc_trans/trans/inline.rs +++ b/src/librustc_trans/trans/inline.rs @@ -115,13 +115,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) } } hir::ItemStruct(ref struct_def, _) => { - match struct_def.kind { - hir::VariantKind::Struct => ccx.sess().bug("instantiate_inline: called on a \ - non-tuple struct"), - _ => { - ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id)); - my_id = struct_def.id; - } + if struct_def.is_struct() { + ccx.sess().bug("instantiate_inline: called on a \ + non-tuple struct") + } else { + ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id)); + my_id = struct_def.id; } } _ => ccx.sess().bug("instantiate_inline: item has a \ diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 80d683a8f35..440b667e801 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -246,7 +246,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, hir_map::NodeStructCtor(struct_def) => { let d = mk_lldecl(abi::Rust); attributes::inline(d, attributes::InlineAttr::Hint); - if struct_def.kind == hir::VariantKind::Struct { + if struct_def.is_struct() { panic!("ast-mapped struct didn't have a ctor id") } base::trans_tuple_struct(ccx, diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index ebf54f62b52..14947d9955e 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -627,8 +627,7 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, struct_def: &hir::VariantData) -> AdtVariant<'tcx> { let fields = - struct_def.fields - .iter() + struct_def.fields() .map(|field| { let field_ty = fcx.tcx().node_id_to_type(field.node.id); let field_ty = fcx.instantiate_type_scheme(field.span, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 0d2d37714c0..4cfc34dbb23 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -524,8 +524,7 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, struct_def: &hir::VariantData) -> AdtVariant<'tcx> { let fields = - struct_def.fields - .iter() + struct_def.fields() .map(|field| { let field_ty = fcx.tcx().node_id_to_type(field.node.id); let field_ty = fcx.instantiate_type_scheme(field.span, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c38befd7444..44e06688774 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1010,11 +1010,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let it_def_id = ccx.tcx.map.local_def_id(it.id); let variant = tcx.lookup_adt_def_master(it_def_id).struct_variant(); - for (f, ty_f) in struct_def.fields.iter().zip(variant.fields.iter()) { + for (f, ty_f) in struct_def.fields().zip(variant.fields.iter()) { convert_field(ccx, &scheme.generics, &predicates, f, ty_f) } - if struct_def.kind != hir::VariantKind::Struct { + if !struct_def.is_struct() { convert_variant_ctor(tcx, struct_def.id, variant, scheme, predicates); } }, @@ -1067,7 +1067,7 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, variants: &[P]) { // fill the field types for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) { - for (f, ty_f) in variant.node.data.fields.iter().zip(ty_variant.fields.iter()) { + for (f, ty_f) in variant.node.data.fields().zip(ty_variant.fields.iter()) { convert_field(ccx, &scheme.generics, &predicates, f, ty_f) } @@ -1089,7 +1089,7 @@ fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>, disr_val: ty::Disr, def: &hir::VariantData) -> ty::VariantDefData<'tcx, 'tcx> { let mut seen_fields: FnvHashMap = FnvHashMap(); - let fields = def.fields.iter().map(|f| { + let fields = def.fields().map(|f| { let fid = tcx.map.local_def_id(f.node.id); match f.node.kind { hir::NamedField(name, vis) => { @@ -1125,7 +1125,7 @@ fn convert_struct_def<'tcx>(tcx: &ty::ctxt<'tcx>, { let did = tcx.map.local_def_id(it.id); - let ctor_id = if def.kind != hir::VariantKind::Struct { + let ctor_id = if !def.is_struct() { tcx.map.local_def_id(def.id) } else { did diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f935210ef28..e5090c167df 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1809,7 +1809,7 @@ impl Clean for ::rustc_front::hir::VariantData { fn clean(&self, cx: &DocContext) -> VariantStruct { VariantStruct { struct_type: doctree::struct_type_from_def(self), - fields: self.fields.clean(cx), + fields: self.fields().map(|x| x.clean(cx)).collect(), fields_stripped: false, } } @@ -1918,12 +1918,12 @@ pub enum VariantKind { } fn struct_def_to_variant_kind(struct_def: &hir::VariantData, cx: &DocContext) -> VariantKind { - if struct_def.kind == hir::VariantKind::Struct { + if struct_def.is_struct() { StructVariant(struct_def.clean(cx)) - } else if struct_def.kind == hir::VariantKind::Unit { + } else if struct_def.is_unit() { CLikeVariant } else { - TupleVariant(struct_def.fields.iter().map(|x| x.node.ty.clean(cx)).collect()) + TupleVariant(struct_def.fields().map(|x| x.node.ty.clean(cx)).collect()) } } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 112c6aebfc5..47cc007f605 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -234,9 +234,9 @@ pub struct Import { } pub fn struct_type_from_def(sd: &hir::VariantData) -> StructType { - if sd.kind != hir::VariantKind::Struct { + if !sd.is_struct() { // We are in a tuple-struct - match sd.fields.len() { + match sd.fields().count() { 0 => Unit, 1 => Newtype, _ => Tuple diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e84d7f549a9..19edccc4fe2 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -97,7 +97,7 @@ pub fn visit_variant_data(&mut self, item: &hir::Item, stab: self.stability(item.id), attrs: item.attrs.clone(), generics: generics.clone(), - fields: sd.fields.clone(), + fields: sd.fields().cloned().collect(), whence: item.span } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index af623549767..34181b2e097 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -65,6 +65,7 @@ use std::rc::Rc; use std::borrow::Cow; use std::hash::{Hash, Hasher}; +use std::{iter, option, slice}; use serialize::{Encodable, Decodable, Encoder, Decoder}; /// A name is a part of an identifier, representing a string or gensym. It's @@ -1740,21 +1741,42 @@ pub fn is_unnamed(&self) -> bool { } } -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum VariantKind { - Struct, - Tuple, +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum VariantData_ { + Struct(Vec), + Tuple(Vec), Unit, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct VariantData { - /// Fields, not including ctor - pub fields: Vec, + pub data_: VariantData_, /// ID of the constructor. This is only used for tuple- or enum-like /// structs. pub id: NodeId, - pub kind: VariantKind, +} + +pub type FieldIter<'a> = iter::FlatMap>, + slice::Iter<'a, StructField>, + fn(&Vec) -> slice::Iter>; + +impl VariantData { + pub fn fields(&self) -> FieldIter { + fn vec_iter(v: &Vec) -> slice::Iter { v.iter() } + match self.data_ { + VariantData_::Struct(ref fields) | VariantData_::Tuple(ref fields) => Some(fields), + _ => None, + }.into_iter().flat_map(vec_iter) + } + pub fn is_struct(&self) -> bool { + if let VariantData_::Struct(..) = self.data_ { true } else { false } + } + pub fn is_tuple(&self) -> bool { + if let VariantData_::Tuple(..) = self.data_ { true } else { false } + } + pub fn is_unit(&self) -> bool { + if let VariantData_::Unit = self.data_ { true } else { false } + } } /* diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 02a9d0b5c38..739bb36d985 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -167,13 +167,22 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ fn fold_struct(cx: &mut Context, def: P) -> P where F: FnMut(&[ast::Attribute]) -> bool { - def.map(|ast::VariantData { fields, id, kind }| { + def.map(|ast::VariantData { data_, id }| { ast::VariantData { - fields: fields.into_iter().filter(|m| { - (cx.in_cfg)(&m.node.attrs) - }).collect(), + data_: match data_ { + ast::VariantData_::Struct(fields) => { + ast::VariantData_::Struct(fields.into_iter().filter(|m| { + (cx.in_cfg)(&m.node.attrs) + }).collect()) + } + ast::VariantData_::Tuple(fields) => { + ast::VariantData_::Tuple(fields.into_iter().filter(|m| { + (cx.in_cfg)(&m.node.attrs) + }).collect()) + } + ast::VariantData_::Unit => ast::VariantData_::Unit + }, id: id, - kind: kind, } }) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 105a7036c5f..25657b9c6cc 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1002,15 +1002,18 @@ fn variant(&self, span: Span, name: Ident, tys: Vec> ) -> ast::Varian }} }).collect(); - let kind = if fields.is_empty() { ast::VariantKind::Unit } else { ast::VariantKind::Tuple }; + let data_ = if fields.is_empty() { + ast::VariantData_::Unit + } else { + ast::VariantData_::Tuple(fields) + }; respan(span, ast::Variant_ { name: name, attrs: Vec::new(), - data: P(ast::VariantData { fields: fields, - id: ast::DUMMY_NODE_ID, - kind: kind }), + data: P(ast::VariantData { data_: data_, + id: ast::DUMMY_NODE_ID}), disr_expr: None, }) } diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index b375dee4e2c..2a5c4993112 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -652,7 +652,7 @@ fn expand_struct_def(&self, struct_def: &'a VariantData, type_ident: Ident, generics: &Generics) -> P { - let field_tys: Vec> = struct_def.fields.iter() + let field_tys: Vec> = struct_def.fields() .map(|field| field.node.ty.clone()) .collect(); @@ -700,7 +700,7 @@ fn expand_enum_def(&self, let mut field_tys = Vec::new(); for variant in &enum_def.variants { - field_tys.extend(variant.node.data.fields.iter() + field_tys.extend(variant.node.data.fields() .map(|field| field.node.ty.clone())); } @@ -1444,7 +1444,7 @@ fn summarise_struct(&self, struct_def: &VariantData) -> StaticFields { let mut named_idents = Vec::new(); let mut just_spans = Vec::new(); - for field in struct_def.fields.iter(){ + for field in struct_def.fields(){ let sp = self.set_expn_info(cx, field.span); match field.node.kind { ast::NamedField(ident, _) => named_idents.push((ident, sp)), @@ -1483,7 +1483,7 @@ fn create_struct_pattern(&self, -> (P, Vec<(Span, Option, P, &'a [ast::Attribute])>) { - if struct_def.fields.is_empty() { + if struct_def.fields().count() == 0 { return (cx.pat_enum(self.span, struct_path, vec![]), vec![]); } @@ -1491,7 +1491,7 @@ fn create_struct_pattern(&self, let mut ident_expr = Vec::new(); let mut struct_type = Unknown; - for (i, struct_field) in struct_def.fields.iter().enumerate() { + for (i, struct_field) in struct_def.fields().enumerate() { let sp = self.set_expn_info(cx, struct_field.span); let opt_id = match struct_field.node.kind { ast::NamedField(ident, _) if (struct_type == Unknown || diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 3a079717b8b..07b58778358 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -95,7 +95,7 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure for variant in &enum_def.variants { let def = &variant.node.data; - if def.kind != ast::VariantKind::Unit { + if !def.is_unit() { cx.span_err(trait_span, "`FromPrimitive` cannot be derived \ for enums with non-unit variants"); return cx.expr_fail(trait_span, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a6922c24693..be6ad931111 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -859,11 +859,11 @@ fn visit_item(&mut self, i: &ast::Item) { fn visit_variant_data(&mut self, s: &'v ast::VariantData, _: ast::Ident, _: &'v ast::Generics, _: ast::NodeId, span: Span) { - if s.fields.is_empty() { - if s.kind == ast::VariantKind::Struct { + if s.fields().count() == 0 { + if s.is_struct() { self.gate_feature("braced_empty_structs", span, "empty structs and enum variants with braces are unstable"); - } else if s.kind == ast::VariantKind::Tuple { + } else if s.is_tuple() { self.context.span_handler.span_err(span, "empty tuple structs and enum variants \ are not allowed, use unit structs and \ enum variants instead"); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index d7b7fc242b4..329ffb286eb 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -815,10 +815,17 @@ pub fn noop_fold_where_predicate( } pub fn noop_fold_struct_def(struct_def: P, fld: &mut T) -> P { - struct_def.map(|VariantData { fields, id, kind }| VariantData { - fields: fields.move_map(|f| fld.fold_struct_field(f)), + struct_def.map(|VariantData { data_, id }| VariantData { + data_: match data_ { + ast::VariantData_::Struct(fields) => { + ast::VariantData_::Struct(fields.move_map(|f| fld.fold_struct_field(f))) + } + ast::VariantData_::Tuple(fields) => { + ast::VariantData_::Tuple(fields.move_map(|f| fld.fold_struct_field(f))) + } + ast::VariantData_::Unit => ast::VariantData_::Unit + }, id: fld.new_id(id), - kind: kind, }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f944c93073a..2431c8cbe88 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -45,7 +45,7 @@ use ast::PatWildSingle; use ast::{PolyTraitRef, QSelf}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; -use ast::{StmtExpr, StmtSemi, StmtMac, VariantData, StructField, VariantKind}; +use ast::{StmtExpr, StmtSemi, StmtMac, VariantData, StructField, VariantData_}; use ast::{BiSub, StrStyle}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; @@ -4640,26 +4640,24 @@ fn parse_item_struct(&mut self) -> PResult { // Otherwise if we look ahead and see a paren we parse a tuple-style // struct. - let (fields, kind) = if self.token.is_keyword(keywords::Where) { + let data_ = if self.token.is_keyword(keywords::Where) { generics.where_clause = try!(self.parse_where_clause()); if try!(self.eat(&token::Semi)) { // If we see a: `struct Foo where T: Copy;` style decl. - (Vec::new(), VariantKind::Unit) + VariantData_::Unit } else { // If we see: `struct Foo where T: Copy { ... }` - (try!(self.parse_record_struct_body()), VariantKind::Struct) + VariantData_::Struct(try!(self.parse_record_struct_body())) } // No `where` so: `struct Foo;` } else if try!(self.eat(&token::Semi) ){ - (Vec::new(), VariantKind::Unit) + VariantData_::Unit // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { - let fields = try!(self.parse_record_struct_body()); - (fields, VariantKind::Struct) + VariantData_::Struct(try!(self.parse_record_struct_body())) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { - let fields = try!(self.parse_tuple_struct_body(&mut generics)); - (fields, VariantKind::Tuple) + VariantData_::Tuple(try!(self.parse_tuple_struct_body(&mut generics))) } else { let token_str = self.this_token_to_string(); return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \ @@ -4668,9 +4666,8 @@ fn parse_item_struct(&mut self) -> PResult { Ok((class_name, ItemStruct(P(ast::VariantData { - fields: fields, + data_: data_, id: ast::DUMMY_NODE_ID, - kind: kind, }), generics), None)) } @@ -5111,9 +5108,8 @@ fn parse_struct_def(&mut self) -> PResult> { try!(self.bump()); Ok(P(VariantData { - fields: fields, + data_: VariantData_::Struct(fields), id: ast::DUMMY_NODE_ID, - kind: VariantKind::Struct, })) } @@ -5150,19 +5146,16 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult { id: ast::DUMMY_NODE_ID, }}); } - struct_def = P(VariantData { fields: fields, - id: ast::DUMMY_NODE_ID, - kind: ast::VariantKind::Tuple }); + struct_def = P(VariantData { data_: ast::VariantData_::Tuple(fields), + id: ast::DUMMY_NODE_ID}); } else if try!(self.eat(&token::Eq) ){ disr_expr = Some(try!(self.parse_expr_nopanic())); any_disr = disr_expr.as_ref().map(|expr| expr.span); - struct_def = P(VariantData { fields: Vec::new(), - id: ast::DUMMY_NODE_ID, - kind: ast::VariantKind::Unit }); + struct_def = P(VariantData { data_: ast::VariantData_::Unit, + id: ast::DUMMY_NODE_ID}); } else { - struct_def = P(VariantData { fields: Vec::new(), - id: ast::DUMMY_NODE_ID, - kind: ast::VariantKind::Unit }); + struct_def = P(VariantData { data_: ast::VariantData_::Unit, + id: ast::DUMMY_NODE_ID}); } let vr = ast::Variant_ { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0f6041d2cd0..161f6243f85 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -520,6 +520,18 @@ fn commasep(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> self.end() } + fn commasep_iter<'it, T: 'it, F, I>(&mut self, b: Breaks, elts: I, mut op: F) -> io::Result<()> + where F: FnMut(&mut Self, &T) -> io::Result<()>, + I: Iterator, + { + try!(self.rbox(0, b)); + let mut first = true; + for elt in elts { + if first { first = false; } else { try!(self.word_space(",")); } + try!(op(self, elt)); + } + self.end() + } fn next_lit(&mut self, pos: BytePos) -> Option { let mut cur_lit = self.cur_cmnt_and_lit().cur_lit; @@ -1392,11 +1404,11 @@ pub fn print_struct(&mut self, print_finalizer: bool) -> io::Result<()> { try!(self.print_ident(ident)); try!(self.print_generics(generics)); - if struct_def.kind != ast::VariantKind::Struct { - if struct_def.kind == ast::VariantKind::Tuple { + if !struct_def.is_struct() { + if struct_def.is_tuple() { try!(self.popen()); - try!(self.commasep( - Inconsistent, &struct_def.fields, + try!(self.commasep_iter( + Inconsistent, struct_def.fields(), |s, field| { match field.node.kind { ast::NamedField(..) => panic!("unexpected named field"), @@ -1422,7 +1434,7 @@ pub fn print_struct(&mut self, try!(self.bopen()); try!(self.hardbreak_if_not_bol()); - for field in &struct_def.fields { + for field in struct_def.fields() { match field.node.kind { ast::UnnamedField(..) => panic!("unexpected unnamed field"), ast::NamedField(ident, visibility) => { @@ -3119,9 +3131,8 @@ fn test_variant_to_string() { name: ident, attrs: Vec::new(), // making this up as I go.... ? - data: P(ast::VariantData { fields: Vec::new(), - id: ast::DUMMY_NODE_ID, - kind: ast::VariantKind::Unit }), + data: P(ast::VariantData { data_: ast::VariantData_::Unit, + id: ast::DUMMY_NODE_ID}), disr_expr: None, }); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index fdff0bf72eb..b7d202804c5 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -604,7 +604,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) { - walk_list!(visitor, visit_struct_field, &struct_definition.fields); + walk_list!(visitor, visit_struct_field, struct_definition.fields()); } pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, -- GitLab