Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

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)