diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2016-02-22 21:24:32 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2016-02-22 21:24:32 +0300 |
| commit | 4e8e607d8469a8882944233e4bb3ee45d2a6435a (patch) | |
| tree | 1383d1f4a4e8982ea73c7165a169ba0fa53912a2 /src/libsyntax_ext | |
| parent | 98a59cf57e02b6e6a5a3bd74eb47b1422eaacc53 (diff) | |
| download | rust-4e8e607d8469a8882944233e4bb3ee45d2a6435a.tar.gz rust-4e8e607d8469a8882944233e4bb3ee45d2a6435a.zip | |
Fix #[derive] for empty structs with braces
Diffstat (limited to 'src/libsyntax_ext')
| -rw-r--r-- | src/libsyntax_ext/deriving/clone.rs | 50 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/debug.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/encodable.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/generic/mod.rs | 21 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/hash.rs | 2 |
5 files changed, 49 insertions, 37 deletions
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 1825c3d347e..0085182d1ac 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -11,7 +11,7 @@ use deriving::generic::*; use deriving::generic::ty::*; -use syntax::ast::{MetaItem, Expr}; +use syntax::ast::{MetaItem, Expr, VariantData}; use syntax::codemap::Span; use syntax::ext::base::{ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; @@ -66,14 +66,17 @@ fn cs_clone( cx.expr_call_global(field.span, fn_path.clone(), args) }; + let vdata; match *substr.fields { - Struct(ref af) => { + Struct(vdata_, ref af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident]); all_fields = af; + vdata = vdata_; } EnumMatching(_, variant, ref af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]); all_fields = af; + vdata = &variant.node.data; }, EnumNonMatchingCollapsed (..) => { cx.span_bug(trait_span, @@ -86,30 +89,29 @@ fn cs_clone( } } - if !all_fields.is_empty() && all_fields[0].name.is_none() { - // enum-like - let subcalls = all_fields.iter().map(subcall).collect(); - let path = cx.expr_path(ctor_path); - cx.expr_call(trait_span, path, subcalls) - } else { - // struct-like - let fields = all_fields.iter().map(|field| { - let ident = match field.name { - Some(i) => i, - None => { - cx.span_bug(trait_span, - &format!("unnamed field in normal struct in \ - `derive({})`", name)) - } - }; - cx.field_imm(field.span, ident, subcall(field)) - }).collect::<Vec<_>>(); + match *vdata { + VariantData::Struct(..) => { + let fields = all_fields.iter().map(|field| { + let ident = match field.name { + Some(i) => i, + None => { + cx.span_bug(trait_span, + &format!("unnamed field in normal struct in \ + `derive({})`", name)) + } + }; + cx.field_imm(field.span, ident, subcall(field)) + }).collect::<Vec<_>>(); - if fields.is_empty() { - // no fields, so construct like `None` - cx.expr_path(ctor_path) - } else { cx.expr_struct(trait_span, ctor_path, fields) } + VariantData::Tuple(..) => { + let subcalls = all_fields.iter().map(subcall).collect(); + let path = cx.expr_path(ctor_path); + cx.expr_call(trait_span, path, subcalls) + } + VariantData::Unit(..) => { + cx.expr_path(ctor_path) + } } } diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 6439e9aa498..109f2ad4025 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -62,7 +62,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, // or fmt.debug_tuple(<name>).field(&<fieldval>)....build() // based on the "shape". let ident = match *substr.fields { - Struct(_) => substr.type_ident, + Struct(..) => substr.type_ident, EnumMatching(_, v, _) => v.node.name, EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => { cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`") @@ -76,11 +76,16 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, let builder_expr = cx.expr_ident(span, builder.clone()); let fmt = substr.nonself_args[0].clone(); + let is_struct = match *substr.fields { + Struct(vdata, _) => vdata, + EnumMatching(_, v, _) => &v.node.data, + _ => unreachable!() + }.is_struct(); let stmts = match *substr.fields { - Struct(ref fields) | EnumMatching(_, _, ref fields) => { + Struct(_, ref fields) | EnumMatching(_, _, ref fields) => { let mut stmts = vec![]; - if fields.is_empty() || fields[0].name.is_none() { + if !is_struct { // tuple struct/"normal" variant let expr = cx.expr_method_call(span, fmt, diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 614a6381962..8262a04e9ce 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -179,7 +179,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, let encode = cx.ident_of("encode"); return match *substr.fields { - Struct(ref fields) => { + Struct(_, ref fields) => { let emit_struct_field = cx.ident_of("emit_struct_field"); let mut stmts = Vec::new(); for (i, &FieldInfo { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index bdba49f2f29..c0237a5d29a 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -300,7 +300,7 @@ pub enum StaticFields { /// A summary of the possible sets of fields. pub enum SubstructureFields<'a> { - Struct(Vec<FieldInfo<'a>>), + Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>), /// Matching variants of the enum: variant index, ast::Variant, /// fields: the field name is only non-`None` in the case of a struct /// variant. @@ -981,7 +981,7 @@ impl<'a> MethodDef<'a> { type_ident, self_args, nonself_args, - &Struct(fields)); + &Struct(struct_def, fields)); // make a series of nested matches, to destructure the // structs. This is actually right-to-left, but it shouldn't @@ -1460,8 +1460,9 @@ impl<'a> TraitDef<'a> { fields in generic `derive`"), // named fields (_, false) => Named(named_idents), - // tuple structs (includes empty structs) - (_, _) => Unnamed(just_spans) + // empty structs + _ if struct_def.is_struct() => Named(named_idents), + _ => Unnamed(just_spans), } } @@ -1486,7 +1487,11 @@ impl<'a> TraitDef<'a> { P<Expr>, &'a [ast::Attribute])>) { if struct_def.fields().is_empty() { - return (cx.pat_enum(self.span, struct_path, vec![]), vec![]); + if struct_def.is_struct() { + return (cx.pat_struct(self.span, struct_path, vec![]), vec![]); + } else { + return (cx.pat_enum(self.span, struct_path, vec![]), vec![]); + } } let mut paths = Vec::new(); @@ -1521,7 +1526,7 @@ impl<'a> TraitDef<'a> { // struct_type is definitely not Unknown, since struct_def.fields // must be nonempty to reach here - let pattern = if struct_type == Record { + let pattern = if struct_def.is_struct() { let field_pats = subpats.into_iter().zip(&ident_expr) .map(|(pat, &(_, id, _, _))| { // id is guaranteed to be Some @@ -1566,7 +1571,7 @@ pub fn cs_fold<F>(use_foldl: bool, F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>, { match *substructure.fields { - EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => { + EnumMatching(_, _, ref all_fields) | Struct(_, ref all_fields) => { if use_foldl { all_fields.iter().fold(base, |old, field| { f(cx, @@ -1612,7 +1617,7 @@ pub fn cs_same_method<F>(f: F, F: FnOnce(&mut ExtCtxt, Span, Vec<P<Expr>>) -> P<Expr>, { match *substructure.fields { - EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => { + EnumMatching(_, _, ref all_fields) | Struct(_, ref all_fields) => { // call self_n.method(other_1_n, other_2_n, ...) let called = all_fields.iter().map(|field| { cx.expr_method_call(field.span, diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 371ba732b48..bf8aa8fb23d 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -76,7 +76,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let mut stmts = Vec::new(); let fields = match *substr.fields { - Struct(ref fs) => fs, + Struct(_, ref fs) => fs, EnumMatching(index, variant, ref fs) => { // Determine the discriminant. We will feed this value to the byte // iteration function. |
