@@ -25,6 +25,15 @@ impl<'c> Translation<'c> {
2525 . expect ( "Enums should already be renamed" ) ;
2626 let integral_type_rs = self . convert_type ( integral_type. ctype ) ?;
2727 let item = match self . tcfg . enum_mode {
28+ EnumMode :: NewType => {
29+ let field = mk ( ) . pub_ ( ) . enum_field ( integral_type_rs) ;
30+ mk ( ) . span ( span)
31+ . call_attr ( "derive" , vec ! [ "Clone" , "Copy" ] )
32+ . call_attr ( "repr" , vec ! [ "transparent" ] )
33+ . pub_ ( )
34+ . struct_item ( enum_name, vec ! [ field] , true )
35+ }
36+
2837 EnumMode :: Consts => mk ( )
2938 . span ( span)
3039 . pub_ ( )
@@ -51,16 +60,16 @@ impl<'c> Translation<'c> {
5160 . borrow ( )
5261 . resolve_decl_name ( enum_id)
5362 . expect ( "Enums should already be renamed" ) ;
54- self . add_import ( enum_id, & enum_name) ;
5563
5664 let ty = mk ( ) . ident_ty ( enum_name) ;
5765 let val = match value {
5866 ConstIntExpr :: I ( value) => signed_int_expr ( value) ,
5967 ConstIntExpr :: U ( value) => mk ( ) . lit_expr ( mk ( ) . int_unsuffixed_lit ( value as u128 ) ) ,
6068 } ;
69+ let init = self . enum_constructor_expr ( enum_id, val) ;
6170
6271 Ok ( ConvertedDecl :: Item (
63- mk ( ) . span ( span) . pub_ ( ) . const_item ( name, ty, val ) ,
72+ mk ( ) . span ( span) . pub_ ( ) . const_item ( name, ty, init ) ,
6473 ) )
6574 }
6675
@@ -88,8 +97,14 @@ impl<'c> Translation<'c> {
8897 ctx : ExprContext ,
8998 enum_id : CEnumId ,
9099 target_cty : CQualTypeId ,
91- val : Box < Expr > ,
100+ mut val : Box < Expr > ,
92101 ) -> TranslationResult < WithStmts < Box < Expr > > > {
102+ match self . tcfg . enum_mode {
103+ // First extract the enum's inner type...
104+ EnumMode :: NewType => val = self . integer_from_enum ( val) ,
105+ EnumMode :: Consts => { }
106+ }
107+
93108 // Cast from the enum's integral type to the expected integral type.
94109 let source_cty = self . enum_integral_type ( enum_id) ;
95110 self . convert_cast (
@@ -103,12 +118,15 @@ impl<'c> Translation<'c> {
103118 )
104119 }
105120
106- /// Translate a cast where the target type is an `enum` type.
107- ///
108- /// When translating variable references to `EnumConstant`s, we always insert casts to the
109- /// expected type. In C, `EnumConstant`s have some integral type, _not_ the enum type. However,
110- /// if we then immediately have a cast to convert this variable back into an enum type, we would
111- /// like to produce Rust with _no_ casts. This function handles this simplification.
121+ /// Gets the inner integral value of an enum value.
122+ pub fn integer_from_enum ( & self , val : Box < Expr > ) -> Box < Expr > {
123+ match self . tcfg . enum_mode {
124+ EnumMode :: NewType => mk ( ) . anon_field_expr ( val, 0 ) ,
125+ EnumMode :: Consts => val,
126+ }
127+ }
128+
129+ /// Translates a cast where the target type is an `enum` type.
112130 pub fn convert_cast_to_enum (
113131 & self ,
114132 ctx : ExprContext ,
@@ -163,13 +181,23 @@ impl<'c> Translation<'c> {
163181 return Ok ( WithStmts :: new_val ( val) ) ;
164182 }
165183
184+ match self . tcfg . enum_mode {
185+ // Enum-to-enum casts need to be translated via the inner value as an intermediate.
186+ EnumMode :: NewType => val = self . integer_from_enum ( val) ,
187+ EnumMode :: Consts => { }
188+ }
189+
166190 source_cty = self . enum_integral_type ( source_enum_id) ;
167191 }
168192
169193 let enum_integral_type = self . enum_integral_type ( enum_id) ;
170194 let mut val = WithStmts :: new_val ( val) ;
171195
172196 match self . tcfg . enum_mode {
197+ EnumMode :: NewType => {
198+ val = val. map ( |val| self . enum_constructor_expr ( enum_id, val) ) ;
199+ }
200+
173201 EnumMode :: Consts => {
174202 let source_type_kind = & self . ast_context . resolve_type ( source_cty. ctype ) . kind ;
175203 let enum_integral_type_kind =
@@ -234,6 +262,7 @@ impl<'c> Translation<'c> {
234262 self . add_import ( enum_id, & enum_name) ;
235263
236264 match self . tcfg . enum_mode {
265+ EnumMode :: NewType => mk ( ) . call_expr ( mk ( ) . ident_expr ( enum_name) , vec ! [ value] ) ,
237266 EnumMode :: Consts => mk ( ) . cast_expr ( value, mk ( ) . ident_ty ( enum_name) ) ,
238267 }
239268 }
0 commit comments