diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 2d9673574c340..026442ba7ac48 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -171,9 +171,11 @@ pub trait AstBuilder { span: Span, ident: ast::Ident, bm: ast::BindingMode) -> P; - fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec> ) -> P; - fn pat_struct(&self, span: Span, - path: ast::Path, field_pats: Vec> ) -> P; + fn pat_path(&self, span: Span, path: ast::Path) -> P; + fn pat_tuple_struct(&self, span: Span, path: ast::Path, + subpats: Vec>) -> P; + fn pat_struct(&self, span: Span, path: ast::Path, + field_pats: Vec>) -> P; fn pat_tuple(&self, span: Span, pats: Vec>) -> P; fn pat_some(&self, span: Span, pat: P) -> P; @@ -802,10 +804,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let binding_expr = self.expr_ident(sp, binding_variable); // Ok(__try_var) pattern - let ok_pat = self.pat_enum(sp, ok_path, vec!(binding_pat.clone())); + let ok_pat = self.pat_tuple_struct(sp, ok_path, vec![binding_pat.clone()]); // Err(__try_var) (pattern and expression resp.) - let err_pat = self.pat_enum(sp, err_path.clone(), vec!(binding_pat)); + let err_pat = self.pat_tuple_struct(sp, err_path.clone(), vec![binding_pat]); let err_inner_expr = self.expr_call(sp, self.expr_path(err_path), vec!(binding_expr.clone())); // return Err(__try_var) @@ -842,18 +844,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let pat = PatKind::Ident(bm, Spanned{span: span, node: ident}, None); self.pat(span, pat) } - fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec>) -> P { - let pat = if subpats.is_empty() { - PatKind::Path(None, path) - } else { - PatKind::TupleStruct(path, subpats, None) - }; - self.pat(span, pat) + fn pat_path(&self, span: Span, path: ast::Path) -> P { + self.pat(span, PatKind::Path(None, path)) } - fn pat_struct(&self, span: Span, - path: ast::Path, field_pats: Vec>) -> P { - let pat = PatKind::Struct(path, field_pats, false); - self.pat(span, pat) + fn pat_tuple_struct(&self, span: Span, path: ast::Path, + subpats: Vec>) -> P { + self.pat(span, PatKind::TupleStruct(path, subpats, None)) + } + fn pat_struct(&self, span: Span, path: ast::Path, + field_pats: Vec>) -> P { + self.pat(span, PatKind::Struct(path, field_pats, false)) } fn pat_tuple(&self, span: Span, pats: Vec>) -> P { self.pat(span, PatKind::Tuple(pats, None)) @@ -862,25 +862,25 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn pat_some(&self, span: Span, pat: P) -> P { let some = self.std_path(&["option", "Option", "Some"]); let path = self.path_global(span, some); - self.pat_enum(span, path, vec!(pat)) + self.pat_tuple_struct(span, path, vec![pat]) } fn pat_none(&self, span: Span) -> P { let some = self.std_path(&["option", "Option", "None"]); let path = self.path_global(span, some); - self.pat_enum(span, path, vec!()) + self.pat_path(span, path) } fn pat_ok(&self, span: Span, pat: P) -> P { let some = self.std_path(&["result", "Result", "Ok"]); let path = self.path_global(span, some); - self.pat_enum(span, path, vec!(pat)) + self.pat_tuple_struct(span, path, vec![pat]) } fn pat_err(&self, span: Span, pat: P) -> P { let some = self.std_path(&["result", "Result", "Err"]); let path = self.path_global(span, some); - self.pat_enum(span, path, vec!(pat)) + self.pat_tuple_struct(span, path, vec![pat]) } fn arm(&self, _span: Span, pats: Vec>, expr: P) -> ast::Arm { diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 8ae77e79310b2..31194b04fa6e4 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -104,7 +104,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { }; let eq_arm = cx.arm(span, - vec![cx.pat_enum(span, equals_path.clone(), vec![])], + vec![cx.pat_path(span, equals_path.clone())], old); let neq_arm = cx.arm(span, vec![cx.pat_ident(span, test_id)], diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index 10a9738742e44..9e9b2f020622f 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -165,7 +165,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P< }; let eq_arm = cx.arm(span, - vec![cx.pat_some(span, cx.pat_enum(span, ordering.clone(), vec![]))], + vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))], old); let neq_arm = cx.arm(span, vec![cx.pat_ident(span, test_id)], diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 9a332227053c7..f395f7bd0c4c4 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -110,7 +110,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, return match *substr.fields { StaticStruct(_, ref summary) => { let nfields = match *summary { - Unnamed(ref fields) => fields.len(), + Unnamed(ref fields, _) => fields.len(), Named(ref fields) => fields.len(), }; let read_struct_field = cx.ident_of("read_struct_field"); @@ -193,9 +193,9 @@ fn decode_static_fields(cx: &mut ExtCtxt, where F: FnMut(&mut ExtCtxt, Span, InternedString, usize) -> P { match *fields { - Unnamed(ref fields) => { + Unnamed(ref fields, is_tuple) => { let path_expr = cx.expr_path(outer_pat_path); - if fields.is_empty() { + if !is_tuple { path_expr } else { let fields = fields.iter() diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index 9df3db938b1f9..449c1ff066b3b 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -57,8 +57,8 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur return match *substr.fields { StaticStruct(_, ref summary) => { match *summary { - Unnamed(ref fields) => { - if fields.is_empty() { + Unnamed(ref fields, is_tuple) => { + if !is_tuple { cx.expr_ident(trait_span, substr.type_ident) } else { let exprs = fields.iter().map(|sp| default_call(*sp)).collect(); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 5960e4546b18c..03282653d3620 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -294,8 +294,8 @@ pub struct FieldInfo<'a> { /// Fields for a static method pub enum StaticFields { - /// Tuple structs/enum variants like this. - Unnamed(Vec), + /// Tuple and unit structs/enum variants like this. + Unnamed(Vec, bool /*is tuple*/), /// Normal structs/struct variants. Named(Vec<(Ident, Span)>), } @@ -1472,7 +1472,7 @@ impl<'a> TraitDef<'a> { (_, false) => Named(named_idents), // empty structs _ if struct_def.is_struct() => Named(named_idents), - _ => Unnamed(just_spans), + _ => Unnamed(just_spans, struct_def.is_tuple()), } } @@ -1512,26 +1512,32 @@ impl<'a> TraitDef<'a> { } let subpats = self.create_subpatterns(cx, paths, mutbl); - let pattern = if struct_def.is_struct() { - let field_pats = subpats.into_iter() - .zip(&ident_exprs) - .map(|(pat, &(sp, ident, _, _))| { - if ident.is_none() { - cx.span_bug(sp, "a braced struct with unnamed fields in `derive`"); - } - codemap::Spanned { - span: pat.span, - node: ast::FieldPat { - ident: ident.unwrap(), - pat: pat, - is_shorthand: false, - }, - } - }) - .collect(); - cx.pat_struct(self.span, struct_path, field_pats) - } else { - cx.pat_enum(self.span, struct_path, subpats) + let pattern = match *struct_def { + VariantData::Struct(..) => { + let field_pats = subpats.into_iter() + .zip(&ident_exprs) + .map(|(pat, &(sp, ident, _, _))| { + if ident.is_none() { + cx.span_bug(sp, "a braced struct with unnamed fields in `derive`"); + } + codemap::Spanned { + span: pat.span, + node: ast::FieldPat { + ident: ident.unwrap(), + pat: pat, + is_shorthand: false, + }, + } + }) + .collect(); + cx.pat_struct(self.span, struct_path, field_pats) + } + VariantData::Tuple(..) => { + cx.pat_tuple_struct(self.span, struct_path, subpats) + } + VariantData::Unit(..) => { + cx.pat_path(self.span, struct_path) + } }; (pattern, ident_exprs) diff --git a/src/test/run-pass-fulldeps/empty-struct-braces-derive.rs b/src/test/run-pass-fulldeps/empty-struct-braces-derive.rs index 8d19209208dc4..66ffff94333e9 100644 --- a/src/test/run-pass-fulldeps/empty-struct-braces-derive.rs +++ b/src/test/run-pass-fulldeps/empty-struct-braces-derive.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// `#[derive(Trait)]` works for empty structs/variants with braces +// `#[derive(Trait)]` works for empty structs/variants with braces or parens. +#![feature(relaxed_adts)] #![feature(rustc_private)] extern crate serialize as rustc_serialize; @@ -18,11 +19,16 @@ extern crate serialize as rustc_serialize; Default, Debug, RustcEncodable, RustcDecodable)] struct S {} +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, + Default, Debug, RustcEncodable, RustcDecodable)] +struct Z(); + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] enum E { V {}, U, + W(), } fn main() { @@ -34,6 +40,14 @@ fn main() { assert!(!(s < s1)); assert_eq!(format!("{:?}", s), "S"); + let z = Z(); + let z1 = z; + let z2 = z.clone(); + assert_eq!(z, z1); + assert_eq!(z, z2); + assert!(!(z < z1)); + assert_eq!(format!("{:?}", z), "Z"); + let e = E::V {}; let e1 = e; let e2 = e.clone(); @@ -41,4 +55,12 @@ fn main() { assert_eq!(e, e2); assert!(!(e < e1)); assert_eq!(format!("{:?}", e), "V"); + + let e = E::W(); + let e1 = e; + let e2 = e.clone(); + assert_eq!(e, e1); + assert_eq!(e, e2); + assert!(!(e < e1)); + assert_eq!(format!("{:?}", e), "W"); }