Skip to content

Commit 413ecde

Browse files
committed
Rollup merge of rust-lang#35728 - petrochenkov:empderive, r=manishearth
Fix #[derive] for empty tuple structs/variants This was missing from rust-lang#35138
2 parents bd38e89 + f6e06a8 commit 413ecde

File tree

7 files changed

+79
-51
lines changed

7 files changed

+79
-51
lines changed

src/libsyntax/ext/build.rs

+20-20
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,11 @@ pub trait AstBuilder {
171171
span: Span,
172172
ident: ast::Ident,
173173
bm: ast::BindingMode) -> P<ast::Pat>;
174-
fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<P<ast::Pat>> ) -> P<ast::Pat>;
175-
fn pat_struct(&self, span: Span,
176-
path: ast::Path, field_pats: Vec<Spanned<ast::FieldPat>> ) -> P<ast::Pat>;
174+
fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat>;
175+
fn pat_tuple_struct(&self, span: Span, path: ast::Path,
176+
subpats: Vec<P<ast::Pat>>) -> P<ast::Pat>;
177+
fn pat_struct(&self, span: Span, path: ast::Path,
178+
field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat>;
177179
fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat>;
178180

179181
fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat>;
@@ -802,10 +804,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
802804
let binding_expr = self.expr_ident(sp, binding_variable);
803805

804806
// Ok(__try_var) pattern
805-
let ok_pat = self.pat_enum(sp, ok_path, vec!(binding_pat.clone()));
807+
let ok_pat = self.pat_tuple_struct(sp, ok_path, vec![binding_pat.clone()]);
806808

807809
// Err(__try_var) (pattern and expression resp.)
808-
let err_pat = self.pat_enum(sp, err_path.clone(), vec!(binding_pat));
810+
let err_pat = self.pat_tuple_struct(sp, err_path.clone(), vec![binding_pat]);
809811
let err_inner_expr = self.expr_call(sp, self.expr_path(err_path),
810812
vec!(binding_expr.clone()));
811813
// return Err(__try_var)
@@ -842,18 +844,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
842844
let pat = PatKind::Ident(bm, Spanned{span: span, node: ident}, None);
843845
self.pat(span, pat)
844846
}
845-
fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
846-
let pat = if subpats.is_empty() {
847-
PatKind::Path(None, path)
848-
} else {
849-
PatKind::TupleStruct(path, subpats, None)
850-
};
851-
self.pat(span, pat)
847+
fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
848+
self.pat(span, PatKind::Path(None, path))
852849
}
853-
fn pat_struct(&self, span: Span,
854-
path: ast::Path, field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
855-
let pat = PatKind::Struct(path, field_pats, false);
856-
self.pat(span, pat)
850+
fn pat_tuple_struct(&self, span: Span, path: ast::Path,
851+
subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
852+
self.pat(span, PatKind::TupleStruct(path, subpats, None))
853+
}
854+
fn pat_struct(&self, span: Span, path: ast::Path,
855+
field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
856+
self.pat(span, PatKind::Struct(path, field_pats, false))
857857
}
858858
fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
859859
self.pat(span, PatKind::Tuple(pats, None))
@@ -862,25 +862,25 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
862862
fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
863863
let some = self.std_path(&["option", "Option", "Some"]);
864864
let path = self.path_global(span, some);
865-
self.pat_enum(span, path, vec!(pat))
865+
self.pat_tuple_struct(span, path, vec![pat])
866866
}
867867

868868
fn pat_none(&self, span: Span) -> P<ast::Pat> {
869869
let some = self.std_path(&["option", "Option", "None"]);
870870
let path = self.path_global(span, some);
871-
self.pat_enum(span, path, vec!())
871+
self.pat_path(span, path)
872872
}
873873

874874
fn pat_ok(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
875875
let some = self.std_path(&["result", "Result", "Ok"]);
876876
let path = self.path_global(span, some);
877-
self.pat_enum(span, path, vec!(pat))
877+
self.pat_tuple_struct(span, path, vec![pat])
878878
}
879879

880880
fn pat_err(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
881881
let some = self.std_path(&["result", "Result", "Err"]);
882882
let path = self.path_global(span, some);
883-
self.pat_enum(span, path, vec!(pat))
883+
self.pat_tuple_struct(span, path, vec![pat])
884884
}
885885

