Skip to content

Commit 62f13cd

Browse files
authored
Rollup merge of rust-lang#98915 - nnethercote:clarify-deriving-code, r=Mark-Simulacrum
Clarify deriving code A number of clarifications to the deriving code. r? `@Mark-Simulacrum`
2 parents 1e8af6b + 0578697 commit 62f13cd

File tree

11 files changed

+454
-567
lines changed

11 files changed

+454
-567
lines changed

compiler/rustc_builtin_macros/src/deriving/clone.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub fn expand_deriving_clone(
8080
name: sym::clone,
8181
generics: Bounds::empty(),
8282
explicit_self: true,
83-
args: Vec::new(),
83+
nonself_args: Vec::new(),
8484
ret_ty: Self_,
8585
attributes: attrs,
8686
unify_fieldless_variants: false,
@@ -160,8 +160,8 @@ fn cs_clone(
160160
let ctor_path;
161161
let all_fields;
162162
let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]);
163-
let subcall = |cx: &mut ExtCtxt<'_>, field: &FieldInfo<'_>| {
164-
let args = vec![cx.expr_addr_of(field.span, field.self_.clone())];
163+
let subcall = |cx: &mut ExtCtxt<'_>, field: &FieldInfo| {
164+
let args = vec![cx.expr_addr_of(field.span, field.self_expr.clone())];
165165
cx.expr_call_global(field.span, fn_path.clone(), args)
166166
};
167167

compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub fn expand_deriving_eq(
3232
name: sym::assert_receiver_is_total_eq,
3333
generics: Bounds::empty(),
3434
explicit_self: true,
35-
args: vec![],
35+
nonself_args: vec![],
3636
ret_ty: Unit,
3737
attributes: attrs,
3838
unify_fieldless_variants: true,

compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs

+36-67
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33
use crate::deriving::path_std;
44

5-
use rustc_ast::ptr::P;
6-
use rustc_ast::{self as ast, MetaItem};
5+
use rustc_ast::MetaItem;
76
use rustc_expand::base::{Annotatable, ExtCtxt};
87
use rustc_span::symbol::{sym, Ident};
98
use rustc_span::Span;
@@ -28,7 +27,7 @@ pub fn expand_deriving_ord(
2827
name: sym::cmp,
2928
generics: Bounds::empty(),
3029
explicit_self: true,
31-
args: vec![(self_ref(), sym::other)],
30+
nonself_args: vec![(self_ref(), sym::other)],
3231
ret_ty: Path(path_std!(cmp::Ordering)),
3332
attributes: attrs,
3433
unify_fieldless_variants: true,
@@ -40,84 +39,54 @@ pub fn expand_deriving_ord(
4039
trait_def.expand(cx, mitem, item, push)
4140
}
4241

43-
pub fn ordering_collapsed(
44-
cx: &mut ExtCtxt<'_>,
45-
span: Span,
46-
self_arg_tags: &[Ident],
47-
) -> P<ast::Expr> {
48-
let lft = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[0]));
49-
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
50-
let fn_cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
51-
cx.expr_call_global(span, fn_cmp_path, vec![lft, rgt])
52-
}
53-
5442
pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
5543
let test_id = Ident::new(sym::cmp, span);
56-
let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
57-
44+
let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
5845
let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
5946

