Skip to content

Commit 6118795

Browse files
committed
Change derive expansions to use discriminant_value intrinsic.
Fix #15523.
1 parent ea27391 commit 6118795

File tree

2 files changed

+28
-30
lines changed

2 files changed

+28
-30
lines changed

src/libcore/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ mod tuple;
157157

158158
#[doc(hidden)]
159159
mod core {
160+
pub use intrinsics;
160161
pub use panicking;
161162
pub use fmt;
162163
pub use clone;

src/libsyntax/ext/deriving/generic/mod.rs

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -706,15 +706,6 @@ impl<'a> TraitDef<'a> {
706706
}
707707
}
708708

709-
fn variant_to_pat(cx: &mut ExtCtxt, sp: Span, enum_ident: ast::Ident, variant: &ast::Variant)
710-
-> P<ast::Pat> {
711-
let path = cx.path(sp, vec![enum_ident, variant.node.name]);
712-
cx.pat(sp, match variant.node.kind {
713-
ast::TupleVariantKind(..) => ast::PatEnum(path, None),
714-
ast::StructVariantKind(..) => ast::PatStruct(path, Vec::new(), true),
715-
})
716-
}
717-
718709
impl<'a> MethodDef<'a> {
719710
fn call_substructure_method(&self,
720711
cx: &mut ExtCtxt,
@@ -1044,8 +1035,8 @@ impl<'a> MethodDef<'a> {
10441035
.collect::<Vec<ast::Ident>>();
10451036

10461037
// The `vi_idents` will be bound, solely in the catch-all, to
1047-
// a series of let statements mapping each self_arg to a usize
1048-
// corresponding to its variant index.
1038+
// a series of let statements mapping each self_arg to an isize
1039+
// corresponding to its discriminant value.
10491040
let vi_idents: Vec<ast::Ident> = self_arg_names.iter()
10501041
.map(|name| { let vi_suffix = format!("{}_vi", &name[..]);
10511042
cx.ident_of(&vi_suffix[..]) })
@@ -1160,33 +1151,39 @@ impl<'a> MethodDef<'a> {
11601151
// unreachable-pattern error.
11611152
//
11621153
if variants.len() > 1 && self_args.len() > 1 {
1163-
let arms: Vec<ast::Arm> = variants.iter().enumerate()
1164-
.map(|(index, variant)| {
1165-
let pat = variant_to_pat(cx, sp, type_ident, &**variant);
1166-
let lit = ast::LitInt(index as u64, ast::UnsignedIntLit(ast::TyUs));
1167-
cx.arm(sp, vec![pat], cx.expr_lit(sp, lit))
1168-
}).collect();
1169-
11701154
// Build a series of let statements mapping each self_arg
1171-
// to a usize corresponding to its variant index.
1155+
// to its discriminant value. If this is a C-style enum
1156+
// with a specific repr type, then casts the values to
1157+
// that type. Otherwise casts to `isize`.
1158+
//
11721159
// i.e. for `enum E<T> { A, B(1), C(T, T) }`, and a deriving
11731160
// with three Self args, builds three statements:
11741161
//
11751162
// ```
1176-
// let __self0_vi = match self {
1177-
// A => 0, B(..) => 1, C(..) => 2
1178-
// };
1179-
// let __self1_vi = match __arg1 {
1180-
// A => 0, B(..) => 1, C(..) => 2
1181-
// };
1182-
// let __self2_vi = match __arg2 {
1183-
// A => 0, B(..) => 1, C(..) => 2
1184-
// };
1163+
// let __self0_vi = unsafe {
1164+
// std::intrinsics::discriminant_value(&self) } as isize;
1165+
// let __self1_vi = unsafe {
1166+
// std::intrinsics::discriminant_value(&__arg1) } as isize;
1167+
// let __self2_vi = unsafe {
1168+
// std::intrinsics::discriminant_value(&__arg2) } as isize;
11851169
// ```
11861170
let mut index_let_stmts: Vec<P<ast::Stmt>> = Vec::new();
11871171
for (&ident, self_arg) in vi_idents.iter().zip(self_args.iter()) {
1188-
let variant_idx = cx.expr_match(sp, self_arg.clone(), arms.clone());
1189-
let let_stmt = cx.stmt_let(sp, false, ident, variant_idx);
1172+
let path = vec![cx.ident_of_std("core"),
1173+
cx.ident_of("intrinsics"),
1174+
cx.ident_of("discriminant_value")];
1175+
let call = cx.expr_call_global(
1176+
sp, path, vec![cx.expr_addr_of(sp, self_arg.clone())]);
1177+
let variant_value = cx.expr_block(P(ast::Block {
1178+
stmts: vec![],
1179+
expr: Some(call),
1180+
id: ast::DUMMY_NODE_ID,
1181+
rules: ast::UnsafeBlock(ast::CompilerGenerated),
1182+
span: sp }));
1183+
1184+
let target_ty = cx.ty_ident(sp, cx.ident_of("isize"));
1185+
let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
1186+
let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
11901187
index_let_stmts.push(let_stmt);
11911188
}
11921189

0 commit comments

Comments
 (0)