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

Commit 10144e2

Browse files
committed
Handle tags better.
Currently, for the enums and comparison traits we always check the tag for equality before doing anything else. This is a bit clumsy. This commit changes things so that the tags are handled very much like a zeroth field in the enum. For `eq`/ne` this makes the code slightly cleaner. For `partial_cmp` and `cmp` it's a more notable change: in the case where the tags aren't equal, instead of having a tag equality check followed by a tag comparison, it just does a single tag comparison. The commit also improves how `Hash` works for enums: instead of having duplicated code to hash the tag for every arm within the match, we do it just once before the match. All this required replacing the `EnumNonMatchingCollapsed` value with a new `EnumTag` value. For fieldless enums the new code is particularly improved. All the code now produced is close to optimal, being very similar to what you'd write by hand.
1 parent 4bcbd76 commit 10144e2

File tree

9 files changed

+245
-329
lines changed

9 files changed

+245
-329
lines changed

compiler/rustc_builtin_macros/src/deriving/clone.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ fn cs_clone_simple(
148148
),
149149
}
150150
}
151-
BlockOrExpr::new_mixed(stmts, cx.expr_deref(trait_span, cx.expr_self(trait_span)))
151+
BlockOrExpr::new_mixed(stmts, Some(cx.expr_deref(trait_span, cx.expr_self(trait_span))))
152152
}
153153

154154
fn cs_clone(
@@ -177,9 +177,7 @@ fn cs_clone(
177177
all_fields = af;
178178
vdata = &variant.data;
179179
}
180-
EnumNonMatchingCollapsed(..) => {
181-
cx.span_bug(trait_span, &format!("non-matching enum variants in `derive({})`", name,))
182-
}
180+
EnumTag(..) => cx.span_bug(trait_span, &format!("enum tags in `derive({})`", name,)),
183181
StaticEnum(..) | StaticStruct(..) => {
184182
cx.span_bug(trait_span, &format!("associated function in `derive({})`", name))
185183
}

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,6 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> Bl
7373
cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
7474
}
7575
CsFold::Fieldless => cx.expr_path(equal_path.clone()),
76-
CsFold::EnumNonMatching(span, tag_tuple) => {
77-
if tag_tuple.len() != 2 {
78-
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
79-
} else {
80-
let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0]));
81-
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[1]));
82-
let fn_cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
83-
cx.expr_call_global(span, fn_cmp_path, vec![lft, rgt])
84-
}
85-
}
8676
},
8777
);
8878
BlockOrExpr::new_expr(expr)

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ pub fn expand_deriving_partial_eq(
5151
}
5252
CsFold::Combine(span, expr1, expr2) => cx.expr_binary(span, combiner, expr1, expr2),
5353
CsFold::Fieldless => cx.expr_bool(span, base),
54-
CsFold::EnumNonMatching(span, _tag_tuple) => cx.expr_bool(span, !base),
5554
},
5655
);
5756
BlockOrExpr::new_expr(expr)

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,6 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
8282
cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
8383
}
8484
CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())),
85-
CsFold::EnumNonMatching(span, tag_tuple) => {
86-
if tag_tuple.len() != 2 {
87-
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
88-
} else {
89-
let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0]));
90-
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[1]));
91-
let fn_partial_cmp_path =
92-
cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
93-
cx.expr_call_global(span, fn_partial_cmp_path, vec![lft, rgt])
94-
}
95-
}
9685
},
9786
);
9887
BlockOrExpr::new_expr(expr)

compiler/rustc_builtin_macros/src/deriving/debug.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
4545
let (ident, vdata, fields) = match substr.fields {
4646
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
4747
EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
48-
EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => {
48+
EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
4949
cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
5050
}
5151
};
@@ -176,6 +176,6 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
176176
stmts.push(names_let.unwrap());
177177
}
178178
stmts.push(values_let);
179-
BlockOrExpr::new_mixed(stmts, expr)
179+
BlockOrExpr::new_mixed(stmts, Some(expr))
180180
}
181181
}

compiler/rustc_builtin_macros/src/deriving/encodable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ fn encodable_substructure(
287287
fn_emit_enum_path,
288288
vec![encoder, cx.expr_str(trait_span, substr.type_ident.name), blk],
289289
);
290-
BlockOrExpr::new_mixed(vec![me], expr)
290+
BlockOrExpr::new_mixed(vec![me], Some(expr))
291291
}
292292

293293
_ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"),

0 commit comments

Comments
 (0)