Skip to content

Commit 9f89853

Browse files
committed
fix FIXME(#6449) in #[derive(PartialOrd, Ord)]
This replaces some `if`s with `match`es. This was originally not possible because using a global path in a match statement caused a "non-constant path in constant expr" ICE. The issue is long since closed, though you still hit it (as an error now, not an ICE) if you try to generate match patterns using pat_lit(expr_path). But it works when constructing the patterns more carefully.
1 parent 7c33793 commit 9f89853

File tree

2 files changed

+48
-55
lines changed

2 files changed

+48
-55
lines changed

src/libsyntax_ext/deriving/cmp/ord.rs

+23-27
Original file line numberDiff line numberDiff line change
@@ -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+
__test => __test
83+
},
84+
__test => __test
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+
// __test => __test
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

+25-28
Original file line numberDiff line numberDiff line change
@@ -110,38 +110,33 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
110110
let test_id = cx.ident_of("__test");
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+
__test => __test
128+
},
129+
__test => __test
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+
// __test => __test
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| {

0 commit comments

Comments
 (0)