From: Vadim Petrochenkov Date: Thu, 1 Oct 2015 15:47:27 +0000 (+0300) Subject: Unify structures and enum variants in AST X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;ds=inline;h=ea47c2b6b349d7f252a6a734ced8204e6ef70546;p=rust.git Unify structures and enum variants in AST --- diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index 5bd188020a3..bd5f7cf3c62 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -267,14 +267,13 @@ pub fn lower_variant(_lctx: &LoweringContext, v: &Variant) -> P { id: v.node.id, name: v.node.name.name, attrs: v.node.attrs.clone(), - kind: match v.node.kind { - TupleVariantKind(ref variant_args) => { - hir::TupleVariantKind(variant_args.iter() - .map(|ref x| lower_variant_arg(_lctx, x)) - .collect()) - } - StructVariantKind(ref struct_def) => { - hir::StructVariantKind(lower_struct_def(_lctx, struct_def)) + kind: { + if v.node.def.ctor_id.is_none() { + hir::StructVariantKind(lower_struct_def(_lctx, &v.node.def)) + } else { + hir::TupleVariantKind(v.node.def.fields.iter().map(|ref field| { + hir::VariantArg { id: field.node.id, ty: lower_ty(_lctx, &field.node.ty) } + }).collect()) } }, disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(_lctx, e)), @@ -567,13 +566,6 @@ fn lower_bounds(_lctx: &LoweringContext, bounds: &TyParamBounds) -> hir::TyParam bounds.iter().map(|bound| lower_ty_param_bound(_lctx, bound)).collect() } -fn lower_variant_arg(_lctx: &LoweringContext, va: &VariantArg) -> hir::VariantArg { - hir::VariantArg { - id: va.id, - ty: lower_ty(_lctx, &va.ty), - } -} - pub fn lower_block(_lctx: &LoweringContext, b: &Block) -> P { P(hir::Block { id: b.id, diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 09825f1f919..983f04643c3 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -504,40 +504,20 @@ fn process_enum(&mut self, qualname.push_str("::"); qualname.push_str(name); let val = self.span.snippet(variant.span); - match variant.node.kind { - ast::TupleVariantKind(ref args) => { - // first ident in span is the variant's name - self.fmt.tuple_variant_str(variant.span, - self.span.span_for_first_ident(variant.span), - variant.node.id, - name, - &qualname, - &enum_data.qualname, - &val, - enum_data.id); - for arg in args { - self.visit_ty(&*arg.ty); - } - } - ast::StructVariantKind(ref struct_def) => { - let ctor_id = match struct_def.ctor_id { - Some(node_id) => node_id, - None => ast::DUMMY_NODE_ID, - }; - self.fmt.struct_variant_str(variant.span, - self.span.span_for_first_ident(variant.span), - variant.node.id, - ctor_id, - &qualname, - &enum_data.qualname, - &val, - enum_data.id); - - for field in &struct_def.fields { - self.process_struct_field_def(field, variant.node.id); - self.visit_ty(&*field.node.ty); - } - } + + let ctor_id = variant.node.def.ctor_id.unwrap_or(ast::DUMMY_NODE_ID); + self.fmt.struct_variant_str(variant.span, + self.span.span_for_first_ident(variant.span), + variant.node.id, + ctor_id, + &qualname, + &enum_data.qualname, + &val, + enum_data.id); + + for field in &variant.node.def.fields { + self.process_struct_field_def(field, variant.node.id); + self.visit_ty(&*field.node.ty); } } self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 34b99ab8cce..57d9837e1aa 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1594,7 +1594,7 @@ pub struct EnumDef { pub struct Variant_ { pub name: Ident, pub attrs: Vec, - pub kind: VariantKind, + pub def: P, pub id: NodeId, /// Explicit discriminant, eg `Foo = 1` pub disr_expr: Option>, diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 2d266be3242..0accf34202e 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -140,19 +140,14 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ if !(cx.in_cfg)(&v.node.attrs) { None } else { - Some(v.map(|Spanned {node: ast::Variant_ {id, name, attrs, kind, + Some(v.map(|Spanned {node: ast::Variant_ {id, name, attrs, def, disr_expr}, span}| { Spanned { node: ast::Variant_ { id: id, name: name, attrs: attrs, - kind: match kind { - ast::TupleVariantKind(..) => kind, - ast::StructVariantKind(def) => { - ast::StructVariantKind(fold_struct(cx, def)) - } - }, + def: fold_struct(cx, def), disr_expr: disr_expr, }, span: span diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index efea85f9162..d448eb63204 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -993,15 +993,20 @@ fn item_fn(&self, } fn variant(&self, span: Span, name: Ident, tys: Vec> ) -> ast::Variant { - let args = tys.into_iter().map(|ty| { - ast::VariantArg { ty: ty, id: ast::DUMMY_NODE_ID } + let fields = tys.into_iter().map(|ty| { + Spanned { span: ty.span, node: ast::StructField_ { + ty: ty, + kind: ast::UnnamedField(ast::Inherited), + attrs: Vec::new(), + id: ast::DUMMY_NODE_ID, + }} }).collect(); respan(span, ast::Variant_ { name: name, attrs: Vec::new(), - kind: ast::TupleVariantKind(args), + def: P(ast::StructDef { fields: fields, ctor_id: Some(ast::DUMMY_NODE_ID) }), 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 9fc2745cf92..f6ea6aef108 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -700,16 +700,8 @@ fn expand_enum_def(&self, let mut field_tys = Vec::new(); for variant in &enum_def.variants { - match variant.node.kind { - ast::VariantKind::TupleVariantKind(ref args) => { - field_tys.extend(args.iter() - .map(|arg| arg.ty.clone())); - } - ast::VariantKind::StructVariantKind(ref args) => { - field_tys.extend(args.fields.iter() - .map(|field| field.node.ty.clone())); - } - } + field_tys.extend(variant.node.def.fields.iter() + .map(|field| field.node.ty.clone())); } let methods = self.methods.iter().map(|method_def| { @@ -1413,14 +1405,7 @@ fn expand_static_enum_method_body(&self, -> P { let summary = enum_def.variants.iter().map(|v| { let ident = v.node.name; - let summary = match v.node.kind { - ast::TupleVariantKind(ref args) => { - Unnamed(args.iter().map(|va| trait_.set_expn_info(cx, va.ty.span)).collect()) - } - ast::StructVariantKind(ref struct_def) => { - trait_.summarise_struct(cx, &**struct_def) - } - }; + let summary = trait_.summarise_struct(cx, &v.node.def); (ident, v.span, summary) }).collect(); self.call_substructure_method(cx, trait_, type_ident, @@ -1560,34 +1545,7 @@ fn create_enum_variant_pattern(&self, -> (P, Vec<(Span, Option, P, &'a [ast::Attribute])>) { let variant_ident = variant.node.name; let variant_path = cx.path(variant.span, vec![enum_ident, variant_ident]); - match variant.node.kind { - ast::TupleVariantKind(ref variant_args) => { - if variant_args.is_empty() { - return (cx.pat_enum(variant.span, variant_path, vec![]), vec![]); - } - - let mut paths = Vec::new(); - let mut ident_expr: Vec<(_, _, _, &'a [ast::Attribute])> = Vec::new(); - for (i, va) in variant_args.iter().enumerate() { - let sp = self.set_expn_info(cx, va.ty.span); - let ident = cx.ident_of(&format!("{}_{}", prefix, i)); - let path1 = codemap::Spanned{span: sp, node: ident}; - paths.push(path1); - let expr_path = cx.expr_path(cx.path_ident(sp, ident)); - let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path))); - ident_expr.push((sp, None, val, &[])); - } - - let subpats = self.create_subpatterns(cx, paths, mutbl); - - (cx.pat_enum(variant.span, variant_path, subpats), - ident_expr) - } - ast::StructVariantKind(ref struct_def) => { - self.create_struct_pattern(cx, variant_path, &**struct_def, - prefix, mutbl) - } - } + self.create_struct_pattern(cx, variant_path, &variant.node.def, prefix, mutbl) } } diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 5d3cc50557c..2fdaa9b7550 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -94,45 +94,35 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure let mut arms = Vec::new(); for variant in &enum_def.variants { - match variant.node.kind { - ast::TupleVariantKind(ref args) => { - if !args.is_empty() { - cx.span_err(trait_span, - "`FromPrimitive` cannot be derived for \ - enum variants with arguments"); - return cx.expr_fail(trait_span, - InternedString::new("")); - } - let span = variant.span; + let def = &variant.node.def; + if def.ctor_id.is_none() || !def.fields.is_empty() { + cx.span_err(trait_span, "`FromPrimitive` cannot be derived \ + for enums with non-unit variants"); + return cx.expr_fail(trait_span, + InternedString::new("")); + } - // expr for `$n == $variant as $name` - let path = cx.path(span, vec![substr.type_ident, variant.node.name]); - let variant = cx.expr_path(path); - let ty = cx.ty_ident(span, cx.ident_of(name)); - let cast = cx.expr_cast(span, variant.clone(), ty); - let guard = cx.expr_binary(span, ast::BiEq, n.clone(), cast); + let span = variant.span; - // expr for `Some($variant)` - let body = cx.expr_some(span, variant); + // expr for `$n == $variant as $name` + let path = cx.path(span, vec![substr.type_ident, variant.node.name]); + let variant = cx.expr_path(path); + let ty = cx.ty_ident(span, cx.ident_of(name)); + let cast = cx.expr_cast(span, variant.clone(), ty); + let guard = cx.expr_binary(span, ast::BiEq, n.clone(), cast); - // arm for `_ if $guard => $body` - let arm = ast::Arm { - attrs: vec!(), - pats: vec!(cx.pat_wild(span)), - guard: Some(guard), - body: body, - }; + // expr for `Some($variant)` + let body = cx.expr_some(span, variant); - arms.push(arm); - } - ast::StructVariantKind(_) => { - cx.span_err(trait_span, - "`FromPrimitive` cannot be derived for enums \ - with struct variants"); - return cx.expr_fail(trait_span, - InternedString::new("")); - } - } + // arm for `_ if $guard => $body` + let arm = ast::Arm { + attrs: vec!(), + pats: vec!(cx.pat_wild(span)), + guard: Some(guard), + body: body, + }; + + arms.push(arm); } // arm for `_ => None` diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 3c1aa992a3c..88781c3664a 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -450,20 +450,12 @@ pub fn noop_fold_foreign_mod(ForeignMod {abi, items}: ForeignMod, } pub fn noop_fold_variant(v: P, fld: &mut T) -> P { - v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr}, span}| Spanned { + v.map(|Spanned {node: Variant_ {id, name, attrs, def, disr_expr}, span}| Spanned { node: Variant_ { id: fld.new_id(id), name: name, attrs: fold_attrs(attrs, fld), - kind: match kind { - TupleVariantKind(variant_args) => { - TupleVariantKind(variant_args.move_map(|x| - fld.fold_variant_arg(x))) - } - StructVariantKind(struct_def) => { - StructVariantKind(fld.fold_struct_def(struct_def)) - } - }, + def: fld.fold_struct_def(def), disr_expr: disr_expr.map(|e| fld.fold_expr(e)), }, span: fld.new_span(span), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 443cea696b6..0748c898a82 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -46,11 +46,11 @@ use ast::{PolyTraitRef, QSelf}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; -use ast::{StructVariantKind, BiSub, StrStyle}; +use ast::{BiSub, StrStyle}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; use ast::{TtDelimited, TtSequence, TtToken}; -use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; +use ast::{Ty, Ty_, TypeBinding}; use ast::{TyMac}; use ast::{TyFixedLengthVec, TyBareFn, TyTypeof, TyInfer}; use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr}; @@ -5131,22 +5131,13 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult { let variant_attrs = self.parse_outer_attributes(); let vlo = self.span.lo; - let kind; - let mut args = Vec::new(); + let struct_def; let mut disr_expr = None; let ident = try!(self.parse_ident()); if try!(self.eat(&token::OpenDelim(token::Brace)) ){ // Parse a struct variant. all_nullary = false; - let start_span = self.span; - let struct_def = try!(self.parse_struct_def()); - if struct_def.fields.is_empty() { - self.span_err(start_span, - &format!("unit-like struct variant should be written \ - without braces, as `{},`", - ident)); - } - kind = StructVariantKind(struct_def); + struct_def = try!(self.parse_struct_def()); } else if self.check(&token::OpenDelim(token::Paren)) { all_nullary = false; let arg_tys = try!(self.parse_enum_variant_seq( @@ -5155,25 +5146,31 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult { seq_sep_trailing_allowed(token::Comma), |p| p.parse_ty_sum() )); + let mut fields = Vec::new(); for ty in arg_tys { - args.push(ast::VariantArg { + fields.push(Spanned { span: ty.span, node: ast::StructField_ { ty: ty, + kind: ast::UnnamedField(ast::Inherited), + attrs: Vec::new(), id: ast::DUMMY_NODE_ID, - }); + }}); } - kind = TupleVariantKind(args); + struct_def = P(StructDef { fields: fields, + ctor_id: Some(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); - kind = TupleVariantKind(args); + struct_def = P(StructDef { fields: Vec::new(), + ctor_id: Some(ast::DUMMY_NODE_ID) }); } else { - kind = TupleVariantKind(Vec::new()); + struct_def = P(StructDef { fields: Vec::new(), + ctor_id: Some(ast::DUMMY_NODE_ID) }); } let vr = ast::Variant_ { name: ident, attrs: variant_attrs, - kind: kind, + def: struct_def, id: ast::DUMMY_NODE_ID, disr_expr: disr_expr, }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f5f3907a4e6..678b8e04897 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1223,7 +1223,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> { } ast::ItemStruct(ref struct_def, ref generics) => { try!(self.head(&visibility_qualified(item.vis,"struct"))); - try!(self.print_struct(&**struct_def, generics, item.ident, item.span)); + try!(self.print_struct(&struct_def, generics, item.ident, item.span, true)); } ast::ItemDefaultImpl(unsafety, ref trait_ref) => { @@ -1388,7 +1388,8 @@ pub fn print_struct(&mut self, struct_def: &ast::StructDef, generics: &ast::Generics, ident: ast::Ident, - span: codemap::Span) -> io::Result<()> { + span: codemap::Span, + print_finalizer: bool) -> io::Result<()> { try!(self.print_ident(ident)); try!(self.print_generics(generics)); if ast_util::struct_def_is_tuple_like(struct_def) { @@ -1410,7 +1411,9 @@ pub fn print_struct(&mut self, try!(self.pclose()); } try!(self.print_where_clause(&generics.where_clause)); - try!(word(&mut self.s, ";")); + if print_finalizer { + try!(word(&mut self.s, ";")); + } try!(self.end()); self.end() // close the outer-box } else { @@ -1505,23 +1508,9 @@ pub fn print_tts(&mut self, tts: &[ast::TokenTree]) -> io::Result<()> { } pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> { - match v.node.kind { - ast::TupleVariantKind(ref args) => { - try!(self.print_ident(v.node.name)); - if !args.is_empty() { - try!(self.popen()); - try!(self.commasep(Consistent, - &args[..], - |s, arg| s.print_type(&*arg.ty))); - try!(self.pclose()); - } - } - ast::StructVariantKind(ref struct_def) => { - try!(self.head("")); - let generics = ast_util::empty_generics(); - try!(self.print_struct(&**struct_def, &generics, v.node.name, v.span)); - } - } + try!(self.head("")); + let generics = ast_util::empty_generics(); + try!(self.print_struct(&v.node.def, &generics, v.node.name, v.span, false)); match v.node.disr_expr { Some(ref d) => { try!(space(&mut self.s)); @@ -3103,6 +3092,7 @@ mod tests { use ast_util; use codemap; use parse::token; + use ptr::P; #[test] fn test_fun_to_string() { @@ -3129,7 +3119,7 @@ fn test_variant_to_string() { name: ident, attrs: Vec::new(), // making this up as I go.... ? - kind: ast::TupleVariantKind(Vec::new()), + def: P(ast::StructDef { fields: Vec::new(), ctor_id: Some(ast::DUMMY_NODE_ID) }), id: 0, disr_expr: None, }); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 091580b9bd8..fe64f87e681 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -315,20 +315,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant, generics: &'v Generics) { visitor.visit_ident(variant.span, variant.node.name); - - match variant.node.kind { - TupleVariantKind(ref variant_arguments) => { - for variant_argument in variant_arguments { - visitor.visit_ty(&variant_argument.ty) - } - } - StructVariantKind(ref struct_definition) => { - visitor.visit_struct_def(struct_definition, - variant.node.name, - generics, - variant.node.id) - } - } + visitor.visit_struct_def(&variant.node.def, variant.node.name, generics, variant.node.id); walk_list!(visitor, visit_expr, &variant.node.disr_expr); walk_list!(visitor, visit_attribute, &variant.node.attrs); } diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs index 6e9b120aa69..e8e37d88049 100644 --- a/src/test/compile-fail/deriving-primitive.rs +++ b/src/test/compile-fail/deriving-primitive.rs @@ -23,12 +23,12 @@ struct A { x: isize } #[derive(FromPrimitive)] enum C { Foo(isize), Bar(usize) } -//~^^ ERROR `FromPrimitive` cannot be derived for enum variants with arguments -//~^^^ ERROR `FromPrimitive` cannot be derived for enum variants with arguments +//~^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants +//~^^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants #[derive(FromPrimitive)] enum D { Baz { x: isize } } -//~^^ ERROR `FromPrimitive` cannot be derived for enums with struct variants -//~^^^ ERROR `FromPrimitive` cannot be derived for enums with struct variants +//~^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants +//~^^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants pub fn main() {} diff --git a/src/test/parse-fail/struct-variant-no-fields.rs b/src/test/parse-fail/struct-variant-no-fields.rs deleted file mode 100644 index 68cf661e218..00000000000 --- a/src/test/parse-fail/struct-variant-no-fields.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -// compile-flags: -Z parse-only - -enum Foo { - Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,` -}