6047
// Builds:
6148
//
62-
// match ::std::cmp::Ord::cmp(&self_field1, &other_field1) {
63-
// ::std::cmp::Ordering::Equal =>
64-
// match ::std::cmp::Ord::cmp(&self_field2, &other_field2) {
65-
// ::std::cmp::Ordering::Equal => {
66-
// ...
49+
// match ::core::cmp::Ord::cmp(&self.x, &other.x) {
50+
// ::std::cmp::Ordering::Equal =>
51+
// ::core::cmp::Ord::cmp(&self.y, &other.y),
52+
// cmp => cmp,
6753
// }
68-
// cmp => cmp
69-
// },
70-
// cmp => cmp
71-
// }
72-
//
7354
let expr = cs_fold(
7455
// foldr nests the if-elses correctly, leaving the first field
7556
// as the outermost one, and the last as the innermost.
7657
false,
77-
|cx, span, old, self_f, other_fs| {
78-
// match new {
79-
// ::std::cmp::Ordering::Equal => old,
80-
// cmp => cmp
81-
// }
82-
let new = {
83-
let [other_f] = other_fs else {
84-
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
85-
};
86-
let args =
87-
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
88-
cx.expr_call_global(span, cmp_path.clone(), args)
89-
};
90-
91-
let eq_arm = cx.arm(span, cx.pat_path(span, equals_path.clone()), old);
92-
let neq_arm = cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
93-
94-
cx.expr_match(span, new, vec![eq_arm, neq_arm])
95-
},
96-
|cx, args| match args {
97-
Some((span, self_f, other_fs)) => {
98-
let new = {
99-
let [other_f] = other_fs else {
100-
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
101-
};
102-
let args =
103-
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
104-
cx.expr_call_global(span, cmp_path.clone(), args)
105-
};
106-
107-
new
108-
}
109-
None => cx.expr_path(equals_path.clone()),
110-
},
111-
Box::new(|cx, span, tag_tuple| {
112-
if tag_tuple.len() != 2 {
113-
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
114-
} else {
115-
ordering_collapsed(cx, span, tag_tuple)
116-
}
117-
}),
11858
cx,
11959
span,
12060
substr,
61+
|cx, fold| match fold {
62+
CsFold::Single(field) => {
63+
let [other_expr] = &field.other_selflike_exprs[..] else {
64+
cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
65+
};
66+
let args = vec![
67+
cx.expr_addr_of(field.span, field.self_expr.clone()),
68+
cx.expr_addr_of(field.span, other_expr.clone()),
69+
];
70+
cx.expr_call_global(field.span, cmp_path.clone(), args)
71+
}
72+
CsFold::Combine(span, expr1, expr2) => {
73+
let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1);
74+
let neq_arm =
75+
cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
76+
cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
77+
}
78+
CsFold::Fieldless => cx.expr_path(equal_path.clone()),
79+
CsFold::EnumNonMatching(span, tag_tuple) => {
80+
if tag_tuple.len() != 2 {
81+
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
82+
} else {
83+
let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0]));
84+
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[1]));
85+
let fn_cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
86+
cx.expr_call_global(span, fn_cmp_path, vec![lft, rgt])
87+
}
88+
}
89+
},
12190
);
12291
BlockOrExpr::new_expr(expr)
12392
}

compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs

+13-25
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33
use crate::deriving::{path_local, path_std};
44

