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)),
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<hir::Block> {
P(hir::Block {
id: b.id,
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);
pub struct Variant_ {
pub name: Ident,
pub attrs: Vec<Attribute>,
- pub kind: VariantKind,
+ pub def: P<StructDef>,
pub id: NodeId,
/// Explicit discriminant, eg `Foo = 1`
pub disr_expr: Option<P<Expr>>,
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
}
fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> 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,
})
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| {
-> P<Expr> {
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,
-> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'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)
}
}
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`
}
pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
- 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),
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};
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(
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,
};
}
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) => {
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) {
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 {
}
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));
use ast_util;
use codemap;
use parse::token;
+ use ptr::P;
#[test]
fn test_fun_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,
});
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);
}
#[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() {}
+++ /dev/null
-// 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.
-
-// compile-flags: -Z parse-only
-
-enum Foo {
- Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,`
-}