Skip to content

Commit 095af52

Browse files
committed
Auto merge of #32139 - durka:derive-fix, r=alexcrichton
cleanups and fixes for #[derive] This contains a bunch of little cleanups and fixes to `#[derive]`. There are more extensive comments on each individual commit. - hygiene cleanups - use `discriminant_value` instead of variant index in `#[derive(Hash)]` - ~~don't move out of borrowed content in `#[derive(PartialOrd, PartialEq)]`~~ - use `intrinsics::unreachable()` instead of `unreachable!()` I don't believe there are any breaking changes in here, but I do want some more eyes on that. Fixes #2810 (!), I believe (we still assume that "std" or "core" is the standard library but so does the rest of rustc...). Fixes #21714 (cc @apasel422). ~~Fixes~~ (postponed) #24047 (cc @withoutboats @bluss). Fixes #31714 (cc @alexcrichton @bluss). Fixes #31886 (cc @oli-obk).
2 parents ce943eb + a037073 commit 095af52

File tree

11 files changed

+242
-157
lines changed

11 files changed

+242
-157
lines changed

src/libsyntax_ext/deriving/cmp/ord.rs

+25-29
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use deriving::generic::*;
1212
use deriving::generic::ty::*;
1313

14-
use syntax::ast::{MetaItem, Expr, BinOpKind, self};
14+
use syntax::ast::{MetaItem, Expr, self};
1515
use syntax::codemap::Span;
1616
use syntax::ext::base::{ExtCtxt, Annotatable};
1717
use syntax::ext::build::AstBuilder;
@@ -64,7 +64,7 @@ pub fn ordering_collapsed(cx: &mut ExtCtxt,
6464

6565
pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
6666
substr: &Substructure) -> P<Expr> {
67-
let test_id = cx.ident_of("__test");
67+
let test_id = cx.ident_of("cmp");
6868
let equals_path = cx.path_global(span,
6969
cx.std_path(&["cmp", "Ordering", "Equal"]));
7070

@@ -73,36 +73,31 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
7373
/*
7474
Builds:
7575
76-
let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1);
77-
if other == ::std::cmp::Ordering::Equal {
78-
let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2);
79-
if __test == ::std::cmp::Ordering::Equal {
80-
...
81-
} else {
82-
__test
83-
}
84-
} else {
85-
__test
76+
match ::std::cmp::Ord::cmp(&self_field1, &other_field1) {
77+
::std::cmp::Ordering::Equal =>
78+
match ::std::cmp::Ord::cmp(&self_field2, &other_field2) {
79+
::std::cmp::Ordering::Equal => {
80+
...
81+
}
82+
cmp => cmp
83+
},
84+
cmp => cmp
8685
}
87-
88-
FIXME #6449: These `if`s could/should be `match`es.
8986
*/
9087
cs_fold(
9188
// foldr nests the if-elses correctly, leaving the first field
9289
// as the outermost one, and the last as the innermost.
9390
false,
9491
|cx, span, old, self_f, other_fs| {
95-
// let __test = new;
96-
// if __test == ::std::cmp::Ordering::Equal {
97-
// old
98-
// } else {
99-
// __test
92+
// match new {
93+
// ::std::cmp::Ordering::Equal => old,
94+
// cmp => cmp
10095
// }
10196

10297
let new = {
10398
let other_f = match (other_fs.len(), other_fs.get(0)) {
10499
(1, Some(o_f)) => o_f,
105-
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
100+
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
106101
};
107102

108103
let args = vec![
@@ -113,20 +108,21 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
113108
cx.expr_call_global(span, cmp_path.clone(), args)
114109
};
115110

116-
let assign = cx.stmt_let(span, false, test_id, new);
111+
let eq_arm = cx.arm(span,
112+
vec![cx.pat_enum(span,
113+
equals_path.clone(),
114+
vec![])],
115+
old);
116+
let neq_arm = cx.arm(span,
117+
vec![cx.pat_ident(span, test_id)],
118+
cx.expr_ident(span, test_id));
117119

118-
let cond = cx.expr_binary(span, BinOpKind::Eq,
119-
cx.expr_ident(span, test_id),
120-
cx.expr_path(equals_path.clone()));
121-
let if_ = cx.expr_if(span,
122-
cond,
123-
old, Some(cx.expr_ident(span, test_id)));
124-
cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
120+
cx.expr_match(span, new, vec![eq_arm, neq_arm])
125121
},
126122
cx.expr_path(equals_path.clone()),
127123
Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
128124
if self_args.len() != 2 {
129-
cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`")
125+
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
130126
} else {
131127
ordering_collapsed(cx, span, tag_tuple)
132128
}

src/libsyntax_ext/deriving/cmp/partial_ord.rs

+26-29
Original file line numberDiff line numberDiff line change
@@ -107,41 +107,36 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt,
107107

108108
pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
109109
substr: &Substructure) -> P<Expr> {
110-
let test_id = cx.ident_of("__test");
110+
let test_id = cx.ident_of("cmp");
111111
let ordering = cx.path_global(span,
112112
cx.std_path(&["cmp", "Ordering", "Equal"]));
113-
let ordering = cx.expr_path(ordering);
114-
let equals_expr = cx.expr_some(span, ordering);
113+
let ordering_expr = cx.expr_path(ordering.clone());
114+
let equals_expr = cx.expr_some(span, ordering_expr);
115115

116116
let partial_cmp_path = cx.std_path(&["cmp", "PartialOrd", "partial_cmp"]);
117117

118118
/*
119119
Builds:
120120
121-
let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1);
122-
if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) {
123-
let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2);
124-
if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) {
125-
...
126-
} else {
127-
__test
128-
}
129-
} else {
130-
__test
121+
match ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1) {
122+
::std::option::Option::Some(::std::cmp::Ordering::Equal) =>
123+
match ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2) {
124+
::std::option::Option::Some(::std::cmp::Ordering::Equal) => {
125+
...
126+
}
127+
cmp => cmp
128+
},
129+
cmp => cmp
131130
}
132-
133-
FIXME #6449: These `if`s could/should be `match`es.
134131
*/
135132
cs_fold(
136133
// foldr nests the if-elses correctly, leaving the first field
137134
// as the outermost one, and the last as the innermost.
138135
false,
139136
|cx, span, old, self_f, other_fs| {
140-
// let __test = new;
141-
// if __test == Some(::std::cmp::Ordering::Equal) {
142-
// old
143-
// } else {
144-
// __test
137+
// match new {
138+
// Some(::std::cmp::Ordering::Equal) => old,
139+
// cmp => cmp
145140
// }
146141

147142
let new = {
@@ -158,15 +153,17 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
158153
cx.expr_call_global(span, partial_cmp_path.clone(), args)
159154
};
160155

161-
let assign = cx.stmt_let(span, false, test_id, new);
162-
163-
let cond = cx.expr_binary(span, BinOpKind::Eq,
164-
cx.expr_ident(span, test_id),
165-
equals_expr.clone());
166-
let if_ = cx.expr_if(span,
167-
cond,
168-
old, Some(cx.expr_ident(span, test_id)));
169-
cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
156+
let eq_arm = cx.arm(span,
157+
vec![cx.pat_some(span,
158+
cx.pat_enum(span,
159+
ordering.clone(),
160+
vec![]))],
161+
old);
162+
let neq_arm = cx.arm(span,
163+
vec![cx.pat_ident(span, test_id)],
164+
cx.expr_ident(span, test_id));
165+
166+
cx.expr_match(span, new, vec![eq_arm, neq_arm])
170167
},
171168
equals_expr.clone(),
172169
Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {

src/libsyntax_ext/deriving/decodable.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
//! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more.
1212
13+
use deriving;
1314
use deriving::generic::*;
1415
use deriving::generic::ty::*;
1516

@@ -54,6 +55,8 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
5455
return
5556
}
5657

58+
let typaram = &*deriving::hygienic_type_parameter(item, "__D");
59+
5760
let trait_def = TraitDef {
5861
span: span,
5962
attributes: Vec::new(),
@@ -66,18 +69,17 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
6669
name: "decode",
6770
generics: LifetimeBounds {
6871
lifetimes: Vec::new(),
69-
bounds: vec!(("__D", vec!(Path::new_(
70-
vec!(krate, "Decoder"), None,
71-
vec!(), true))))
72+
bounds: vec![(typaram,
73+
vec![Path::new_(vec!(krate, "Decoder"), None, vec!(), true)])]
7274
},
7375
explicit_self: None,
74-
args: vec!(Ptr(Box::new(Literal(Path::new_local("__D"))),
76+
args: vec!(Ptr(Box::new(Literal(Path::new_local(typaram))),
7577
Borrowed(None, Mutability::Mutable))),
7678
ret_ty: Literal(Path::new_(
7779
pathvec_std!(cx, core::result::Result),
7880
None,
7981
vec!(Box::new(Self_), Box::new(Literal(Path::new_(
80-
vec!["__D", "Error"], None, vec![], false
82+
vec![typaram, "Error"], None, vec![], false
8183
)))),
8284
true
8385
)),

src/libsyntax_ext/deriving/encodable.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
//! }
8989
//! ```
9090
91+
use deriving;
9192
use deriving::generic::*;
9293
use deriving::generic::ty::*;
9394

@@ -130,6 +131,8 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
130131
return;
131132
}
132133

134+
let typaram = &*deriving::hygienic_type_parameter(item, "__S");
135+
133136
let trait_def = TraitDef {
134137
span: span,
135138
attributes: Vec::new(),
@@ -142,18 +145,17 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
142145
name: "encode",
143146
generics: LifetimeBounds {
144147
lifetimes: Vec::new(),
145-
bounds: vec!(("__S", vec!(Path::new_(
146-
vec!(krate, "Encoder"), None,
147-
vec!(), true))))
148+
bounds: vec![(typaram,
149+
vec![Path::new_(vec![krate, "Encoder"], None, vec!(), true)])]
148150
},
149151
explicit_self: borrowed_explicit_self(),
150-
args: vec!(Ptr(Box::new(Literal(Path::new_local("__S"))),
152+
args: vec!(Ptr(Box::new(Literal(Path::new_local(typaram))),
151153
Borrowed(None, Mutability::Mutable))),
152154
ret_ty: Literal(Path::new_(
153155
pathvec_std!(cx, core::result::Result),
154156
None,
155157
vec!(Box::new(Tuple(Vec::new())), Box::new(Literal(Path::new_(
156-
vec!["__S", "Error"], None, vec![], false
158+
vec![typaram, "Error"], None, vec![], false
157159
)))),
158160
true
159161
)),

0 commit comments

Comments
 (0)