@@ -183,8 +183,22 @@ 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 (
194+ if self . c ( )
195+ && let Some ( max_size) = cx. data_layout ( ) . c_enum_max_size
196+ {
197+ IntegerType :: Fixed ( max_size, true )
198+ } else {
199+ IntegerType :: Pointer ( true )
200+ } ,
201+ )
188202 }
189203
190204 /// Returns `true` if this `#[repr()]` should inhabit "smart enum
@@ -274,6 +288,8 @@ pub struct TargetDataLayout {
274288 /// Note: This isn't in LLVM's data layout string, it is `short_enum`
275289 /// so the only valid spec for LLVM is c_int::BITS or 8
276290 pub c_enum_min_size : Integer ,
291+ /// Maximum size of #[repr(C)] enums (defaults to pointer size).
292+ pub c_enum_max_size : Option < Integer > ,
277293}
278294
279295impl Default for TargetDataLayout {
@@ -307,6 +323,7 @@ impl Default for TargetDataLayout {
307323 address_space_info : vec ! [ ] ,
308324 instruction_address_space : AddressSpace :: ZERO ,
309325 c_enum_min_size : Integer :: I32 ,
326+ c_enum_max_size : None ,
310327 }
311328 }
312329}
@@ -327,7 +344,7 @@ impl TargetDataLayout {
327344 /// [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout)
328345 ///
329346 /// 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.
347+ /// determined from llvm string. Likewise, it does not fill in `c_enum_max_size`.
331348 pub fn parse_from_llvm_datalayout_string < ' a > (
332349 input : & ' a str ,
333350 default_address_space : AddressSpace ,
0 commit comments