886886
fn arm(&self, _span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm {

src/libsyntax_ext/deriving/cmp/ord.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
104104
};
105105

106106
let eq_arm = cx.arm(span,
107-
vec![cx.pat_enum(span, equals_path.clone(), vec![])],
107+
vec![cx.pat_path(span, equals_path.clone())],
108108
old);
109109
let neq_arm = cx.arm(span,
110110
vec![cx.pat_ident(span, test_id)],

src/libsyntax_ext/deriving/cmp/partial_ord.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
165165
};
166166

167167
let eq_arm = cx.arm(span,
168-
vec![cx.pat_some(span, cx.pat_enum(span, ordering.clone(), vec![]))],
168+
vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))],
169169
old);
170170
let neq_arm = cx.arm(span,
171171
vec![cx.pat_ident(span, test_id)],

src/libsyntax_ext/deriving/decodable.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
110110
return match *substr.fields {
111111
StaticStruct(_, ref summary) => {
112112
let nfields = match *summary {
113-
Unnamed(ref fields) => fields.len(),
113+
Unnamed(ref fields, _) => fields.len(),
114114
Named(ref fields) => fields.len(),
115115
};
116116
let read_struct_field = cx.ident_of("read_struct_field");
@@ -193,9 +193,9 @@ fn decode_static_fields<F>(cx: &mut ExtCtxt,
193193
where F: FnMut(&mut ExtCtxt, Span, InternedString, usize) -> P<Expr>
194194
{
195195
match *fields {
196-
Unnamed(ref fields) => {
196+
Unnamed(ref fields, is_tuple) => {
197197
let path_expr = cx.expr_path(outer_pat_path);
198-
if fields.is_empty() {
198+
if !is_tuple {
199199
path_expr
200200
} else {
201201
let fields = fields.iter()

src/libsyntax_ext/deriving/default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
5757
return match *substr.fields {
5858
StaticStruct(_, ref summary) => {
5959
match *summary {
60-
Unnamed(ref fields) => {
61-
if fields.is_empty() {
60+
Unnamed(ref fields, is_tuple) => {
61+
if !is_tuple {
6262
cx.expr_ident(trait_span, substr.type_ident)
6363
} else {
6464
let exprs = fields.iter().map(|sp| default_call(*sp)).collect();

src/libsyntax_ext/deriving/generic/mod.rs

+29-23
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,8 @@ pub struct FieldInfo<'a> {
294294

295295
/// Fields for a static method
296296
pub enum StaticFields {
297-
/// Tuple structs/enum variants like this.
298-
Unnamed(Vec<Span>),
297+
/// Tuple and unit structs/enum variants like this.
298+
Unnamed(Vec<Span>, bool /*is tuple*/),
299299
/// Normal structs/struct variants.
300300
Named(Vec<(Ident, Span)>),
301301
}
@@ -1472,7 +1472,7 @@ impl<'a> TraitDef<'a> {
14721472
(_, false) => Named(named_idents),
14731473
// empty structs
14741474
_ if struct_def.is_struct() => Named(named_idents),
1475-
_ => Unnamed(just_spans),
1475+
_ => Unnamed(just_spans, struct_def.is_tuple()),
14761476
}
14771477
}
14781478

@@ -1512,26 +1512,32 @@ impl<'a> TraitDef<'a> {
15121512
}
15131513

15141514
let subpats = self.create_subpatterns(cx, paths, mutbl);
1515-
let pattern = if struct_def.is_struct() {
1516-
let field_pats = subpats.into_iter()
1517-
.zip(&ident_exprs)
1518-
.map(|(pat, &(sp, ident, _, _))| {
1519-
if ident.is_none() {
1520-
cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
1521-
}
1522-
codemap::Spanned {
1523-
span: pat.span,
1524-
node: ast::FieldPat {
1525-
ident: ident.unwrap(),
1526-
pat: pat,
1527-
is_shorthand: false,
1528-
},
1529-
}
1530-
})
1531-
.collect();
1532-
cx.pat_struct(self.span, struct_path, field_pats)
1533-
} else {
1534-
cx.pat_enum(self.span, struct_path, subpats)
1515+
let pattern = match *struct_def {
1516+
VariantData::Struct(..) => {
1517+
let field_pats = subpats.into_iter()
1518+
.zip(&ident_exprs)
1519+
.map(|(pat, &(sp, ident, _, _))| {
1520+
if ident.is_none() {
1521+
cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
1522+
}
1523+
codemap::Spanned {
1524+
span: pat.span,
1525+
node: ast::FieldPat {
1526+
ident: ident.unwrap(),
1527+
pat: pat,
1528+
is_shorthand: false,
1529+
},
1530+
}
1531+
})
1532+
.collect();
1533+
cx.pat_struct(self.span, struct_path, field_pats)
1534+
}
1535+
VariantData::Tuple(..) => {
1536+
cx.pat_tuple_struct(self.span, struct_path, subpats)
1537+
}
1538+
VariantData::Unit(..) => {
1539+
cx.pat_path(self.span, struct_path)
1540+
}
15351541
};
15361542

15371543
(pattern, ident_exprs)

src/test/run-pass-fulldeps/empty-struct-braces-derive.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// `#[derive(Trait)]` works for empty structs/variants with braces
11+
// `#[derive(Trait)]` works for empty structs/variants with braces or parens.
1212

13+
#![feature(relaxed_adts)]
1314
#![feature(rustc_private)]
1415

1516
extern crate serialize as rustc_serialize;
@@ -18,11 +19,16 @@ extern crate serialize as rustc_serialize;
1819
Default, Debug, RustcEncodable, RustcDecodable)]
1920
struct S {}
2021

22+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
23+
Default, Debug, RustcEncodable, RustcDecodable)]
24+
struct Z();
25+
2126
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
2227
Debug, RustcEncodable, RustcDecodable)]
2328
enum E {
2429
V {},
2530
U,
31+
W(),
2632
}
2733

2834
fn main() {
@@ -34,11 +40,27 @@ fn main() {
3440
assert!(!(s < s1));
3541
assert_eq!(format!("{:?}", s), "S");
3642

43+
let z = Z();
44+
let z1 = z;
45+
let z2 = z.clone();
46+
assert_eq!(z, z1);
47+
assert_eq!(z, z2);
48+
assert!(!(z < z1));
49+
assert_eq!(format!("{:?}", z), "Z");
50+
3751
let e = E::V {};
3852
let e1 = e;
3953
let e2 = e.clone();
4054
assert_eq!(e, e1);
4155
assert_eq!(e, e2);
4256
assert!(!(e < e1));
4357
assert_eq!(format!("{:?}", e), "V");
58+
59+
let e = E::W();
60+
let e1 = e;
61+
let e2 = e.clone();
62+
assert_eq!(e, e1);
63+
assert_eq!(e, e2);
64+
assert!(!(e < e1));
65+
assert_eq!(format!("{:?}", e), "W");
4466
}

0 commit comments

Comments
 (0)