Skip to content

Commit 5762d23

Browse files
committed
Avoid unnecessary blocks in derive output.
By not committing to either block form or expression form until necessary, we can avoid lots of unnecessary blocks.
1 parent d4ecc4f commit 5762d23

File tree

12 files changed

+406
-427
lines changed

12 files changed

+406
-427
lines changed

compiler/rustc_builtin_macros/src/deriving/clone.rs

Lines changed: 7 additions & 8 deletions
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, Expr, Generics, ItemKind, MetaItem, VariantData};
5+
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
76
use rustc_expand::base::{Annotatable, ExtCtxt};
87
use rustc_span::symbol::{kw, sym, Ident};
98
use rustc_span::Span;
@@ -98,7 +97,7 @@ fn cs_clone_simple(
9897
trait_span: Span,
9998
substr: &Substructure<'_>,
10099
is_union: bool,
101-
) -> P<Expr> {
100+
) -> BlockOrExpr {
102101
let mut stmts = Vec::new();
103102
let mut process_variant = |variant: &VariantData| {
104103
for field in variant.fields() {
@@ -139,16 +138,15 @@ fn cs_clone_simple(
139138
),
140139
}
141140
}
142-
stmts.push(cx.stmt_expr(cx.expr_deref(trait_span, cx.expr_self(trait_span))));
143-
cx.expr_block(cx.block(trait_span, stmts))
141+
BlockOrExpr::new_mixed(stmts, cx.expr_deref(trait_span, cx.expr_self(trait_span)))
144142
}
145143

146144
fn cs_clone(
147145
name: &str,
148146
cx: &mut ExtCtxt<'_>,
149147
trait_span: Span,
150148
substr: &Substructure<'_>,
151-
) -> P<Expr> {
149+
) -> BlockOrExpr {
152150
let ctor_path;
153151
let all_fields;
154152
let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]);
@@ -177,7 +175,7 @@ fn cs_clone(
177175
}
178176
}
179177

180-
match *vdata {
178+
let expr = match *vdata {
181179
VariantData::Struct(..) => {
182180
let fields = all_fields
183181
.iter()
@@ -201,5 +199,6 @@ fn cs_clone(
201199
cx.expr_call(trait_span, path, subcalls)
202200
}
203201
VariantData::Unit(..) => cx.expr_path(ctor_path),
204-
}
202+
};
203+
BlockOrExpr::new_expr(expr)
205204
}

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

