diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2015-10-08 23:45:46 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2015-10-13 15:19:25 +0300 |
| commit | 40aa09e4c9f4c3f0fa2b088895c8f5125325eaa4 (patch) | |
| tree | 0ea29987683fbd21b30e2bc23769517a7984a116 /src/libsyntax | |
| parent | 30af54dede8b9f03a83dd5ad588bb430a5a76270 (diff) | |
| download | rust-40aa09e4c9f4c3f0fa2b088895c8f5125325eaa4.tar.gz rust-40aa09e4c9f4c3f0fa2b088895c8f5125325eaa4.zip | |
Merge struct fields and struct kind
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 36 | ||||
| -rw-r--r-- | src/libsyntax/config.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/mod.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/primitive.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 37 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 27 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
10 files changed, 104 insertions, 59 deletions
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::fmt; 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 @@ impl StructFieldKind { } } -#[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<StructField>), + Tuple(Vec<StructField>), Unit, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct VariantData { - /// Fields, not including ctor - pub fields: Vec<StructField>, + 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<option::IntoIter<&'a Vec<StructField>>, + slice::Iter<'a, StructField>, + fn(&Vec<StructField>) -> slice::Iter<StructField>>; + +impl VariantData { + pub fn fields(&self) -> FieldIter { + fn vec_iter<T>(v: &Vec<T>) -> slice::Iter<T> { 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<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_ fn fold_struct<F>(cx: &mut Context<F>, def: P<ast::VariantData>) -> P<ast::VariantData> 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 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }} }).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 @@ impl<'a> TraitDef<'a> { struct_def: &'a VariantData, type_ident: Ident, generics: &Generics) -> P<ast::Item> { - let field_tys: Vec<P<ast::Ty>> = struct_def.fields.iter() + let field_tys: Vec<P<ast::Ty>> = struct_def.fields() .map(|field| field.node.ty.clone()) .collect(); @@ -700,7 +700,7 @@ impl<'a> TraitDef<'a> { 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 @@ impl<'a> TraitDef<'a> { 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 @@ impl<'a> TraitDef<'a> { -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'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 @@ impl<'a> TraitDef<'a> { 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 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { 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<T: Folder>( } pub fn noop_fold_struct_def<T: Folder>(struct_def: P<VariantData>, fld: &mut T) -> P<VariantData> { - 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::{PatRegion, PatStruct, PatTup, PatVec, PatWild, PatWildMulti}; 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 @@ impl<'a> Parser<'a> { // 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<T> where T: Copy;` style decl. - (Vec::new(), VariantKind::Unit) + VariantData_::Unit } else { // If we see: `struct Foo<T> where T: Copy { ... }` - (try!(self.parse_record_struct_body()), VariantKind::Struct) + VariantData_::Struct(try!(self.parse_record_struct_body())) } // No `where` so: `struct Foo<T>;` } 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 @@ impl<'a> Parser<'a> { Ok((class_name, ItemStruct(P(ast::VariantData { - fields: fields, + data_: data_, id: ast::DUMMY_NODE_ID, - kind: kind, }), generics), None)) } @@ -5111,9 +5108,8 @@ impl<'a> Parser<'a> { try!(self.bump()); Ok(P(VariantData { - fields: fields, + data_: VariantData_::Struct(fields), id: ast::DUMMY_NODE_ID, - kind: VariantKind::Struct, })) } @@ -5150,19 +5146,16 @@ impl<'a> Parser<'a> { 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 @@ pub trait PrintState<'a> { 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<Item=&'it T>, + { + 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<comments::Literal> { let mut cur_lit = self.cur_cmnt_and_lit().cur_lit; @@ -1392,11 +1404,11 @@ impl<'a> State<'a> { 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 @@ impl<'a> State<'a> { 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 @@ mod tests { 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, |
