@@ -197,109 +197,37 @@ pub trait LayoutCalculator {
197197 None => VariantIdx :: new ( 0 ) ,
198198 } ;
199199
200- let is_struct = !is_enum ||
201- // Only one variant is present.
202- ( present_second. is_none ( ) &&
203- // Representation optimizations are allowed.
204- !repr. inhibit_enum_layout_opt ( ) ) ;
205- if is_struct {
206- // Struct, or univariant enum equivalent to a struct.
207- // (Typechecking will reject discriminant-sizing attrs.)
208-
209- let v = present_first;
210- let kind = if is_enum || variants[ v] . is_empty ( ) || always_sized {
211- StructKind :: AlwaysSized
212- } else {
213- StructKind :: MaybeUnsized
214- } ;
215-
216- let mut st = self . univariant ( dl, & variants[ v] , repr, kind) ?;
217- st. variants = Variants :: Single { index : v } ;
218-
219- if is_unsafe_cell {
220- let hide_niches = |scalar : & mut _ | match scalar {
221- Scalar :: Initialized { value, valid_range } => {
222- * valid_range = WrappingRange :: full ( value. size ( dl) )
223- }
224- // Already doesn't have any niches
225- Scalar :: Union { .. } => { }
226- } ;
227- match & mut st. abi {
228- Abi :: Uninhabited => { }
229- Abi :: Scalar ( scalar) => hide_niches ( scalar) ,
230- Abi :: ScalarPair ( a, b) => {
231- hide_niches ( a) ;
232- hide_niches ( b) ;
233- }
234- Abi :: Vector { element, count : _ } => hide_niches ( element) ,
235- Abi :: Aggregate { sized : _ } => { }
236- }
237- st. largest_niche = None ;
238- return Some ( st) ;
239- }
240-
241- let ( start, end) = scalar_valid_range;
242- match st. abi {
243- Abi :: Scalar ( ref mut scalar) | Abi :: ScalarPair ( ref mut scalar, _) => {
244- // Enlarging validity ranges would result in missed
245- // optimizations, *not* wrongly assuming the inner
246- // value is valid. e.g. unions already enlarge validity ranges,
247- // because the values may be uninitialized.
248- //
249- // Because of that we only check that the start and end
250- // of the range is representable with this scalar type.
251-
252- let max_value = scalar. size ( dl) . unsigned_int_max ( ) ;
253- if let Bound :: Included ( start) = start {
254- // FIXME(eddyb) this might be incorrect - it doesn't
255- // account for wrap-around (end < start) ranges.
256- assert ! ( start <= max_value, "{start} > {max_value}" ) ;
257- scalar. valid_range_mut ( ) . start = start;
258- }
259- if let Bound :: Included ( end) = end {
260- // FIXME(eddyb) this might be incorrect - it doesn't
261- // account for wrap-around (end < start) ranges.
262- assert ! ( end <= max_value, "{end} > {max_value}" ) ;
263- scalar. valid_range_mut ( ) . end = end;
264- }
265-
266- // Update `largest_niche` if we have introduced a larger niche.
267- let niche = Niche :: from_scalar ( dl, Size :: ZERO , * scalar) ;
268- if let Some ( niche) = niche {
269- match st. largest_niche {
270- Some ( largest_niche) => {
271- // Replace the existing niche even if they're equal,
272- // because this one is at a lower offset.
273- if largest_niche. available ( dl) <= niche. available ( dl) {
274- st. largest_niche = Some ( niche) ;
275- }
276- }
277- None => st. largest_niche = Some ( niche) ,
278- }
279- }
280- }
281- _ => assert ! (
282- start == Bound :: Unbounded && end == Bound :: Unbounded ,
283- "nonscalar layout for layout_scalar_valid_range type: {st:#?}" ,
284- ) ,
285- }
286-
287- return Some ( st) ;
200+ // take the struct path if it is an actual struct
201+ if !is_enum ||
202+ // or for optimizing univariant enums
203+ ( present_second. is_none ( ) && !repr. inhibit_enum_layout_opt ( ) )
204+ {
205+ layout_of_struct (
206+ self ,
207+ repr,
208+ variants,
209+ is_enum,
210+ is_unsafe_cell,
211+ scalar_valid_range,
212+ always_sized,
213+ dl,
214+ present_first,
215+ )
216+ } else {
217+ // At this point, we have handled all unions and
218+ // structs. (We have also handled univariant enums
219+ // that allow representation optimization.)
220+ assert ! ( is_enum) ;
221+ layout_of_enum (
222+ self ,
223+ repr,
224+ variants,
225+ discr_range_of_repr,
226+ discriminants,
227+ dont_niche_optimize_enum,
228+ dl,
229+ )
288230 }
289-
290- // At this point, we have handled all unions and
291- // structs. (We have also handled univariant enums
292- // that allow representation optimization.)
293- assert ! ( is_enum) ;
294- layout_of_enum (
295- self ,
296- repr,
297- variants,
298- discr_range_of_repr,
299- discriminants,
300- dont_niche_optimize_enum,
301- dl,
302- )
303231 }
304232
305233 fn layout_of_union <
@@ -407,6 +335,106 @@ pub trait LayoutCalculator {
407335 }
408336}
409337
338+ /// single-variant enums are just structs, if you think about it
339+ fn layout_of_struct < ' a , LC , FieldIdx : Idx , VariantIdx : Idx , F > (
340+ layout_calc : & LC ,
341+ repr : & ReprOptions ,
342+ variants : & IndexSlice < VariantIdx , IndexVec < FieldIdx , F > > ,
343+ is_enum : bool ,
344+ is_unsafe_cell : bool ,
345+ scalar_valid_range : ( Bound < u128 > , Bound < u128 > ) ,
346+ always_sized : bool ,
347+ dl : & TargetDataLayout ,
348+ present_first : VariantIdx ,
349+ ) -> Option < LayoutS < FieldIdx , VariantIdx > >
350+ where
351+ LC : LayoutCalculator + ?Sized ,
352+ F : Deref < Target = & ' a LayoutS < FieldIdx , VariantIdx > > + fmt:: Debug ,
353+ {
354+ // Struct, or univariant enum equivalent to a struct.
355+ // (Typechecking will reject discriminant-sizing attrs.)
356+
357+ let v = present_first;
358+ let kind = if is_enum || variants[ v] . is_empty ( ) || always_sized {
359+ StructKind :: AlwaysSized
360+ } else {
361+ StructKind :: MaybeUnsized
362+ } ;
363+
364+ let mut st = layout_calc. univariant ( dl, & variants[ v] , repr, kind) ?;
365+ st. variants = Variants :: Single { index : v } ;
366+
367+ if is_unsafe_cell {
368+ let hide_niches = |scalar : & mut _ | match scalar {
369+ Scalar :: Initialized { value, valid_range } => {
370+ * valid_range = WrappingRange :: full ( value. size ( dl) )
371+ }
372+ // Already doesn't have any niches
373+ Scalar :: Union { .. } => { }
374+ } ;
375+ match & mut st. abi {
376+ Abi :: Uninhabited => { }
377+ Abi :: Scalar ( scalar) => hide_niches ( scalar) ,
378+ Abi :: ScalarPair ( a, b) => {
379+ hide_niches ( a) ;
380+ hide_niches ( b) ;
381+ }
382+ Abi :: Vector { element, count : _ } => hide_niches ( element) ,
383+ Abi :: Aggregate { sized : _ } => { }
384+ }
385+ st. largest_niche = None ;
386+ return Some ( st) ;
387+ }
388+
389+ let ( start, end) = scalar_valid_range;
390+ match st. abi {
391+ Abi :: Scalar ( ref mut scalar) | Abi :: ScalarPair ( ref mut scalar, _) => {
392+ // Enlarging validity ranges would result in missed
393+ // optimizations, *not* wrongly assuming the inner
394+ // value is valid. e.g. unions already enlarge validity ranges,
395+ // because the values may be uninitialized.
396+ //
397+ // Because of that we only check that the start and end
398+ // of the range is representable with this scalar type.
399+
400+ let max_value = scalar. size ( dl) . unsigned_int_max ( ) ;
401+ if let Bound :: Included ( start) = start {
402+ // FIXME(eddyb) this might be incorrect - it doesn't
403+ // account for wrap-around (end < start) ranges.
404+ assert ! ( start <= max_value, "{start} > {max_value}" ) ;
405+ scalar. valid_range_mut ( ) . start = start;
406+ }
407+ if let Bound :: Included ( end) = end {
408+ // FIXME(eddyb) this might be incorrect - it doesn't
409+ // account for wrap-around (end < start) ranges.
410+ assert ! ( end <= max_value, "{end} > {max_value}" ) ;
411+ scalar. valid_range_mut ( ) . end = end;
412+ }
413+
414+ // Update `largest_niche` if we have introduced a larger niche.
415+ let niche = Niche :: from_scalar ( dl, Size :: ZERO , * scalar) ;
416+ if let Some ( niche) = niche {
417+ match st. largest_niche {
418+ Some ( largest_niche) => {
419+ // Replace the existing niche even if they're equal,
420+ // because this one is at a lower offset.
421+ if largest_niche. available ( dl) <= niche. available ( dl) {
422+ st. largest_niche = Some ( niche) ;
423+ }
424+ }
425+ None => st. largest_niche = Some ( niche) ,
426+ }
427+ }
428+ }
429+ _ => assert ! (
430+ start == Bound :: Unbounded && end == Bound :: Unbounded ,
431+ "nonscalar layout for layout_scalar_valid_range type: {st:#?}" ,
432+ ) ,
433+ }
434+
435+ Some ( st)
436+ }
437+
410438fn layout_of_enum < ' a , LC , FieldIdx : Idx , VariantIdx : Idx , F > (
411439 layout_calc : & LC ,
412440 repr : & ReprOptions ,
0 commit comments