5-
use rustc_ast::ptr::P;
6-
use rustc_ast::{BinOpKind, Expr, MetaItem};
5+
use rustc_ast::{BinOpKind, MetaItem};
76
use rustc_expand::base::{Annotatable, ExtCtxt};
87
use rustc_span::symbol::sym;
98
use rustc_span::Span;
@@ -23,33 +22,22 @@ pub fn expand_deriving_partial_eq(
2322
combiner: BinOpKind,
2423
base: bool,
2524
) -> BlockOrExpr {
26-
let op = |cx: &mut ExtCtxt<'_>, span: Span, self_f: P<Expr>, other_fs: &[P<Expr>]| {
27-
let [other_f] = other_fs else {
28-
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`");
29-
};
30-
31-
cx.expr_binary(span, op, self_f, other_f.clone())
32-
};
33-
3425
let expr = cs_fold(
3526
true, // use foldl
36-
|cx, span, subexpr, self_f, other_fs| {
37-
let eq = op(cx, span, self_f, other_fs);
38-
cx.expr_binary(span, combiner, subexpr, eq)
39-
},
40-
|cx, args| {
41-
match args {
42-
Some((span, self_f, other_fs)) => {
43-
// Special-case the base case to generate cleaner code.
44-
op(cx, span, self_f, other_fs)
45-
}
46-
None => cx.expr_bool(span, base),
47-
}
48-
},
49-
Box::new(|cx, span, _| cx.expr_bool(span, !base)),
5027
cx,
5128
span,
5229
substr,
30+
|cx, fold| match fold {
31+
CsFold::Single(field) => {
32+
let [other_expr] = &field.other_selflike_exprs[..] else {
33+
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
34+
};
35+
cx.expr_binary(field.span, op, field.self_expr.clone(), other_expr.clone())
36+
}
37+
CsFold::Combine(span, expr1, expr2) => cx.expr_binary(span, combiner, expr1, expr2),
38+
CsFold::Fieldless => cx.expr_bool(span, base),
39+
CsFold::EnumNonMatching(span, _tag_tuple) => cx.expr_bool(span, !base),
40+
},
5341
);
5442
BlockOrExpr::new_expr(expr)
5543
}
@@ -69,7 +57,7 @@ pub fn expand_deriving_partial_eq(
6957
name: $name,
7058
generics: Bounds::empty(),
7159
explicit_self: true,
72-
args: vec![(self_ref(), sym::other)],
60+
nonself_args: vec![(self_ref(), sym::other)],
7361
ret_ty: Path(path_local!(bool)),
7462
attributes: attrs,
7563
unify_fieldless_variants: true,

compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs

+38-64
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33
use crate::deriving::{path_std, pathvec_std};
44

5-
use rustc_ast::ptr::P;
6-
use rustc_ast::{Expr, MetaItem};
5+
use rustc_ast::MetaItem;
76
use rustc_expand::base::{Annotatable, ExtCtxt};
87
use rustc_span::symbol::{sym, Ident};
98
use rustc_span::Span;
@@ -26,7 +25,7 @@ pub fn expand_deriving_partial_ord(
2625
name: sym::partial_cmp,
2726
generics: Bounds::empty(),
2827
explicit_self: true,
29-
args: vec![(self_ref(), sym::other)],
28+
nonself_args: vec![(self_ref(), sym::other)],
3029
ret_ty,
3130
attributes: attrs,
3231
unify_fieldless_variants: true,
@@ -50,79 +49,54 @@ pub fn expand_deriving_partial_ord(
5049

5150
pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
5251
let test_id = Ident::new(sym::cmp, span);
53-
let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
54-
let ordering_expr = cx.expr_path(ordering.clone());
55-
52+
let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
5653
let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
5754

5855
// Builds:
5956
//
60-
// match ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1) {
61-
// ::std::option::Option::Some(::std::cmp::Ordering::Equal) =>
62-
// match ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2) {
63-
// ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {
64-
// ...
65-
// }
66-
// cmp => cmp
67-
// },
68-
// cmp => cmp
57+
// match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) {
58+
// ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
59+
// ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y),
60+
// cmp => cmp,
6961
// }
70-
//
7162
let expr = cs_fold(
7263
// foldr nests the if-elses correctly, leaving the first field
7364
// as the outermost one, and the last as the innermost.
7465
false,
75-
|cx, span, old, self_f, other_fs| {
76-
// match new {
77-
// Some(::std::cmp::Ordering::Equal) => old,
78-
// cmp => cmp
79-
// }
80-
81-
let new = {
82-
let [other_f] = other_fs else {
83-
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`");
84-
};
85-
86-
let args =
87-
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
88-
89-
cx.expr_call_global(span, partial_cmp_path.clone(), args)
90-
};
91-
92-
let eq_arm = cx.arm(span, cx.pat_some(span, cx.pat_path(span, ordering.clone())), old);
93-
let neq_arm = cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
94-
95-
cx.expr_match(span, new, vec![eq_arm, neq_arm])
96-
},
97-
|cx: &mut ExtCtxt<'_>, args: Option<(Span, P<Expr>, &[P<Expr>])>| match args {
98-
Some((span, self_f, other_fs)) => {
99-
let new = {
100-
let [other_f] = other_fs else {
101-
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
102-
};
103-
let args =
104-
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
105-
cx.expr_call_global(span, partial_cmp_path.clone(), args)
106-
};
107-
108-
new
109-
}
110-
None => cx.expr_some(span, ordering_expr.clone()),
111-
},
112-
Box::new(|cx, span, tag_tuple| {
113-
if tag_tuple.len() != 2 {
114-
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
115-
} else {
116-
let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0]));
117-
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[1]));
118-
let fn_partial_cmp_path =
119-
cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
120-
cx.expr_call_global(span, fn_partial_cmp_path, vec![lft, rgt])
121-
}
122-
}),
12366
cx,
12467
span,
12568
substr,
69+
|cx, fold| match fold {
70+
CsFold::Single(field) => {
71+
let [other_expr] = &field.other_selflike_exprs[..] else {
72+
cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
73+
};
74+
let args = vec![
75+
cx.expr_addr_of(field.span, field.self_expr.clone()),
76+
cx.expr_addr_of(field.span, other_expr.clone()),
77+
];
78+
cx.expr_call_global(field.span, partial_cmp_path.clone(), args)
79+
}
80+
CsFold::Combine(span, expr1, expr2) => {
81+
let eq_arm =
82+
cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1);
83+
let neq_arm =
84+
cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
85+
cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
86+
}
87+
CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())),
88+
CsFold::EnumNonMatching(span, tag_tuple) => {
89+
if tag_tuple.len() != 2 {
90+
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
91+
} else {
92+
let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0]));
93+
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[1]));
94+
let fn_partial_cmp_path =
95+
cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
96+
cx.expr_call_global(span, fn_partial_cmp_path, vec![lft, rgt])
97+
}
98+
}
99+
},
126100
);
127101
BlockOrExpr::new_expr(expr)
128102
}

0 commit comments

Comments
 (0)