Skip to content

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

Diff for: compiler/rustc_builtin_macros/src/deriving/clone.rs

+2-4
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
}

Diff for: compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs

-10
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)

Diff for: compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs

-1
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)

Diff for: compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs

-11
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)

Diff for: compiler/rustc_builtin_macros/src/deriving/debug.rs

+2-2
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
}

Diff for: compiler/rustc_builtin_macros/src/deriving/encodable.rs

+1-1
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)