@@ -2617,22 +2617,22 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
2617
2617
/// the occasional mistake, and this check should help them figure things out.
2618
2618
#[ allow_internal_unstable( const_eval_select, delayed_debug_assertions) ] // permit this to be called in stably-const fn
2619
2619
macro_rules! assert_unsafe_precondition {
2620
- ( $name : expr, ( $( $i : ident: $ty: ty) ,* $( , ) ?) => $e: expr $( , ) ?) => {
2620
+ ( $message : expr, ( $( $arg : expr => $name : ident: $ty: ty) ,* $( , ) ?) => $e: expr $( , ) ?) => {
2621
2621
{
2622
2622
#[ inline( never) ]
2623
- fn precondition_check( $( $i: $ty) ,* ) {
2623
+ #[ rustc_nounwind]
2624
+ fn precondition_check( $( $name: $ty) ,* ) {
2624
2625
if !$e {
2625
2626
:: core:: panicking:: panic_nounwind(
2626
- concat!( "unsafe precondition(s) violated: " , $name )
2627
+ concat!( "unsafe precondition(s) violated: " , $message )
2627
2628
) ;
2628
2629
}
2629
2630
}
2630
- #[ allow( non_snake_case) ]
2631
2631
#[ inline]
2632
2632
const fn comptime( $( _: $ty) ,* ) { }
2633
2633
2634
2634
if :: core:: intrinsics:: debug_assertions( ) {
2635
- :: core:: intrinsics:: const_eval_select( ( $( $i , ) * ) , comptime, precondition_check) ;
2635
+ :: core:: intrinsics:: const_eval_select( ( $( $arg , ) * ) , comptime, precondition_check) ;
2636
2636
}
2637
2637
}
2638
2638
} ;
@@ -2643,7 +2643,32 @@ pub(crate) use assert_unsafe_precondition;
2643
2643
/// `align_of::<T>()`.
2644
2644
#[ inline]
2645
2645
pub ( crate ) fn is_aligned_and_not_null ( ptr : * const ( ) , align : usize ) -> bool {
2646
- ptr. is_aligned_to ( align) && !ptr. is_null ( )
2646
+ !ptr. is_null ( ) && ptr. is_aligned_to ( align)
2647
+ }
2648
+
2649
+ #[ inline]
2650
+ pub ( crate ) fn is_valid_allocation_size ( size : usize , len : usize ) -> bool {
2651
+ let max_len = if size == 0 { usize:: MAX } else { isize:: MAX as usize / size } ;
2652
+ len <= max_len
2653
+ }
2654
+
2655
+ pub ( crate ) fn is_nonoverlapping_mono (
2656
+ src : * const ( ) ,
2657
+ dst : * const ( ) ,
2658
+ size : usize ,
2659
+ count : usize ,
2660
+ ) -> bool {
2661
+ let src_usize = src. addr ( ) ;
2662
+ let dst_usize = dst. addr ( ) ;
2663
+ let Some ( size) = size. checked_mul ( count) else {
2664
+ crate :: panicking:: panic_nounwind (
2665
+ "is_nonoverlapping: `size_of::<T>() * count` overflows a usize" ,
2666
+ )
2667
+ } ;
2668
+ let diff = src_usize. abs_diff ( dst_usize) ;
2669
+ // If the absolute distance between the ptrs is at least as big as the size of the buffer,
2670
+ // they do not overlap.
2671
+ diff >= size
2647
2672
}
2648
2673
2649
2674
/// Checks whether the regions of memory starting at `src` and `dst` of size
@@ -2755,70 +2780,31 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
2755
2780
#[ inline( always) ]
2756
2781
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
2757
2782
#[ rustc_diagnostic_item = "ptr_copy_nonoverlapping" ]
2758
- #[ rustc_allow_const_fn_unstable( const_eval_select) ]
2759
2783
pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
2760
2784
extern "rust-intrinsic" {
2761
2785
#[ rustc_const_stable( feature = "const_intrinsic_copy" , since = "1.63.0" ) ]
2762
2786
#[ rustc_nounwind]
2763
2787
pub fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) ;
2764
2788
}
2765
2789
2766
- const fn compiletime ( _: * const ( ) , _: * mut ( ) , _: usize , _: usize , _: usize ) { }
2767
-
2768
2790
// SAFETY: the safety contract for `copy_nonoverlapping` must be
2769
2791
// upheld by the caller.
2770
2792
unsafe {
2771
- if crate :: intrinsics:: debug_assertions ( ) {
2772
- const_eval_select (
2773
- (
2774
- src as * const ( ) ,
2775
- dst as * mut ( ) ,
2776
- crate :: mem:: size_of :: < T > ( ) ,
2777
- crate :: mem:: align_of :: < T > ( ) ,
2778
- count,
2779
- ) ,
2780
- compiletime,
2781
- check_aligned_nonoverlapping,
2782
- ) ;
2783
- }
2784
- copy_nonoverlapping ( src, dst, count)
2785
- }
2786
- }
2787
-
2788
- #[ inline( never) ]
2789
- pub ( crate ) fn check_aligned_nonoverlapping (
2790
- src : * const ( ) ,
2791
- dst : * mut ( ) ,
2792
- size : usize ,
2793
- align : usize ,
2794
- count : usize ,
2795
- ) {
2796
- if src. is_null ( ) || dst. is_null ( ) {
2797
- crate :: panicking:: panic_nounwind (
2798
- "ptr::copy_nonoverlapping requires that both pointer arguments are non-null" ,
2799
- ) ;
2800
- }
2801
- if !src. is_aligned_to ( align) || !dst. is_aligned_to ( align) {
2802
- crate :: panicking:: panic_nounwind (
2803
- "ptr::copy_nonoverlapping requires that both pointer arguments are aligned" ,
2804
- ) ;
2805
- }
2806
- let src_usize = src. addr ( ) ;
2807
- let dst_usize = dst. addr ( ) ;
2808
- let Some ( size) = size. checked_mul ( count) else {
2809
- crate :: panicking:: panic_nounwind (
2810
- "is_nonoverlapping: `size_of::<T>() * count` overflows a usize" ,
2811
- )
2812
- } ;
2813
- let diff = src_usize. abs_diff ( dst_usize) ;
2814
- // If the absolute distance between the ptrs is at least as big as the size of the buffer,
2815
- // they do not overlap.
2816
- let is_nonoverlapping = diff >= size;
2817
-
2818
- if !is_nonoverlapping {
2819
- crate :: panicking:: panic_nounwind (
2820
- "ptr::copy_nonoverlapping requires the specified memory ranges do not overlap" ,
2793
+ assert_unsafe_precondition ! (
2794
+ "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
2795
+ and the specified memory ranges do not overlap",
2796
+ (
2797
+ src as * const ( ) => src: * const ( ) ,
2798
+ dst as * mut ( ) => dst: * mut ( ) ,
2799
+ size_of:: <T >( ) => size: usize ,
2800
+ align_of:: <T >( ) => align: usize ,
2801
+ count => count: usize ,
2802
+ ) =>
2803
+ is_aligned_and_not_null( src, align)
2804
+ && is_aligned_and_not_null( dst, align)
2805
+ && is_nonoverlapping_mono( src, dst, size, count)
2821
2806
) ;
2807
+ copy_nonoverlapping ( src, dst, count)
2822
2808
}
2823
2809
}
2824
2810
@@ -2896,41 +2882,27 @@ pub(crate) fn check_aligned_nonoverlapping(
2896
2882
#[ inline( always) ]
2897
2883
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
2898
2884
#[ rustc_diagnostic_item = "ptr_copy" ]
2899
- #[ rustc_allow_const_fn_unstable( const_eval_select) ]
2900
2885
pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
2901
2886
extern "rust-intrinsic" {
2902
2887
#[ rustc_const_stable( feature = "const_intrinsic_copy" , since = "1.63.0" ) ]
2903
2888
#[ rustc_nounwind]
2904
2889
fn copy < T > ( src : * const T , dst : * mut T , count : usize ) ;
2905
2890
}
2906
2891
2907
- const fn compiletime ( _: * const ( ) , _: * mut ( ) , _: usize ) { }
2908
-
2909
2892
// SAFETY: the safety contract for `copy` must be upheld by the caller.
2910
2893
unsafe {
2911
- if crate :: intrinsics:: debug_assertions ( ) {
2912
- const_eval_select (
2913
- ( src as * const ( ) , dst as * mut ( ) , align_of :: < T > ( ) ) ,
2914
- compiletime,
2915
- check_valid_copy,
2916
- ) ;
2917
- }
2918
- copy ( src, dst, count)
2919
- }
2920
- }
2921
-
2922
- #[ inline( never) ]
2923
- #[ rustc_nounwind]
2924
- fn check_valid_copy ( src : * const ( ) , dst : * mut ( ) , align : usize ) {
2925
- if src. is_null ( ) || dst. is_null ( ) {
2926
- crate :: panicking:: panic_nounwind (
2927
- "ptr::copy requires that both pointer arguments are non-null" ,
2928
- ) ;
2929
- }
2930
- if !src. is_aligned_to ( align) || !dst. is_aligned_to ( align) {
2931
- crate :: panicking:: panic_nounwind (
2932
- "ptr::copy requires that both pointer arguments are aligned" ,
2894
+ assert_unsafe_precondition ! (
2895
+ "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
2896
+ and the specified memory ranges do not overlap",
2897
+ (
2898
+ src as * const ( ) => src: * const ( ) ,
2899
+ dst as * mut ( ) => dst: * mut ( ) ,
2900
+ align_of:: <T >( ) => align: usize ,
2901
+ ) =>
2902
+ is_aligned_and_not_null( src, align)
2903
+ && is_aligned_and_not_null( dst, align)
2933
2904
) ;
2905
+ copy ( src, dst, count)
2934
2906
}
2935
2907
}
2936
2908
@@ -2997,13 +2969,14 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
2997
2969
fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) ;
2998
2970
}
2999
2971
3000
- let addr = dst as * const ( ) ;
3001
- let align = align_of :: < T > ( ) ;
3002
2972
// SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
3003
2973
unsafe {
3004
2974
assert_unsafe_precondition ! (
3005
2975
"ptr::write_bytes requires that the destination pointer is aligned and non-null" ,
3006
- ( addr: * const ( ) , align: usize ) => is_aligned_and_not_null( addr, align)
2976
+ (
2977
+ dst as * const ( ) => addr: * const ( ) ,
2978
+ align_of:: <T >( ) => align: usize
2979
+ ) => is_aligned_and_not_null( addr, align)
3007
2980
) ;
3008
2981
write_bytes ( dst, val, count)
3009
2982
}
0 commit comments