Lines changed: 3 additions & 4 deletions
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, Expr, MetaItem};
5+
use rustc_ast::{self as ast, MetaItem};
76
use rustc_expand::base::{Annotatable, ExtCtxt};
87
use rustc_span::symbol::{sym, Ident};
98
use rustc_span::Span;
@@ -52,7 +51,7 @@ fn cs_total_eq_assert(
5251
cx: &mut ExtCtxt<'_>,
5352
trait_span: Span,
5453
substr: &Substructure<'_>,
55-
) -> P<Expr> {
54+
) -> BlockOrExpr {
5655
let mut stmts = Vec::new();
5756
let mut process_variant = |variant: &ast::VariantData| {
5857
for field in variant.fields() {
@@ -78,5 +77,5 @@ fn cs_total_eq_assert(
7877
}
7978
_ => cx.span_bug(trait_span, "unexpected substructure in `derive(Eq)`"),
8079
}
81-
cx.expr_block(cx.block(trait_span, stmts))
80+
BlockOrExpr::new_stmts(stmts)
8281
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::deriving::generic::*;
33
use crate::deriving::path_std;
44

55
use rustc_ast::ptr::P;
6-
use rustc_ast::{self as ast, Expr, MetaItem};
6+
use rustc_ast::{self as ast, MetaItem};
77
use rustc_expand::base::{Annotatable, ExtCtxt};
88
use rustc_span::symbol::{sym, Ident};
99
use rustc_span::Span;
@@ -51,7 +51,7 @@ pub fn ordering_collapsed(
5151
cx.expr_call_global(span, fn_cmp_path, vec![lft, rgt])
5252
}
5353

54-
pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
54+
pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
5555
let test_id = Ident::new(sym::cmp, span);
5656
let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
5757

@@ -70,7 +70,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<
7070
// cmp => cmp
7171
// }
7272
//
73-
cs_fold(
73+
let expr = cs_fold(
7474
// foldr nests the if-elses correctly, leaving the first field
7575
// as the outermost one, and the last as the innermost.
7676
false,
@@ -107,5 +107,6 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<
107107
cx,
108108
span,
109109
substr,
110-
)
110+
);
111+
BlockOrExpr::new_expr(expr)
111112
}

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,14 @@ pub fn expand_deriving_partial_eq(
1515
item: &Annotatable,
1616
push: &mut dyn FnMut(Annotatable),
1717
) {
18-
// structures are equal if all fields are equal, and non equal, if
19-
// any fields are not equal or if the enum variants are different
2018
fn cs_op(
2119
cx: &mut ExtCtxt<'_>,
2220
span: Span,
2321
substr: &Substructure<'_>,
2422
op: BinOpKind,
2523
combiner: BinOpKind,
2624
base: bool,
27-
) -> P<Expr> {
25+
) -> BlockOrExpr {
2826
let op = |cx: &mut ExtCtxt<'_>, span: Span, self_f: P<Expr>, other_fs: &[P<Expr>]| {
2927
let [other_f] = other_fs else {
3028
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`");
@@ -33,7 +31,7 @@ pub fn expand_deriving_partial_eq(
3331
cx.expr_binary(span, op, self_f, other_f.clone())
3432
};
3533

36-
cs_fold1(
34+
let expr = cs_fold1(
3735
true, // use foldl
3836
|cx, span, subexpr, self_f, other_fs| {
3937
let eq = op(cx, span, self_f, other_fs);
@@ -52,13 +50,14 @@ pub fn expand_deriving_partial_eq(
5250
cx,
5351
span,
5452
substr,
55-
)
53+
);
54+
BlockOrExpr::new_expr(expr)
5655
}
5756

58-
fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
57+
fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
5958
cs_op(cx, span, substr, BinOpKind::Eq, BinOpKind::And, true)
6059
}
61-
fn cs_ne(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
60+
fn cs_ne(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
6261
cs_op(cx, span, substr, BinOpKind::Ne, BinOpKind::Or, false)
6362
}
6463

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

Lines changed: 5 additions & 5 deletions
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;
@@ -48,7 +47,7 @@ pub fn expand_deriving_partial_ord(
4847
trait_def.expand(cx, mitem, item, push)
4948
}
5049

51-
pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
50+
pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
5251
let test_id = Ident::new(sym::cmp, span);
5352
let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
5453
let ordering_expr = cx.expr_path(ordering.clone());
@@ -69,7 +68,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
6968
// cmp => cmp
7069
// }
7170
//
72-
cs_fold(
71+
let expr = cs_fold(
7372
// foldr nests the if-elses correctly, leaving the first field
7473
// as the outermost one, and the last as the innermost.
7574
false,
@@ -110,5 +109,6 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
110109
cx,
111110
span,
112111
substr,
113-
)
112+
);
113+
BlockOrExpr::new_expr(expr)
114114
}

compiler/rustc_builtin_macros/src/deriving/debug.rs

Lines changed: 7 additions & 8 deletions
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, Expr, MetaItem};
5+
use rustc_ast::{self as ast, MetaItem};
76
use rustc_expand::base::{Annotatable, ExtCtxt};
87
use rustc_span::symbol::{sym, Ident, Symbol};
98
use rustc_span::Span;
@@ -42,7 +41,7 @@ pub fn expand_deriving_debug(
4241
trait_def.expand(cx, mitem, item, push)
4342
}
4443

45-
fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
44+
fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
4645
let (ident, vdata, fields) = match substr.fields {
4746
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
4847
EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
@@ -74,7 +73,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
7473
if fields.is_empty() {
7574
// Special case for no fields.
7675
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
77-
cx.expr_call_global(span, fn_path_write_str, vec![fmt, name])
76+
let expr = cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]);
77+
BlockOrExpr::new_expr(expr)
7878
} else if fields.len() <= CUTOFF {
7979
// Few enough fields that we can use a specific-length method.
8080
let debug = if is_struct {
@@ -100,7 +100,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
100100
let field = cx.expr_addr_of(field.span, field);
101101
args.push(field);
102102
}
103-
cx.expr_call_global(span, fn_path_debug, args)
103+
let expr = cx.expr_call_global(span, fn_path_debug, args);
104+
BlockOrExpr::new_expr(expr)
104105
} else {
105106
// Enough fields that we must use the any-length method.
106107
let mut name_exprs = Vec::with_capacity(fields.len());
@@ -176,8 +177,6 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
176177
stmts.push(names_let.unwrap());
177178
}
178179
stmts.push(values_let);
179-
stmts.push(cx.stmt_expr(expr));
180-
181-
cx.expr_block(cx.block(span, stmts))
180+
BlockOrExpr::new_mixed(stmts, expr)
182181
}
183182
}

compiler/rustc_builtin_macros/src/deriving/decodable.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fn decodable_substructure(
6262
trait_span: Span,
6363
substr: &Substructure<'_>,
6464
krate: Symbol,
65-
) -> P<Expr> {
65+
) -> BlockOrExpr {
6666
let decoder = substr.nonself_args[0].clone();
6767
let recurse = vec![
6868
Ident::new(krate, trait_span),
@@ -74,7 +74,7 @@ fn decodable_substructure(
7474
let blkarg = Ident::new(sym::_d, trait_span);
7575
let blkdecoder = cx.expr_ident(trait_span, blkarg);
7676

77-
match *substr.fields {
77+
let expr = match *substr.fields {
7878
StaticStruct(_, ref summary) => {
7979
let nfields = match *summary {
8080
Unnamed(ref fields, _) => fields.len(),
@@ -173,7 +173,8 @@ fn decodable_substructure(
173173
)
174174
}
175175
_ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
176-
}
176+
};
177+
BlockOrExpr::new_expr(expr)
177178
}
178179

179180
/// Creates a decoder for a single enum variant/struct:

compiler/rustc_builtin_macros/src/deriving/default.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33

4-
use rustc_ast::ptr::P;
4+
use rustc_ast as ast;
55
use rustc_ast::walk_list;
66
use rustc_ast::EnumDef;
77
use rustc_ast::VariantData;
8-
use rustc_ast::{Expr, MetaItem};
98
use rustc_errors::Applicability;
109
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
1110
use rustc_span::symbol::Ident;
@@ -16,7 +15,7 @@ use smallvec::SmallVec;
1615
pub fn expand_deriving_default(
1716
cx: &mut ExtCtxt<'_>,
1817
span: Span,
19-
mitem: &MetaItem,
18+
mitem: &ast::MetaItem,
2019
item: &Annotatable,
2120
push: &mut dyn FnMut(Annotatable),
2221
) {
@@ -59,12 +58,12 @@ fn default_struct_substructure(
5958
trait_span: Span,
6059
substr: &Substructure<'_>,
6160
summary: &StaticFields,
62-
) -> P<Expr> {
61+
) -> BlockOrExpr {
6362
// Note that `kw::Default` is "default" and `sym::Default` is "Default"!
6463
let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]);
6564
let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
6665

67-
match summary {
66+
let expr = match summary {
6867
Unnamed(ref fields, is_tuple) => {
6968
if !is_tuple {
7069
cx.expr_ident(trait_span, substr.type_ident)
@@ -80,31 +79,27 @@ fn default_struct_substructure(
8079
.collect();
8180
cx.expr_struct_ident(trait_span, substr.type_ident, default_fields)
8281
}
83-
}
82+
};
83+
BlockOrExpr::new_expr(expr)
8484
}
8585

8686
fn default_enum_substructure(
8787
cx: &mut ExtCtxt<'_>,
8888
trait_span: Span,
8989
enum_def: &EnumDef,
90-
) -> P<Expr> {
91-
let Ok(default_variant) = extract_default_variant(cx, enum_def, trait_span) else {
92-
return DummyResult::raw_expr(trait_span, true);
90+
) -> BlockOrExpr {
91+
let expr = if let Ok(default_variant) = extract_default_variant(cx, enum_def, trait_span)
92+
&& let Ok(_) = validate_default_attribute(cx, default_variant)
93+
{
94+
// We now know there is exactly one unit variant with exactly one `#[default]` attribute.
95+
cx.expr_path(cx.path(
96+
default_variant.span,
97+
vec![Ident::new(kw::SelfUpper, default_variant.span), default_variant.ident],
98+
))
99+
} else {
100+
DummyResult::raw_expr(trait_span, true)
93101
};
94-
95-
// At this point, we know that there is exactly one variant with a `#[default]` attribute. The
96-
// attribute hasn't yet been validated.
97-
98-
if let Err(()) = validate_default_attribute(cx, default_variant) {
99-
return DummyResult::raw_expr(trait_span, true);
100-
}
101-
102-
// We now know there is exactly one unit variant with exactly one `#[default]` attribute.
103-
104-
cx.expr_path(cx.path(
105-
default_variant.span,
106-
vec![Ident::new(kw::SelfUpper, default_variant.span), default_variant.ident],
107-
))
102+
BlockOrExpr::new_expr(expr)
108103
}
109104

110105
fn extract_default_variant<'a>(

0 commit comments

Comments
 (0)