@@ -201,6 +201,7 @@ use ext::base::ExtCtxt;
201
201
use ext:: build:: AstBuilder ;
202
202
use codemap:: { self , DUMMY_SP } ;
203
203
use codemap:: Span ;
204
+ use diagnostic:: SpanHandler ;
204
205
use fold:: MoveMap ;
205
206
use owned_slice:: OwnedSlice ;
206
207
use parse:: token:: InternedString ;
@@ -391,6 +392,7 @@ impl<'a> TraitDef<'a> {
391
392
ast:: ItemEnum ( ref enum_def, ref generics) => {
392
393
self . expand_enum_def ( cx,
393
394
enum_def,
395
+ & item. attrs [ ..] ,
394
396
item. ident ,
395
397
generics)
396
398
}
@@ -653,6 +655,7 @@ impl<'a> TraitDef<'a> {
653
655
fn expand_enum_def ( & self ,
654
656
cx : & mut ExtCtxt ,
655
657
enum_def : & EnumDef ,
658
+ type_attrs : & [ ast:: Attribute ] ,
656
659
type_ident : Ident ,
657
660
generics : & Generics ) -> P < ast:: Item > {
658
661
let mut field_tys = Vec :: new ( ) ;
@@ -687,6 +690,7 @@ impl<'a> TraitDef<'a> {
687
690
method_def. expand_enum_method_body ( cx,
688
691
self ,
689
692
enum_def,
693
+ type_attrs,
690
694
type_ident,
691
695
self_args,
692
696
& nonself_args[ ..] )
@@ -706,6 +710,32 @@ impl<'a> TraitDef<'a> {
706
710
}
707
711
}
708
712
713
+ fn find_repr_type_name ( diagnostic : & SpanHandler ,
714
+ type_attrs : & [ ast:: Attribute ] ) -> & ' static str {
715
+ let mut repr_type_name = "i32" ;
716
+ for a in type_attrs {
717
+ for r in & attr:: find_repr_attrs ( diagnostic, a) {
718
+ repr_type_name = match * r {
719
+ attr:: ReprAny | attr:: ReprPacked => continue ,
720
+ attr:: ReprExtern => "i32" ,
721
+
722
+ attr:: ReprInt ( _, attr:: SignedInt ( ast:: TyIs ) ) => "isize" ,
723
+ attr:: ReprInt ( _, attr:: SignedInt ( ast:: TyI8 ) ) => "i8" ,
724
+ attr:: ReprInt ( _, attr:: SignedInt ( ast:: TyI16 ) ) => "i16" ,
725
+ attr:: ReprInt ( _, attr:: SignedInt ( ast:: TyI32 ) ) => "i32" ,
726
+ attr:: ReprInt ( _, attr:: SignedInt ( ast:: TyI64 ) ) => "i64" ,
727
+
728
+ attr:: ReprInt ( _, attr:: UnsignedInt ( ast:: TyUs ) ) => "usize" ,
729
+ attr:: ReprInt ( _, attr:: UnsignedInt ( ast:: TyU8 ) ) => "u8" ,
730
+ attr:: ReprInt ( _, attr:: UnsignedInt ( ast:: TyU16 ) ) => "u16" ,
731
+ attr:: ReprInt ( _, attr:: UnsignedInt ( ast:: TyU32 ) ) => "u32" ,
732
+ attr:: ReprInt ( _, attr:: UnsignedInt ( ast:: TyU64 ) ) => "u64" ,
733
+ }
734
+ }
735
+ }
736
+ repr_type_name
737
+ }
738
+
709
739
impl < ' a > MethodDef < ' a > {
710
740
fn call_substructure_method ( & self ,
711
741
cx : & mut ExtCtxt ,
@@ -974,12 +1004,13 @@ impl<'a> MethodDef<'a> {
974
1004
cx : & mut ExtCtxt ,
975
1005
trait_ : & TraitDef ,
976
1006
enum_def : & EnumDef ,
1007
+ type_attrs : & [ ast:: Attribute ] ,
977
1008
type_ident : Ident ,
978
1009
self_args : Vec < P < Expr > > ,
979
1010
nonself_args : & [ P < Expr > ] )
980
1011
-> P < Expr > {
981
1012
self . build_enum_match_tuple (
982
- cx, trait_, enum_def, type_ident, self_args, nonself_args)
1013
+ cx, trait_, enum_def, type_attrs , type_ident, self_args, nonself_args)
983
1014
}
984
1015
985
1016
@@ -1013,6 +1044,7 @@ impl<'a> MethodDef<'a> {
1013
1044
cx : & mut ExtCtxt ,
1014
1045
trait_ : & TraitDef ,
1015
1046
enum_def : & EnumDef ,
1047
+ type_attrs : & [ ast:: Attribute ] ,
1016
1048
type_ident : Ident ,
1017
1049
self_args : Vec < P < Expr > > ,
1018
1050
nonself_args : & [ P < Expr > ] ) -> P < Expr > {
@@ -1168,6 +1200,10 @@ impl<'a> MethodDef<'a> {
1168
1200
// std::intrinsics::discriminant_value(&__arg2) } as isize;
1169
1201
// ```
1170
1202
let mut index_let_stmts: Vec < P < ast:: Stmt > > = Vec :: new ( ) ;
1203
+
1204
+ let target_type_name =
1205
+ find_repr_type_name ( & cx. parse_sess . span_diagnostic , type_attrs) ;
1206
+
1171
1207
for ( & ident, self_arg) in vi_idents. iter ( ) . zip ( self_args. iter ( ) ) {
1172
1208
let path = vec ! [ cx. ident_of_std( "core" ) ,
1173
1209
cx. ident_of( "intrinsics" ) ,
@@ -1181,18 +1217,7 @@ impl<'a> MethodDef<'a> {
1181
1217
rules : ast:: UnsafeBlock ( ast:: CompilerGenerated ) ,
1182
1218
span : sp } ) ) ;
1183
1219
1184
- // FIXME: This unconditionally casts to `isize`. However:
1185
- //
1186
- // 1. On 32-bit platforms, that will truncate 64-bit enums
1187
- // that are making use of the upper 32 bits, and
1188
- //
1189
- // 2. On all platforms, it will misinterpret the sign bit
1190
- // of a 64-bit enum.
1191
- //
1192
- // What it should do is lookup whether the enum has an
1193
- // repr-attribute and cast to that if necessary. But
1194
- // attributes are not yet available to this function.
1195
- let target_ty = cx. ty_ident ( sp, cx. ident_of ( "isize" ) ) ;
1220
+ let target_ty = cx. ty_ident ( sp, cx. ident_of ( target_type_name) ) ;
1196
1221
let variant_disr = cx. expr_cast ( sp, variant_value, target_ty) ;
1197
1222
let let_stmt = cx. stmt_let ( sp, false , ident, variant_disr) ;
1198
1223
index_let_stmts. push ( let_stmt) ;
0 commit comments