@@ -183,8 +183,18 @@ impl ReprOptions {
183183
184184    /// Returns the discriminant type, given these `repr` options. 
185185/// This must only be called on enums! 
186- pub  fn  discr_type ( & self )  -> IntegerType  { 
187-         self . int . unwrap_or ( IntegerType :: Pointer ( true ) ) 
186+ /// 
187+ /// This is the "typeck type" of the discriminant, which is effectively the maximum size: 
188+ /// discriminant values will be wrapped to fit (with a lint). Layout can later decide to use a 
189+ /// smaller type (which it will do depending on the actual discriminant values, also enforcing 
190+ /// `c_enum_min_size` along the way) and that will work just fine, it just induces casts when 
191+ /// getting/setting the discriminant. 
192+ pub  fn  discr_type ( & self ,  cx :  & impl  HasDataLayout )  -> IntegerType  { 
193+         self . int . unwrap_or ( if  self . c ( )  { 
194+             IntegerType :: Fixed ( cx. data_layout ( ) . c_enum_max_size ,  true ) 
195+         }  else  { 
196+             IntegerType :: Pointer ( true ) 
197+         } ) 
188198    } 
189199
190200    /// Returns `true` if this `#[repr()]` should inhabit "smart enum 
@@ -274,6 +284,8 @@ pub struct TargetDataLayout {
274284/// Note: This isn't in LLVM's data layout string, it is `short_enum` 
275285/// so the only valid spec for LLVM is c_int::BITS or 8 
276286pub  c_enum_min_size :  Integer , 
287+     /// Maximum size of #[repr(C)] enums (defaults to c_longlong::BITS, which is always 64). 
288+ pub  c_enum_max_size :  Integer , 
277289} 
278290
279291impl  Default  for  TargetDataLayout  { 
@@ -307,6 +319,10 @@ impl Default for TargetDataLayout {
307319            address_space_info :  vec ! [ ] , 
308320            instruction_address_space :  AddressSpace :: ZERO , 
309321            c_enum_min_size :  Integer :: I32 , 
322+             // C23 allows enums to have any integer type. The largest integer type in the standard 
323+             // is `long long`, which is always 64bits (judging from our own definition in 
324+             // `library/core/src/ffi/primitives.rs`). 
325+             c_enum_max_size :  Integer :: I64 , 
310326        } 
311327    } 
312328} 
@@ -327,7 +343,7 @@ impl TargetDataLayout {
327343/// [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout) 
328344/// 
329345/// This function doesn't fill `c_enum_min_size` and it will always be `I32` since it can not be 
330- /// determined from llvm string. 
346+ /// determined from llvm string. Likewise, it does not fill in `c_enum_max_size`.  
331347pub  fn  parse_from_llvm_datalayout_string < ' a > ( 
332348        input :  & ' a  str , 
333349        default_address_space :  AddressSpace , 
0 commit comments