@@ -485,7 +485,9 @@ impl String {
485485 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
486486 #[ must_use]
487487 pub fn with_capacity ( capacity : usize ) -> String {
488- String { vec : Vec :: with_capacity ( capacity) }
488+ String {
489+ vec : Vec :: with_capacity ( capacity) ,
490+ }
489491 }
490492
491493 /// Creates a new empty `String` with at least the specified capacity.
@@ -498,7 +500,9 @@ impl String {
498500 #[ inline]
499501 #[ unstable( feature = "try_with_capacity" , issue = "91913" ) ]
500502 pub fn try_with_capacity ( capacity : usize ) -> Result < String , TryReserveError > {
501- Ok ( String { vec : Vec :: try_with_capacity ( capacity) ? } )
503+ Ok ( String {
504+ vec : Vec :: try_with_capacity ( capacity) ?,
505+ } )
502506 }
503507
504508 /// Converts a vector of bytes to a `String`.
@@ -563,7 +567,10 @@ impl String {
563567 pub fn from_utf8 ( vec : Vec < u8 > ) -> Result < String , FromUtf8Error > {
564568 match str:: from_utf8 ( & vec) {
565569 Ok ( ..) => Ok ( String { vec } ) ,
566- Err ( e) => Err ( FromUtf8Error { bytes : vec, error : e } ) ,
570+ Err ( e) => Err ( FromUtf8Error {
571+ bytes : vec,
572+ error : e,
573+ } ) ,
567574 }
568575 }
569576
@@ -790,7 +797,9 @@ impl String {
790797 let ( chunks, [ ] ) = v. as_chunks :: < 2 > ( ) else {
791798 return Err ( FromUtf16Error ( ( ) ) ) ;
792799 } ;
793- match ( cfg ! ( target_endian = "little" ) , unsafe { v. align_to :: < u16 > ( ) } ) {
800+ match ( cfg ! ( target_endian = "little" ) , unsafe {
801+ v. align_to :: < u16 > ( )
802+ } ) {
794803 ( true , ( [ ] , v, [ ] ) ) => Self :: from_utf16 ( v) ,
795804 _ => char:: decode_utf16 ( chunks. iter ( ) . copied ( ) . map ( u16:: from_le_bytes) )
796805 . collect :: < Result < _ , _ > > ( )
@@ -826,15 +835,21 @@ impl String {
826835 #[ cfg( not( no_global_oom_handling) ) ]
827836 #[ unstable( feature = "str_from_utf16_endian" , issue = "116258" ) ]
828837 pub fn from_utf16le_lossy ( v : & [ u8 ] ) -> String {
829- match ( cfg ! ( target_endian = "little" ) , unsafe { v. align_to :: < u16 > ( ) } ) {
838+ match ( cfg ! ( target_endian = "little" ) , unsafe {
839+ v. align_to :: < u16 > ( )
840+ } ) {
830841 ( true , ( [ ] , v, [ ] ) ) => Self :: from_utf16_lossy ( v) ,
831842 ( true , ( [ ] , v, [ _remainder] ) ) => Self :: from_utf16_lossy ( v) + "\u{FFFD} " ,
832843 _ => {
833844 let ( chunks, remainder) = v. as_chunks :: < 2 > ( ) ;
834845 let string = char:: decode_utf16 ( chunks. iter ( ) . copied ( ) . map ( u16:: from_le_bytes) )
835846 . map ( |r| r. unwrap_or ( char:: REPLACEMENT_CHARACTER ) )
836847 . collect ( ) ;
837- if remainder. is_empty ( ) { string } else { string + "\u{FFFD} " }
848+ if remainder. is_empty ( ) {
849+ string
850+ } else {
851+ string + "\u{FFFD} "
852+ }
838853 }
839854 }
840855 }
@@ -909,7 +924,11 @@ impl String {
909924 let string = char:: decode_utf16 ( chunks. iter ( ) . copied ( ) . map ( u16:: from_be_bytes) )
910925 . map ( |r| r. unwrap_or ( char:: REPLACEMENT_CHARACTER ) )
911926 . collect ( ) ;
912- if remainder. is_empty ( ) { string } else { string + "\u{FFFD} " }
927+ if remainder. is_empty ( ) {
928+ string
929+ } else {
930+ string + "\u{FFFD} "
931+ }
913932 }
914933 }
915934 }
@@ -992,7 +1011,11 @@ impl String {
9921011 #[ inline]
9931012 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
9941013 pub unsafe fn from_raw_parts ( buf : * mut u8 , length : usize , capacity : usize ) -> String {
995- unsafe { String { vec : Vec :: from_raw_parts ( buf, length, capacity) } }
1014+ unsafe {
1015+ String {
1016+ vec : Vec :: from_raw_parts ( buf, length, capacity) ,
1017+ }
1018+ }
9961019 }
9971020
9981021 /// Converts a vector of bytes to a `String` without checking that the
@@ -1524,7 +1547,11 @@ impl String {
15241547 let next = idx + ch. len_utf8 ( ) ;
15251548 let len = self . len ( ) ;
15261549 unsafe {
1527- ptr:: copy ( self . vec . as_ptr ( ) . add ( next) , self . vec . as_mut_ptr ( ) . add ( idx) , len - next) ;
1550+ ptr:: copy (
1551+ self . vec . as_ptr ( ) . add ( next) ,
1552+ self . vec . as_mut_ptr ( ) . add ( idx) ,
1553+ len - next,
1554+ ) ;
15281555 self . vec . set_len ( len - ( next - idx) ) ;
15291556 }
15301557 ch
@@ -1574,7 +1601,9 @@ impl String {
15741601 Some ( ( prev_front, start) )
15751602 } )
15761603 . collect ( ) ;
1577- rejections. into_iter ( ) . chain ( core:: iter:: once ( ( front, self . len ( ) ) ) )
1604+ rejections
1605+ . into_iter ( )
1606+ . chain ( core:: iter:: once ( ( front, self . len ( ) ) ) )
15781607 } ;
15791608
15801609 let mut len = 0 ;
@@ -1648,7 +1677,11 @@ impl String {
16481677 }
16491678
16501679 let len = self . len ( ) ;
1651- let mut guard = SetLenOnDrop { s : self , idx : 0 , del_bytes : 0 } ;
1680+ let mut guard = SetLenOnDrop {
1681+ s : self ,
1682+ idx : 0 ,
1683+ del_bytes : 0 ,
1684+ } ;
16521685
16531686 while guard. idx < len {
16541687 let ch =
@@ -1779,7 +1812,11 @@ impl String {
17791812 // ahead. This is safe because sufficient capacity was just reserved, and `idx`
17801813 // is a char boundary.
17811814 unsafe {
1782- ptr:: copy ( self . vec . as_ptr ( ) . add ( idx) , self . vec . as_mut_ptr ( ) . add ( idx + amt) , len - idx) ;
1815+ ptr:: copy (
1816+ self . vec . as_ptr ( ) . add ( idx) ,
1817+ self . vec . as_mut_ptr ( ) . add ( idx + amt) ,
1818+ len - idx,
1819+ ) ;
17831820 }
17841821
17851822 // SAFETY: Copy the new string slice into the vacated region if `idx != len`,
@@ -1980,7 +2017,12 @@ impl String {
19802017 // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks.
19812018 let chars_iter = unsafe { self . get_unchecked ( start..end) } . chars ( ) ;
19822019
1983- Drain { start, end, iter : chars_iter, string : self_ptr }
2020+ Drain {
2021+ start,
2022+ end,
2023+ iter : chars_iter,
2024+ string : self_ptr,
2025+ }
19842026 }
19852027
19862028 /// Converts a `String` into an iterator over the [`char`]s of the string.
@@ -2035,7 +2077,9 @@ impl String {
20352077 #[ must_use = "`self` will be dropped if the result is not used" ]
20362078 #[ unstable( feature = "string_into_chars" , issue = "133125" ) ]
20372079 pub fn into_chars ( self ) -> IntoChars {
2038- IntoChars { bytes : self . into_bytes ( ) . into_iter ( ) }
2080+ IntoChars {
2081+ bytes : self . into_bytes ( ) . into_iter ( ) ,
2082+ }
20392083 }
20402084
20412085 /// Removes the specified range in the string,
@@ -2287,7 +2331,9 @@ impl Error for FromUtf16Error {}
22872331#[ stable( feature = "rust1" , since = "1.0.0" ) ]
22882332impl Clone for String {
22892333 fn clone ( & self ) -> Self {
2290- String { vec : self . vec . clone ( ) }
2334+ String {
2335+ vec : self . vec . clone ( ) ,
2336+ }
22912337 }
22922338
22932339 /// Clones the contents of `source` into `self`.
@@ -3488,3 +3534,192 @@ impl From<char> for String {
34883534 c. to_string ( )
34893535 }
34903536}
3537+
3538+ #[ cfg( kani) ]
3539+ #[ unstable( feature = "kani" , issue = "none" ) ]
3540+ mod verify {
3541+ use super :: * ;
3542+ use core:: kani;
3543+
3544+ /// Helper: create a symbolic ASCII string of arbitrary length up to N bytes.
3545+ /// All bytes are constrained to be valid ASCII (0..=127), ensuring valid UTF-8.
3546+ fn any_ascii_string < const N : usize > ( ) -> String {
3547+ let mut bytes: [ u8 ; N ] = kani:: any ( ) ;
3548+ let len: usize = kani:: any ( ) ;
3549+ kani:: assume ( len <= N ) ;
3550+ // Constrain all active bytes to ASCII range for valid UTF-8
3551+ for i in 0 ..N {
3552+ if i < len {
3553+ kani:: assume ( bytes[ i] <= 127 ) ;
3554+ }
3555+ }
3556+ unsafe { String :: from_utf8_unchecked ( bytes[ ..len] . to_vec ( ) ) }
3557+ }
3558+
3559+ // ---- from_utf16le ----
3560+
3561+ #[ kani:: proof]
3562+ #[ kani:: unwind( 6 ) ]
3563+ fn check_from_utf16le ( ) {
3564+ let bytes: [ u8 ; 8 ] = kani:: any ( ) ;
3565+ let len: usize = kani:: any ( ) ;
3566+ kani:: assume ( len <= 8 ) ;
3567+ let _ = String :: from_utf16le ( & bytes[ ..len] ) ;
3568+ }
3569+
3570+ // ---- from_utf16le_lossy ----
3571+
3572+ #[ kani:: proof]
3573+ #[ kani:: unwind( 6 ) ]
3574+ fn check_from_utf16le_lossy ( ) {
3575+ let bytes: [ u8 ; 8 ] = kani:: any ( ) ;
3576+ let len: usize = kani:: any ( ) ;
3577+ kani:: assume ( len <= 8 ) ;
3578+ let _ = String :: from_utf16le_lossy ( & bytes[ ..len] ) ;
3579+ }
3580+
3581+ // ---- from_utf16be ----
3582+
3583+ #[ kani:: proof]
3584+ #[ kani:: unwind( 6 ) ]
3585+ fn check_from_utf16be ( ) {
3586+ let bytes: [ u8 ; 8 ] = kani:: any ( ) ;
3587+ let len: usize = kani:: any ( ) ;
3588+ kani:: assume ( len <= 8 ) ;
3589+ let _ = String :: from_utf16be ( & bytes[ ..len] ) ;
3590+ }
3591+
3592+ // ---- from_utf16be_lossy ----
3593+
3594+ #[ kani:: proof]
3595+ #[ kani:: unwind( 6 ) ]
3596+ fn check_from_utf16be_lossy ( ) {
3597+ let bytes: [ u8 ; 8 ] = kani:: any ( ) ;
3598+ let len: usize = kani:: any ( ) ;
3599+ kani:: assume ( len <= 8 ) ;
3600+ let _ = String :: from_utf16be_lossy ( & bytes[ ..len] ) ;
3601+ }
3602+
3603+ // ---- pop ----
3604+
3605+ #[ kani:: proof]
3606+ #[ kani:: unwind( 6 ) ]
3607+ fn check_pop ( ) {
3608+ let s = any_ascii_string :: < 4 > ( ) ;
3609+ let mut s = s;
3610+ let _ = s. pop ( ) ;
3611+ }
3612+
3613+ // ---- remove ----
3614+
3615+ #[ kani:: proof]
3616+ #[ kani:: unwind( 6 ) ]
3617+ fn check_str_remove ( ) {
3618+ let mut s = String :: from ( "abcd" ) ;
3619+ let idx: usize = kani:: any ( ) ;
3620+ kani:: assume ( idx < s. len ( ) ) ;
3621+ let _ = s. remove ( idx) ;
3622+ }
3623+
3624+ // ---- remove_matches ----
3625+
3626+ #[ kani:: proof]
3627+ #[ kani:: unwind( 6 ) ]
3628+ fn check_remove_matches ( ) {
3629+ let mut s = String :: from ( "abca" ) ;
3630+ s. remove_matches ( 'a' ) ;
3631+ }
3632+
3633+ // ---- retain ----
3634+
3635+ #[ kani:: proof]
3636+ #[ kani:: unwind( 6 ) ]
3637+ fn check_retain ( ) {
3638+ let mut s = String :: from ( "axbx" ) ;
3639+ s. retain ( |c| c != 'x' ) ;
3640+ }
3641+
3642+ // ---- insert ----
3643+
3644+ #[ kani:: proof]
3645+ #[ kani:: unwind( 6 ) ]
3646+ fn check_insert ( ) {
3647+ let mut s = any_ascii_string :: < 4 > ( ) ;
3648+ let len = s. len ( ) ;
3649+ let idx: usize = kani:: any ( ) ;
3650+ kani:: assume ( idx <= len) ;
3651+ // Insert an ASCII char (valid UTF-8, 1-byte)
3652+ s. insert ( idx, 'z' ) ;
3653+ }
3654+
3655+ // ---- insert_str ----
3656+
3657+ #[ kani:: proof]
3658+ #[ kani:: unwind( 6 ) ]
3659+ fn check_insert_str ( ) {
3660+ let mut s = any_ascii_string :: < 4 > ( ) ;
3661+ let len = s. len ( ) ;
3662+ let idx: usize = kani:: any ( ) ;
3663+ kani:: assume ( idx <= len) ;
3664+ s. insert_str ( idx, "hi" ) ;
3665+ }
3666+
3667+ // ---- split_off ----
3668+
3669+ #[ kani:: proof]
3670+ #[ kani:: unwind( 6 ) ]
3671+ fn check_split_off ( ) {
3672+ let mut s = any_ascii_string :: < 4 > ( ) ;
3673+ let len = s. len ( ) ;
3674+ let at: usize = kani:: any ( ) ;
3675+ kani:: assume ( at <= len) ;
3676+ let _ = s. split_off ( at) ;
3677+ }
3678+
3679+ // ---- drain ----
3680+
3681+ #[ kani:: proof]
3682+ #[ kani:: unwind( 6 ) ]
3683+ fn check_drain ( ) {
3684+ let mut s = any_ascii_string :: < 4 > ( ) ;
3685+ let len = s. len ( ) ;
3686+ let start: usize = kani:: any ( ) ;
3687+ let end: usize = kani:: any ( ) ;
3688+ kani:: assume ( start <= end) ;
3689+ kani:: assume ( end <= len) ;
3690+ // ASCII: every index is a char boundary
3691+ let _ = s. drain ( start..end) ;
3692+ }
3693+
3694+ // ---- replace_range ----
3695+
3696+ #[ kani:: proof]
3697+ #[ kani:: unwind( 6 ) ]
3698+ fn check_replace_range ( ) {
3699+ let mut s = any_ascii_string :: < 4 > ( ) ;
3700+ let len = s. len ( ) ;
3701+ let start: usize = kani:: any ( ) ;
3702+ let end: usize = kani:: any ( ) ;
3703+ kani:: assume ( start <= end) ;
3704+ kani:: assume ( end <= len) ;
3705+ s. replace_range ( start..end, "ok" ) ;
3706+ }
3707+
3708+ // ---- into_boxed_str ----
3709+
3710+ #[ kani:: proof]
3711+ #[ kani:: unwind( 6 ) ]
3712+ fn check_into_boxed_str ( ) {
3713+ let s = any_ascii_string :: < 4 > ( ) ;
3714+ let _ = s. into_boxed_str ( ) ;
3715+ }
3716+
3717+ // ---- leak ----
3718+
3719+ #[ kani:: proof]
3720+ #[ kani:: unwind( 6 ) ]
3721+ fn check_leak ( ) {
3722+ let s = any_ascii_string :: < 4 > ( ) ;
3723+ let _ = s. leak ( ) ;
3724+ }
3725+ }
0 commit comments