@@ -706,15 +706,6 @@ impl<'a> TraitDef<'a> {
706
706
}
707
707
}
708
708
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
-
718
709
impl < ' a > MethodDef < ' a > {
719
710
fn call_substructure_method ( & self ,
720
711
cx : & mut ExtCtxt ,
@@ -1044,8 +1035,8 @@ impl<'a> MethodDef<'a> {
1044
1035
. collect :: < Vec < ast:: Ident > > ( ) ;
1045
1036
1046
1037
// 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 .
1049
1040
let vi_idents: Vec < ast:: Ident > = self_arg_names. iter ( )
1050
1041
. map ( |name| { let vi_suffix = format ! ( "{}_vi" , & name[ ..] ) ;
1051
1042
cx. ident_of ( & vi_suffix[ ..] ) } )
@@ -1160,33 +1151,39 @@ impl<'a> MethodDef<'a> {
1160
1151
// unreachable-pattern error.
1161
1152
//
1162
1153
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
-
1170
1154
// 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
+ //
1172
1159
// i.e. for `enum E<T> { A, B(1), C(T, T) }`, and a deriving
1173
1160
// with three Self args, builds three statements:
1174
1161
//
1175
1162
// ```
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;
1185
1169
// ```
1186
1170
let mut index_let_stmts: Vec < P < ast:: Stmt > > = Vec :: new ( ) ;
1187
1171
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) ;
1190
1187
index_let_stmts. push ( let_stmt) ;
1191
1188
}
1192
1189
0 commit comments