@@ -427,6 +427,52 @@ impl DstLayout {
427427 }
428428 }
429429
430+ /// Constructs a `DstLayout` which describes a dynamically-sized type with
431+ /// the given properties.
432+ ///
433+ /// # Safety
434+ ///
435+ /// Unsafe code may assume that the returned `DstLayout` is the correct
436+ /// layout for the described type so long as:
437+ /// - The type has the alignment `align`
438+ /// - The type has at least one field
439+ /// - The byte offset of the first byte of the trailing field is equal to
440+ /// `trailing_field_offset`
441+ /// - The trailing field's layout is correctly described by
442+ /// `trailing_field_layout`
443+ const fn for_dst (
444+ align : NonZeroUsize ,
445+ trailing_field_offset : usize ,
446+ trailing_field_layout : DstLayout ,
447+ ) -> Option < DstLayout > {
448+ Some ( DstLayout {
449+ // SAFETY: The caller has promised that this is the correct
450+ // alignment.
451+ _align : align,
452+ _size_info : match trailing_field_layout. _size_info {
453+ SizeInfo :: Sized { _size } => {
454+ let without_padding = match trailing_field_offset. checked_add ( _size) {
455+ Some ( without_padding) => without_padding,
456+ None => return None ,
457+ } ;
458+
459+ let padding = util:: core_layout:: _padding_needed_for ( without_padding, align) ;
460+ // SAFETY: TODO
461+ SizeInfo :: Sized { _size : without_padding + padding }
462+ }
463+ SizeInfo :: SliceDst ( TrailingSliceLayout { _offset, _elem_size } ) => {
464+ let offset = match trailing_field_offset. checked_add ( _offset) {
465+ Some ( offset) => offset,
466+ None => return None ,
467+ } ;
468+
469+ // SAFETY: TODO
470+ SizeInfo :: SliceDst ( TrailingSliceLayout { _offset : offset, _elem_size } )
471+ }
472+ } ,
473+ } )
474+ }
475+
430476 /// Validates that a cast is sound from a layout perspective.
431477 ///
432478 /// Validates that the size and alignment requirements of a type with the
@@ -3684,6 +3730,20 @@ mod tests {
36843730 }
36853731 }
36863732
3733+ #[ test]
3734+ fn test_dst_layout_for_dst ( ) {
3735+ macro_rules! test {
3736+ ( $align: expr, $trailing_field_offset: expr, $trailing_field_layout: expr, $expect: expr) => { {
3737+ let align = NonZeroUsize :: new( $align) . unwrap( ) ;
3738+ let layout =
3739+ DstLayout :: for_dst( align, $trailing_field_offset, $trailing_field_layout) ;
3740+ assert_eq!( layout, $expect) ;
3741+ } } ;
3742+ }
3743+
3744+ // TODO: Write tests.
3745+ }
3746+
36873747 // This test takes a long time when running under Miri, so we skip it in
36883748 // that case. This is acceptable because this is a logic test that doesn't
36893749 // attempt to expose UB.
0 commit comments