diff --git a/RELEASES.md b/RELEASES.md index 1dd3fbea6136f..da53c946f0004 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1735,7 +1735,7 @@ Stabilized APIs - [`impl Sync for mpsc::Sender`](https://doc.rust-lang.org/stable/std/sync/mpsc/struct.Sender.html#impl-Sync-for-Sender%3CT%3E) - [`impl TryFrom<&OsStr> for &str`](https://doc.rust-lang.org/stable/std/primitive.str.html#impl-TryFrom%3C%26'a+OsStr%3E-for-%26'a+str) -- [`String::leak`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.leak) +- [`String::leak`](https://doc.rust-lang.org/stable/alloc/string/type.String.html#method.leak) These APIs are now stable in const contexts: @@ -3794,8 +3794,8 @@ and related tools. [`collections::TryReserveError`]: https://doc.rust-lang.org/std/collections/struct.TryReserveError.html [`HashMap::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.try_reserve [`HashSet::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.try_reserve -[`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve -[`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve_exact +[`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/type.String.html#method.try_reserve +[`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/type.String.html#method.try_reserve_exact [`Vec::try_reserve`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve [`Vec::try_reserve_exact`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact [`VecDeque::try_reserve`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve @@ -3936,7 +3936,7 @@ and related tools. [`BufWriter::into_parts`]: https://doc.rust-lang.org/stable/std/io/struct.BufWriter.html#method.into_parts [`core::panic::{UnwindSafe, RefUnwindSafe, AssertUnwindSafe}`]: https://github.com/rust-lang/rust/pull/84662 [`Vec::shrink_to`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.shrink_to -[`String::shrink_to`]: https://doc.rust-lang.org/stable/std/string/struct.String.html#method.shrink_to +[`String::shrink_to`]: https://doc.rust-lang.org/stable/std/string/type.String.html#method.shrink_to [`OsString::shrink_to`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.shrink_to [`PathBuf::shrink_to`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.shrink_to [`BinaryHeap::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/struct.BinaryHeap.html#method.shrink_to @@ -8131,7 +8131,7 @@ Compatibility Notes [`Iterator::try_for_each`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_for_each [`NonNull::cast`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.cast [`Option::filter`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.filter -[`String::replace_range`]: https://doc.rust-lang.org/std/string/struct.String.html#method.replace_range +[`String::replace_range`]: https://doc.rust-lang.org/std/string/type.String.html#method.replace_range [`Take::set_limit`]: https://doc.rust-lang.org/std/io/struct.Take.html#method.set_limit [`hint::unreachable_unchecked`]: https://doc.rust-lang.org/std/hint/fn.unreachable_unchecked.html [`os::unix::process::parent_id`]: https://doc.rust-lang.org/std/os/unix/process/fn.parent_id.html @@ -8376,7 +8376,7 @@ Compatibility Notes [`process::id`]: https://doc.rust-lang.org/std/process/fn.id.html [`slice::rotate_left`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_left [`slice::rotate_right`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_right -[`String::retain`]: https://doc.rust-lang.org/std/string/struct.String.html#method.retain +[`String::retain`]: https://doc.rust-lang.org/std/string/type.String.html#method.retain [cargo/5041]: https://github.com/rust-lang/cargo/pull/5041 [cargo/5083]: https://github.com/rust-lang/cargo/pull/5083 @@ -9827,8 +9827,8 @@ Compatibility Notes [`Result::unwrap_or_default`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_default [`SocketAddr::is_ipv4`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html#method.is_ipv4 [`SocketAddr::is_ipv6`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html#method.is_ipv6 -[`String::insert_str`]: https://doc.rust-lang.org/std/string/struct.String.html#method.insert_str -[`String::split_off`]: https://doc.rust-lang.org/std/string/struct.String.html#method.split_off +[`String::insert_str`]: https://doc.rust-lang.org/std/string/type.String.html#method.insert_str +[`String::split_off`]: https://doc.rust-lang.org/std/string/type.String.html#method.split_off [`Vec::dedup_by_key`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup_by_key [`Vec::dedup_by`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup_by [`VecDeque::resize`]: https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.resize @@ -11742,8 +11742,8 @@ Compatibility Notes [`Ipv6Addr::is_unspecified`]: http://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#method.is_unspecified [`Path::strip_prefix`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.strip_prefix [`RandomState::new`]: http://doc.rust-lang.org/nightly/std/collections/hash_map/struct.RandomState.html#method.new -[`String::as_mut_str`]: http://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_str -[`String::as_str`]: http://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_str +[`String::as_mut_str`]: http://doc.rust-lang.org/nightly/std/string/type.String.html#method.as_mut_str +[`String::as_str`]: http://doc.rust-lang.org/nightly/std/string/type.String.html#method.as_str [`Vec::as_mut_slice`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_slice [`Vec::as_slice`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_slice [`clone_from_slice`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.clone_from_slice @@ -11929,7 +11929,7 @@ Compatibility Notes [`os::unix::fs::DirBuilderExt::mode`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.DirBuilderExt.html#tymethod.mode [`os::unix::fs::DirBuilderExt`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.DirBuilderExt.html [`string::Drain`]: http://doc.rust-lang.org/nightly/std/string/struct.Drain.html -[`string::String::drain`]: http://doc.rust-lang.org/nightly/std/string/struct.String.html#method.drain +[`string::String::drain`]: http://doc.rust-lang.org/nightly/std/string/type.String.html#method.drain [`vec::Drain`]: http://doc.rust-lang.org/nightly/std/vec/struct.Drain.html [`vec::Vec::drain`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.drain [`vec_deque::Drain`]: http://doc.rust-lang.org/nightly/std/collections/vec_deque/struct.Drain.html diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 57679d595da3e..e4b0cf93e5a4d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1563,7 +1563,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } }; - let mut bad_struct_syntax_suggestion = |this: &mut Self, def_id: DefId| { + let bad_struct_syntax_suggestion = |this: &mut Self, err: &mut Diag<'_>, def_id: DefId| { let (followed_by_brace, closing_brace) = this.followed_by_brace(span); match source { @@ -1737,12 +1737,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } ( - Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _), + Res::Def(kind @ (DefKind::Mod | DefKind::Trait | DefKind::TyAlias), _), PathSource::Expr(Some(parent)), - ) => { - if !path_sep(self, err, parent, kind) { - return false; - } + ) if path_sep(self, err, parent, kind) => { + return true; } ( Res::Def(DefKind::Enum, def_id), @@ -1774,13 +1772,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor { if let PathSource::Expr(Some(parent)) = source { if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind { - bad_struct_syntax_suggestion(self, def_id); + bad_struct_syntax_suggestion(self, err, def_id); return true; } } struct_ctor } else { - bad_struct_syntax_suggestion(self, def_id); + bad_struct_syntax_suggestion(self, err, def_id); return true; }; @@ -1858,7 +1856,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.span_label(span, "constructor is not visible here due to private fields"); } (Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => { - bad_struct_syntax_suggestion(self, def_id); + bad_struct_syntax_suggestion(self, err, def_id); } (Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => { match source { diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 8b38e6fc259af..55ff69d00c9b6 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1848,11 +1848,23 @@ impl Clone for Box<[T], A> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_slice_clone", since = "1.3.0")] -impl Clone for Box { +impl Clone for Box { fn clone(&self) -> Self { - // this makes a copy of the data - let buf: Box<[u8]> = self.as_bytes().into(); - unsafe { from_boxed_utf8_unchecked(buf) } + let alloc = Box::allocator(self).clone(); + let len = self.len(); + let buf = RawVec::with_capacity_in(len, alloc); + unsafe { + ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len); + from_boxed_utf8_unchecked(buf.into_box(len).assume_init()) + } + } + + fn clone_from(&mut self, other: &Self) { + if self.len() == other.len() { + unsafe { self.as_bytes_mut().copy_from_slice(other.as_bytes()) } + } else { + *self = other.clone(); + } } } diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 6fee8d3fe3346..de5be9dd1080c 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -49,10 +49,11 @@ pub use core::str::{from_raw_parts, from_raw_parts_mut}; use core::unicode::conversions; use core::{mem, ptr}; +use crate::alloc::{Allocator, Global}; use crate::borrow::ToOwned; use crate::boxed::Box; use crate::slice::{Concat, Join, SliceIndex}; -use crate::string::String; +use crate::string::string::String; use crate::vec::Vec; /// Note: `str` in `Concat` is not meaningful here. @@ -186,7 +187,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Borrow for String { +impl Borrow for String { #[inline] fn borrow(&self) -> &str { &self[..] @@ -194,7 +195,7 @@ impl Borrow for String { } #[stable(feature = "string_borrow_mut", since = "1.36.0")] -impl BorrowMut for String { +impl BorrowMut for String { #[inline] fn borrow_mut(&mut self) -> &mut str { &mut self[..] @@ -235,7 +236,7 @@ impl str { #[stable(feature = "str_box_extras", since = "1.20.0")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] - pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { + pub fn into_boxed_bytes(self: Box) -> Box<[u8], A> { self.into() } @@ -502,8 +503,8 @@ impl str { #[rustc_allow_incoherent_impl] #[must_use = "`self` will be dropped if the result is not used"] #[inline] - pub fn into_string(self: Box) -> String { - let slice = Box::<[u8]>::from(self); + pub fn into_string(self: Box) -> String { + let slice = Box::<[u8], A>::from(self); unsafe { String::from_utf8_unchecked(slice.into_vec()) } } @@ -615,8 +616,9 @@ impl str { #[stable(feature = "str_box_extras", since = "1.20.0")] #[must_use] #[inline] -pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { - unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } +pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8], A>) -> Box { + let (raw, alloc) = Box::into_raw_with_allocator(v); + unsafe { Box::from_raw_in(raw as *mut str, alloc) } } /// Converts leading ascii bytes in `s` by calling the `convert` function. diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index b29f740ef0f2a..2cd08ce8df53e 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -42,30 +42,16 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::error::Error; -use core::iter::FusedIterator; -#[cfg(not(no_global_oom_handling))] -use core::iter::from_fn; -#[cfg(not(no_global_oom_handling))] -use core::ops::Add; -#[cfg(not(no_global_oom_handling))] -use core::ops::AddAssign; -#[cfg(not(no_global_oom_handling))] -use core::ops::Bound::{Excluded, Included, Unbounded}; -use core::ops::{self, Range, RangeBounds}; -use core::str::pattern::{Pattern, Utf8Pattern}; -use core::{fmt, hash, ptr, slice}; +use core::fmt; #[cfg(not(no_global_oom_handling))] use crate::alloc::Allocator; +use crate::alloc::Global; #[cfg(not(no_global_oom_handling))] use crate::borrow::{Cow, ToOwned}; -use crate::boxed::Box; -use crate::collections::TryReserveError; -use crate::str::{self, CharIndices, Chars, Utf8Error, from_utf8_unchecked_mut}; -#[cfg(not(no_global_oom_handling))] -use crate::str::{FromStr, from_boxed_utf8_unchecked}; -use crate::vec::{self, Vec}; +use crate::str; + +pub mod string; /// A UTF-8–encoded, growable string. /// @@ -356,12 +342,9 @@ use crate::vec::{self, Vec}; /// [Deref]: core::ops::Deref "ops::Deref" /// [`Deref`]: core::ops::Deref "ops::Deref" /// [`as_str()`]: String::as_str -#[derive(PartialEq, PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), lang = "String")] -pub struct String { - vec: Vec, -} +#[cfg_attr(not(test), rustc_diagnostic_item = "String")] +pub type String = string::String; /// A possible error value when converting a `String` from a UTF-8 byte vector. /// @@ -378,7 +361,7 @@ pub struct String { /// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error` /// through the [`utf8_error`] method. /// -/// [`Utf8Error`]: str::Utf8Error "std::str::Utf8Error" +/// [`Utf8Error`]: core::str::Utf8Error "std::str::Utf8Error" /// [`std::str`]: core::str "std::str" /// [`&str`]: prim@str "&str" /// [`utf8_error`]: FromUtf8Error::utf8_error @@ -395,12 +378,7 @@ pub struct String { /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(no_global_oom_handling), derive(Clone))] -#[derive(Debug, PartialEq, Eq)] -pub struct FromUtf8Error { - bytes: Vec, - error: Utf8Error, -} +pub type FromUtf8Error = string::FromUtf8Error; /// A possible error value when converting a `String` from a UTF-16 byte slice. /// @@ -418,2411 +396,145 @@ pub struct FromUtf8Error { /// assert!(String::from_utf16(v).is_err()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct FromUtf16Error(()); +pub type FromUtf16Error = string::FromUtf16Error; -impl String { - /// Creates a new empty `String`. - /// - /// Given that the `String` is empty, this will not allocate any initial - /// buffer. While that means that this initial operation is very - /// inexpensive, it may cause excessive allocation later when you add - /// data. If you have an idea of how much data the `String` will hold, - /// consider the [`with_capacity`] method to prevent excessive - /// re-allocation. - /// - /// [`with_capacity`]: String::with_capacity - /// - /// # Examples - /// - /// ``` - /// let s = String::new(); - /// ``` - #[inline] - #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_new")] - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub const fn new() -> String { - String { vec: Vec::new() } - } +/// A type alias for [`Infallible`]. +/// +/// This alias exists for backwards compatibility, and may be eventually deprecated. +/// +/// [`Infallible`]: core::convert::Infallible "convert::Infallible" +#[stable(feature = "str_parse_error", since = "1.5.0")] +pub type ParseError = core::convert::Infallible; - /// Creates a new empty `String` with at least the specified capacity. - /// - /// `String`s have an internal buffer to hold their data. The capacity is - /// the length of that buffer, and can be queried with the [`capacity`] - /// method. This method creates an empty `String`, but one with an initial - /// buffer that can hold at least `capacity` bytes. This is useful when you - /// may be appending a bunch of data to the `String`, reducing the number of - /// reallocations it needs to do. - /// - /// [`capacity`]: String::capacity - /// - /// If the given capacity is `0`, no allocation will occur, and this method - /// is identical to the [`new`] method. - /// - /// [`new`]: String::new +/// A trait for converting a value to a `String`. +/// +/// This trait is automatically implemented for any type which implements the +/// [`Display`] trait. As such, `ToString` shouldn't be implemented directly: +/// [`Display`] should be implemented instead, and you get the `ToString` +/// implementation for free. +/// +/// [`Display`]: fmt::Display +#[cfg_attr(not(test), rustc_diagnostic_item = "ToString")] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToString { + /// Converts the given value to a `String`. /// /// # Examples /// /// ``` - /// let mut s = String::with_capacity(10); - /// - /// // The String contains no chars, even though it has capacity for more - /// assert_eq!(s.len(), 0); - /// - /// // These are all done without reallocating... - /// let cap = s.capacity(); - /// for _ in 0..10 { - /// s.push('a'); - /// } - /// - /// assert_eq!(s.capacity(), cap); + /// let i = 5; + /// let five = String::from("5"); /// - /// // ...but this may make the string reallocate - /// s.push('a'); + /// assert_eq!(five, i.to_string()); /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] + #[rustc_conversion_suggestion] #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn with_capacity(capacity: usize) -> String { - String { vec: Vec::with_capacity(capacity) } - } + #[cfg_attr(not(test), rustc_diagnostic_item = "to_string_method")] + fn to_string(&self) -> String; +} - /// Creates a new empty `String` with at least the specified capacity. - /// - /// # Errors - /// - /// Returns [`Err`] if the capacity exceeds `isize::MAX` bytes, - /// or if the memory allocator reports failure. - /// +/// # Panics +/// +/// In this implementation, the `to_string` method panics +/// if the `Display` implementation returns an error. +/// This indicates an incorrect `Display` implementation +/// since `fmt::Write for String` never returns an error itself. +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl ToString for T { #[inline] - #[unstable(feature = "try_with_capacity", issue = "91913")] - pub fn try_with_capacity(capacity: usize) -> Result { - Ok(String { vec: Vec::try_with_capacity(capacity)? }) + fn to_string(&self) -> String { + ::spec_to_string(self) } +} + +#[cfg(not(no_global_oom_handling))] +trait SpecToString { + fn spec_to_string(&self) -> String; +} - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Since we don't - // require this method for testing purposes, I'll just stub it - // NB see the slice::hack module in slice.rs for more information +#[cfg(not(no_global_oom_handling))] +impl SpecToString for T { + // A common guideline is to not inline generic functions. However, + // removing `#[inline]` from this method causes non-negligible regressions. + // See , the last attempt + // to try to remove it. #[inline] - #[cfg(test)] - #[allow(missing_docs)] - pub fn from_str(_: &str) -> String { - panic!("not available with cfg(test)"); + default fn spec_to_string(&self) -> String { + let mut buf = String::new(); + let mut formatter = + core::fmt::Formatter::new(&mut buf, core::fmt::FormattingOptions::new()); + // Bypass format_args!() to avoid write_str with zero-length strs + fmt::Display::fmt(self, &mut formatter) + .expect("a Display implementation returned an error unexpectedly"); + buf } +} - /// Converts a vector of bytes to a `String`. - /// - /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes - /// ([`Vec`]) is made of bytes, so this function converts between the - /// two. Not all byte slices are valid `String`s, however: `String` - /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that - /// the bytes are valid UTF-8, and then does the conversion. - /// - /// If you are sure that the byte slice is valid UTF-8, and you don't want - /// to incur the overhead of the validity check, there is an unsafe version - /// of this function, [`from_utf8_unchecked`], which has the same behavior - /// but skips the check. - /// - /// This method will take care to not copy the vector, for efficiency's - /// sake. - /// - /// If you need a [`&str`] instead of a `String`, consider - /// [`str::from_utf8`]. - /// - /// The inverse of this method is [`into_bytes`]. - /// - /// # Errors - /// - /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the - /// provided bytes are not UTF-8. The vector you moved in is also included. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// // some bytes, in a vector - /// let sparkle_heart = vec![240, 159, 146, 150]; - /// - /// // We know these bytes are valid, so we'll use `unwrap()`. - /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); - /// - /// assert_eq!("💖", sparkle_heart); - /// ``` - /// - /// Incorrect bytes: - /// - /// ``` - /// // some invalid bytes, in a vector - /// let sparkle_heart = vec![0, 159, 146, 150]; - /// - /// assert!(String::from_utf8(sparkle_heart).is_err()); - /// ``` - /// - /// See the docs for [`FromUtf8Error`] for more details on what you can do - /// with this error. - /// - /// [`from_utf8_unchecked`]: String::from_utf8_unchecked - /// [`Vec`]: crate::vec::Vec "Vec" - /// [`&str`]: prim@str "&str" - /// [`into_bytes`]: String::into_bytes +#[cfg(not(no_global_oom_handling))] +impl SpecToString for core::ascii::Char { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_from_utf8")] - pub fn from_utf8(vec: Vec) -> Result { - match str::from_utf8(&vec) { - Ok(..) => Ok(String { vec }), - Err(e) => Err(FromUtf8Error { bytes: vec, error: e }), - } + fn spec_to_string(&self) -> String { + self.as_str().to_owned() } +} - /// Converts a slice of bytes to a string, including invalid characters. - /// - /// Strings are made of bytes ([`u8`]), and a slice of bytes - /// ([`&[u8]`][byteslice]) is made of bytes, so this function converts - /// between the two. Not all byte slices are valid strings, however: strings - /// are required to be valid UTF-8. During this conversion, - /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with - /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: � - /// - /// [byteslice]: prim@slice - /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER - /// - /// If you are sure that the byte slice is valid UTF-8, and you don't want - /// to incur the overhead of the conversion, there is an unsafe version - /// of this function, [`from_utf8_unchecked`], which has the same behavior - /// but skips the checks. - /// - /// [`from_utf8_unchecked`]: String::from_utf8_unchecked - /// - /// This function returns a [`Cow<'a, str>`]. If our byte slice is invalid - /// UTF-8, then we need to insert the replacement characters, which will - /// change the size of the string, and hence, require a `String`. But if - /// it's already valid UTF-8, we don't need a new allocation. This return - /// type allows us to handle both cases. - /// - /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// // some bytes, in a vector - /// let sparkle_heart = vec![240, 159, 146, 150]; - /// - /// let sparkle_heart = String::from_utf8_lossy(&sparkle_heart); - /// - /// assert_eq!("💖", sparkle_heart); - /// ``` - /// - /// Incorrect bytes: - /// - /// ``` - /// // some invalid bytes - /// let input = b"Hello \xF0\x90\x80World"; - /// let output = String::from_utf8_lossy(input); - /// - /// assert_eq!("Hello �World", output); - /// ``` - #[must_use] - #[cfg(not(no_global_oom_handling))] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { - let mut iter = v.utf8_chunks(); - - let first_valid = if let Some(chunk) = iter.next() { - let valid = chunk.valid(); - if chunk.invalid().is_empty() { - debug_assert_eq!(valid.len(), v.len()); - return Cow::Borrowed(valid); - } - valid - } else { - return Cow::Borrowed(""); - }; - - const REPLACEMENT: &str = "\u{FFFD}"; - - let mut res = String::with_capacity(v.len()); - res.push_str(first_valid); - res.push_str(REPLACEMENT); - - for chunk in iter { - res.push_str(chunk.valid()); - if !chunk.invalid().is_empty() { - res.push_str(REPLACEMENT); - } - } - - Cow::Owned(res) +#[cfg(not(no_global_oom_handling))] +impl SpecToString for char { + #[inline] + fn spec_to_string(&self) -> String { + String::from(self.encode_utf8(&mut [0; 4])) } +} - /// Converts a [`Vec`] to a `String`, substituting invalid UTF-8 - /// sequences with replacement characters. - /// - /// See [`from_utf8_lossy`] for more details. - /// - /// [`from_utf8_lossy`]: String::from_utf8_lossy - /// - /// Note that this function does not guarantee reuse of the original `Vec` - /// allocation. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(string_from_utf8_lossy_owned)] - /// // some bytes, in a vector - /// let sparkle_heart = vec![240, 159, 146, 150]; - /// - /// let sparkle_heart = String::from_utf8_lossy_owned(sparkle_heart); - /// - /// assert_eq!(String::from("💖"), sparkle_heart); - /// ``` - /// - /// Incorrect bytes: - /// - /// ``` - /// #![feature(string_from_utf8_lossy_owned)] - /// // some invalid bytes - /// let input: Vec = b"Hello \xF0\x90\x80World".into(); - /// let output = String::from_utf8_lossy_owned(input); - /// - /// assert_eq!(String::from("Hello �World"), output); - /// ``` - #[must_use] - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] - pub fn from_utf8_lossy_owned(v: Vec) -> String { - if let Cow::Owned(string) = String::from_utf8_lossy(&v) { - string - } else { - // SAFETY: `String::from_utf8_lossy`'s contract ensures that if - // it returns a `Cow::Borrowed`, it is a valid UTF-8 string. - // Otherwise, it returns a new allocation of an owned `String`, with - // replacement characters for invalid sequences, which is returned - // above. - unsafe { String::from_utf8_unchecked(v) } - } +#[cfg(not(no_global_oom_handling))] +impl SpecToString for bool { + #[inline] + fn spec_to_string(&self) -> String { + String::from(if *self { "true" } else { "false" }) } +} - /// Decode a native endian UTF-16–encoded vector `v` into a `String`, - /// returning [`Err`] if `v` contains any invalid data. - /// - /// # Examples - /// - /// ``` - /// // 𝄞music - /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, - /// 0x0073, 0x0069, 0x0063]; - /// assert_eq!(String::from("𝄞music"), - /// String::from_utf16(v).unwrap()); - /// - /// // 𝄞muic - /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, - /// 0xD800, 0x0069, 0x0063]; - /// assert!(String::from_utf16(v).is_err()); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf16(v: &[u16]) -> Result { - // This isn't done via collect::>() for performance reasons. - // FIXME: the function can be simplified again when #48994 is closed. - let mut ret = String::with_capacity(v.len()); - for c in char::decode_utf16(v.iter().cloned()) { - if let Ok(c) = c { - ret.push(c); - } else { - return Err(FromUtf16Error(())); +#[cfg(not(no_global_oom_handling))] +impl SpecToString for u8 { + #[inline] + fn spec_to_string(&self) -> String { + let mut buf = String::with_capacity(3); + let mut n = *self; + if n >= 10 { + if n >= 100 { + buf.push((b'0' + n / 100) as char); + n %= 100; } + buf.push((b'0' + n / 10) as char); + n %= 10; } - Ok(ret) + buf.push((b'0' + n) as char); + buf } +} - /// Decode a native endian UTF-16–encoded slice `v` into a `String`, - /// replacing invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. - /// - /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], - /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 - /// conversion requires a memory allocation. - /// - /// [`from_utf8_lossy`]: String::from_utf8_lossy - /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" - /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER - /// - /// # Examples - /// - /// ``` - /// // 𝄞music - /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, - /// 0x0073, 0xDD1E, 0x0069, 0x0063, - /// 0xD834]; - /// - /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), - /// String::from_utf16_lossy(v)); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[must_use] +#[cfg(not(no_global_oom_handling))] +impl SpecToString for i8 { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf16_lossy(v: &[u16]) -> String { - char::decode_utf16(v.iter().cloned()) - .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) - .collect() - } - - /// Decode a UTF-16LE–encoded vector `v` into a `String`, - /// returning [`Err`] if `v` contains any invalid data. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(str_from_utf16_endian)] - /// // 𝄞music - /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, - /// 0x73, 0x00, 0x69, 0x00, 0x63, 0x00]; - /// assert_eq!(String::from("𝄞music"), - /// String::from_utf16le(v).unwrap()); - /// - /// // 𝄞muic - /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, - /// 0x00, 0xD8, 0x69, 0x00, 0x63, 0x00]; - /// assert!(String::from_utf16le(v).is_err()); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "str_from_utf16_endian", issue = "116258")] - pub fn from_utf16le(v: &[u8]) -> Result { - if v.len() % 2 != 0 { - return Err(FromUtf16Error(())); - } - match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { - (true, ([], v, [])) => Self::from_utf16(v), - _ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes)) - .collect::>() - .map_err(|_| FromUtf16Error(())), + fn spec_to_string(&self) -> String { + let mut buf = String::with_capacity(4); + if self.is_negative() { + buf.push('-'); } - } - - /// Decode a UTF-16LE–encoded slice `v` into a `String`, replacing - /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. - /// - /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], - /// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8 - /// conversion requires a memory allocation. - /// - /// [`from_utf8_lossy`]: String::from_utf8_lossy - /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" - /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(str_from_utf16_endian)] - /// // 𝄞music - /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, - /// 0x73, 0x00, 0x1E, 0xDD, 0x69, 0x00, 0x63, 0x00, - /// 0x34, 0xD8]; - /// - /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), - /// String::from_utf16le_lossy(v)); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "str_from_utf16_endian", issue = "116258")] - pub fn from_utf16le_lossy(v: &[u8]) -> String { - match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { - (true, ([], v, [])) => Self::from_utf16_lossy(v), - (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", - _ => { - let mut iter = v.array_chunks::<2>(); - let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes)) - .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) - .collect(); - if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } + let mut n = self.unsigned_abs(); + if n >= 10 { + if n >= 100 { + buf.push('1'); + n -= 100; } + buf.push((b'0' + n / 10) as char); + n %= 10; } + buf.push((b'0' + n) as char); + buf } - - /// Decode a UTF-16BE–encoded vector `v` into a `String`, - /// returning [`Err`] if `v` contains any invalid data. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(str_from_utf16_endian)] - /// // 𝄞music - /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, - /// 0x00, 0x73, 0x00, 0x69, 0x00, 0x63]; - /// assert_eq!(String::from("𝄞music"), - /// String::from_utf16be(v).unwrap()); - /// - /// // 𝄞muic - /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, - /// 0xD8, 0x00, 0x00, 0x69, 0x00, 0x63]; - /// assert!(String::from_utf16be(v).is_err()); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "str_from_utf16_endian", issue = "116258")] - pub fn from_utf16be(v: &[u8]) -> Result { - if v.len() % 2 != 0 { - return Err(FromUtf16Error(())); - } - match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { - (true, ([], v, [])) => Self::from_utf16(v), - _ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes)) - .collect::>() - .map_err(|_| FromUtf16Error(())), - } - } - - /// Decode a UTF-16BE–encoded slice `v` into a `String`, replacing - /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. - /// - /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], - /// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8 - /// conversion requires a memory allocation. - /// - /// [`from_utf8_lossy`]: String::from_utf8_lossy - /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" - /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(str_from_utf16_endian)] - /// // 𝄞music - /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, - /// 0x00, 0x73, 0xDD, 0x1E, 0x00, 0x69, 0x00, 0x63, - /// 0xD8, 0x34]; - /// - /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), - /// String::from_utf16be_lossy(v)); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "str_from_utf16_endian", issue = "116258")] - pub fn from_utf16be_lossy(v: &[u8]) -> String { - match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { - (true, ([], v, [])) => Self::from_utf16_lossy(v), - (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", - _ => { - let mut iter = v.array_chunks::<2>(); - let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes)) - .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) - .collect(); - if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } - } - } - } - - /// Decomposes a `String` into its raw components: `(pointer, length, capacity)`. - /// - /// Returns the raw pointer to the underlying data, the length of - /// the string (in bytes), and the allocated capacity of the data - /// (in bytes). These are the same arguments in the same order as - /// the arguments to [`from_raw_parts`]. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `String`. The only way to do - /// this is to convert the raw pointer, length, and capacity back - /// into a `String` with the [`from_raw_parts`] function, allowing - /// the destructor to perform the cleanup. - /// - /// [`from_raw_parts`]: String::from_raw_parts - /// - /// # Examples - /// - /// ``` - /// #![feature(vec_into_raw_parts)] - /// let s = String::from("hello"); - /// - /// let (ptr, len, cap) = s.into_raw_parts(); - /// - /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; - /// assert_eq!(rebuilt, "hello"); - /// ``` - #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] - pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { - self.vec.into_raw_parts() - } - - /// Creates a new `String` from a pointer, a length and a capacity. - /// - /// # Safety - /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * The memory at `buf` needs to have been previously allocated by the - /// same allocator the standard library uses, with a required alignment of exactly 1. - /// * `length` needs to be less than or equal to `capacity`. - /// * `capacity` needs to be the correct value. - /// * The first `length` bytes at `buf` need to be valid UTF-8. - /// - /// Violating these may cause problems like corrupting the allocator's - /// internal data structures. For example, it is normally **not** safe to - /// build a `String` from a pointer to a C `char` array containing UTF-8 - /// _unless_ you are certain that array was originally allocated by the - /// Rust standard library's allocator. - /// - /// The ownership of `buf` is effectively transferred to the - /// `String` which may then deallocate, reallocate or change the - /// contents of memory pointed to by the pointer at will. Ensure - /// that nothing else uses the pointer after calling this - /// function. - /// - /// # Examples - /// - /// ``` - /// use std::mem; - /// - /// unsafe { - /// let s = String::from("hello"); - /// - // FIXME Update this when vec_into_raw_parts is stabilized - /// // Prevent automatically dropping the String's data - /// let mut s = mem::ManuallyDrop::new(s); - /// - /// let ptr = s.as_mut_ptr(); - /// let len = s.len(); - /// let capacity = s.capacity(); - /// - /// let s = String::from_raw_parts(ptr, len, capacity); - /// - /// assert_eq!(String::from("hello"), s); - /// } - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { - unsafe { String { vec: Vec::from_raw_parts(buf, length, capacity) } } - } - - /// Converts a vector of bytes to a `String` without checking that the - /// string contains valid UTF-8. - /// - /// See the safe version, [`from_utf8`], for more details. - /// - /// [`from_utf8`]: String::from_utf8 - /// - /// # Safety - /// - /// This function is unsafe because it does not check that the bytes passed - /// to it are valid UTF-8. If this constraint is violated, it may cause - /// memory unsafety issues with future users of the `String`, as the rest of - /// the standard library assumes that `String`s are valid UTF-8. - /// - /// # Examples - /// - /// ``` - /// // some bytes, in a vector - /// let sparkle_heart = vec![240, 159, 146, 150]; - /// - /// let sparkle_heart = unsafe { - /// String::from_utf8_unchecked(sparkle_heart) - /// }; - /// - /// assert_eq!("💖", sparkle_heart); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_utf8_unchecked(bytes: Vec) -> String { - String { vec: bytes } - } - - /// Converts a `String` into a byte vector. - /// - /// This consumes the `String`, so we do not need to copy its contents. - /// - /// # Examples - /// - /// ``` - /// let s = String::from("hello"); - /// let bytes = s.into_bytes(); - /// - /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]); - /// ``` - #[inline] - #[must_use = "`self` will be dropped if the result is not used"] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] - pub const fn into_bytes(self) -> Vec { - self.vec - } - - /// Extracts a string slice containing the entire `String`. - /// - /// # Examples - /// - /// ``` - /// let s = String::from("foo"); - /// - /// assert_eq!("foo", s.as_str()); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "string_as_str", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")] - #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] - pub const fn as_str(&self) -> &str { - // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error - // at construction. - unsafe { str::from_utf8_unchecked(self.vec.as_slice()) } - } - - /// Converts a `String` into a mutable string slice. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("foobar"); - /// let s_mut_str = s.as_mut_str(); - /// - /// s_mut_str.make_ascii_uppercase(); - /// - /// assert_eq!("FOOBAR", s_mut_str); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "string_as_str", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")] - #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] - pub const fn as_mut_str(&mut self) -> &mut str { - // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error - // at construction. - unsafe { str::from_utf8_unchecked_mut(self.vec.as_mut_slice()) } - } - - /// Appends a given string slice onto the end of this `String`. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("foo"); - /// - /// s.push_str("bar"); - /// - /// assert_eq!("foobar", s); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_confusables("append", "push")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_push_str")] - pub fn push_str(&mut self, string: &str) { - self.vec.extend_from_slice(string.as_bytes()) - } - - /// Copies elements from `src` range to the end of the string. - /// - /// # Panics - /// - /// Panics if the starting point or end point do not lie on a [`char`] - /// boundary, or if they're out of bounds. - /// - /// # Examples - /// - /// ``` - /// #![feature(string_extend_from_within)] - /// let mut string = String::from("abcde"); - /// - /// string.extend_from_within(2..); - /// assert_eq!(string, "abcdecde"); - /// - /// string.extend_from_within(..2); - /// assert_eq!(string, "abcdecdeab"); - /// - /// string.extend_from_within(4..8); - /// assert_eq!(string, "abcdecdeabecde"); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "string_extend_from_within", issue = "103806")] - pub fn extend_from_within(&mut self, src: R) - where - R: RangeBounds, - { - let src @ Range { start, end } = slice::range(src, ..self.len()); - - assert!(self.is_char_boundary(start)); - assert!(self.is_char_boundary(end)); - - self.vec.extend_from_within(src); - } - - /// Returns this `String`'s capacity, in bytes. - /// - /// # Examples - /// - /// ``` - /// let s = String::with_capacity(10); - /// - /// assert!(s.capacity() >= 10); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] - pub const fn capacity(&self) -> usize { - self.vec.capacity() - } - - /// Reserves capacity for at least `additional` bytes more than the - /// current length. The allocator may reserve more space to speculatively - /// avoid frequent allocations. After calling `reserve`, - /// capacity will be greater than or equal to `self.len() + additional`. - /// Does nothing if capacity is already sufficient. - /// - /// # Panics - /// - /// Panics if the new capacity overflows [`usize`]. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut s = String::new(); - /// - /// s.reserve(10); - /// - /// assert!(s.capacity() >= 10); - /// ``` - /// - /// This might not actually increase the capacity: - /// - /// ``` - /// let mut s = String::with_capacity(10); - /// s.push('a'); - /// s.push('b'); - /// - /// // s now has a length of 2 and a capacity of at least 10 - /// let capacity = s.capacity(); - /// assert_eq!(2, s.len()); - /// assert!(capacity >= 10); - /// - /// // Since we already have at least an extra 8 capacity, calling this... - /// s.reserve(8); - /// - /// // ... doesn't actually increase. - /// assert_eq!(capacity, s.capacity()); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn reserve(&mut self, additional: usize) { - self.vec.reserve(additional) - } - - /// Reserves the minimum capacity for at least `additional` bytes more than - /// the current length. Unlike [`reserve`], this will not - /// deliberately over-allocate to speculatively avoid frequent allocations. - /// After calling `reserve_exact`, capacity will be greater than or equal to - /// `self.len() + additional`. Does nothing if the capacity is already - /// sufficient. - /// - /// [`reserve`]: String::reserve - /// - /// # Panics - /// - /// Panics if the new capacity overflows [`usize`]. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut s = String::new(); - /// - /// s.reserve_exact(10); - /// - /// assert!(s.capacity() >= 10); - /// ``` - /// - /// This might not actually increase the capacity: - /// - /// ``` - /// let mut s = String::with_capacity(10); - /// s.push('a'); - /// s.push('b'); - /// - /// // s now has a length of 2 and a capacity of at least 10 - /// let capacity = s.capacity(); - /// assert_eq!(2, s.len()); - /// assert!(capacity >= 10); - /// - /// // Since we already have at least an extra 8 capacity, calling this... - /// s.reserve_exact(8); - /// - /// // ... doesn't actually increase. - /// assert_eq!(capacity, s.capacity()); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn reserve_exact(&mut self, additional: usize) { - self.vec.reserve_exact(additional) - } - - /// Tries to reserve capacity for at least `additional` bytes more than the - /// current length. The allocator may reserve more space to speculatively - /// avoid frequent allocations. After calling `try_reserve`, capacity will be - /// greater than or equal to `self.len() + additional` if it returns - /// `Ok(())`. Does nothing if capacity is already sufficient. This method - /// preserves the contents even if an error occurs. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// use std::collections::TryReserveError; - /// - /// fn process_data(data: &str) -> Result { - /// let mut output = String::new(); - /// - /// // Pre-reserve the memory, exiting if we can't - /// output.try_reserve(data.len())?; - /// - /// // Now we know this can't OOM in the middle of our complex work - /// output.push_str(data); - /// - /// Ok(output) - /// } - /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); - /// ``` - #[stable(feature = "try_reserve", since = "1.57.0")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.vec.try_reserve(additional) - } - - /// Tries to reserve the minimum capacity for at least `additional` bytes - /// more than the current length. Unlike [`try_reserve`], this will not - /// deliberately over-allocate to speculatively avoid frequent allocations. - /// After calling `try_reserve_exact`, capacity will be greater than or - /// equal to `self.len() + additional` if it returns `Ok(())`. - /// Does nothing if the capacity is already sufficient. - /// - /// Note that the allocator may give the collection more space than it - /// requests. Therefore, capacity can not be relied upon to be precisely - /// minimal. Prefer [`try_reserve`] if future insertions are expected. - /// - /// [`try_reserve`]: String::try_reserve - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// use std::collections::TryReserveError; - /// - /// fn process_data(data: &str) -> Result { - /// let mut output = String::new(); - /// - /// // Pre-reserve the memory, exiting if we can't - /// output.try_reserve_exact(data.len())?; - /// - /// // Now we know this can't OOM in the middle of our complex work - /// output.push_str(data); - /// - /// Ok(output) - /// } - /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); - /// ``` - #[stable(feature = "try_reserve", since = "1.57.0")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.vec.try_reserve_exact(additional) - } - - /// Shrinks the capacity of this `String` to match its length. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("foo"); - /// - /// s.reserve(100); - /// assert!(s.capacity() >= 100); - /// - /// s.shrink_to_fit(); - /// assert_eq!(3, s.capacity()); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn shrink_to_fit(&mut self) { - self.vec.shrink_to_fit() - } - - /// Shrinks the capacity of this `String` with a lower bound. - /// - /// The capacity will remain at least as large as both the length - /// and the supplied value. - /// - /// If the current capacity is less than the lower limit, this is a no-op. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("foo"); - /// - /// s.reserve(100); - /// assert!(s.capacity() >= 100); - /// - /// s.shrink_to(10); - /// assert!(s.capacity() >= 10); - /// s.shrink_to(0); - /// assert!(s.capacity() >= 3); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "shrink_to", since = "1.56.0")] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.vec.shrink_to(min_capacity) - } - - /// Appends the given [`char`] to the end of this `String`. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("abc"); - /// - /// s.push('1'); - /// s.push('2'); - /// s.push('3'); - /// - /// assert_eq!("abc123", s); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn push(&mut self, ch: char) { - match ch.len_utf8() { - 1 => self.vec.push(ch as u8), - _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()), - } - } - - /// Returns a byte slice of this `String`'s contents. - /// - /// The inverse of this method is [`from_utf8`]. - /// - /// [`from_utf8`]: String::from_utf8 - /// - /// # Examples - /// - /// ``` - /// let s = String::from("hello"); - /// - /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] - pub const fn as_bytes(&self) -> &[u8] { - self.vec.as_slice() - } - - /// Shortens this `String` to the specified length. - /// - /// If `new_len` is greater than or equal to the string's current length, this has no - /// effect. - /// - /// Note that this method has no effect on the allocated capacity - /// of the string - /// - /// # Panics - /// - /// Panics if `new_len` does not lie on a [`char`] boundary. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("hello"); - /// - /// s.truncate(2); - /// - /// assert_eq!("he", s); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn truncate(&mut self, new_len: usize) { - if new_len <= self.len() { - assert!(self.is_char_boundary(new_len)); - self.vec.truncate(new_len) - } - } - - /// Removes the last character from the string buffer and returns it. - /// - /// Returns [`None`] if this `String` is empty. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("abč"); - /// - /// assert_eq!(s.pop(), Some('č')); - /// assert_eq!(s.pop(), Some('b')); - /// assert_eq!(s.pop(), Some('a')); - /// - /// assert_eq!(s.pop(), None); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn pop(&mut self) -> Option { - let ch = self.chars().rev().next()?; - let newlen = self.len() - ch.len_utf8(); - unsafe { - self.vec.set_len(newlen); - } - Some(ch) - } - - /// Removes a [`char`] from this `String` at a byte position and returns it. - /// - /// This is an *O*(*n*) operation, as it requires copying every element in the - /// buffer. - /// - /// # Panics - /// - /// Panics if `idx` is larger than or equal to the `String`'s length, - /// or if it does not lie on a [`char`] boundary. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("abç"); - /// - /// assert_eq!(s.remove(0), 'a'); - /// assert_eq!(s.remove(1), 'ç'); - /// assert_eq!(s.remove(0), 'b'); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_confusables("delete", "take")] - pub fn remove(&mut self, idx: usize) -> char { - let ch = match self[idx..].chars().next() { - Some(ch) => ch, - None => panic!("cannot remove a char from the end of a string"), - }; - - let next = idx + ch.len_utf8(); - let len = self.len(); - unsafe { - ptr::copy(self.vec.as_ptr().add(next), self.vec.as_mut_ptr().add(idx), len - next); - self.vec.set_len(len - (next - idx)); - } - ch - } - - /// Remove all matches of pattern `pat` in the `String`. - /// - /// # Examples - /// - /// ``` - /// #![feature(string_remove_matches)] - /// let mut s = String::from("Trees are not green, the sky is not blue."); - /// s.remove_matches("not "); - /// assert_eq!("Trees are green, the sky is blue.", s); - /// ``` - /// - /// Matches will be detected and removed iteratively, so in cases where - /// patterns overlap, only the first pattern will be removed: - /// - /// ``` - /// #![feature(string_remove_matches)] - /// let mut s = String::from("banana"); - /// s.remove_matches("ana"); - /// assert_eq!("bna", s); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")] - pub fn remove_matches(&mut self, pat: P) { - use core::str::pattern::Searcher; - - let rejections = { - let mut searcher = pat.into_searcher(self); - // Per Searcher::next: - // - // A Match result needs to contain the whole matched pattern, - // however Reject results may be split up into arbitrary many - // adjacent fragments. Both ranges may have zero length. - // - // In practice the implementation of Searcher::next_match tends to - // be more efficient, so we use it here and do some work to invert - // matches into rejections since that's what we want to copy below. - let mut front = 0; - let rejections: Vec<_> = from_fn(|| { - let (start, end) = searcher.next_match()?; - let prev_front = front; - front = end; - Some((prev_front, start)) - }) - .collect(); - rejections.into_iter().chain(core::iter::once((front, self.len()))) - }; - - let mut len = 0; - let ptr = self.vec.as_mut_ptr(); - - for (start, end) in rejections { - let count = end - start; - if start != len { - // SAFETY: per Searcher::next: - // - // The stream of Match and Reject values up to a Done will - // contain index ranges that are adjacent, non-overlapping, - // covering the whole haystack, and laying on utf8 - // boundaries. - unsafe { - ptr::copy(ptr.add(start), ptr.add(len), count); - } - } - len += count; - } - - unsafe { - self.vec.set_len(len); - } - } - - /// Retains only the characters specified by the predicate. - /// - /// In other words, remove all characters `c` such that `f(c)` returns `false`. - /// This method operates in place, visiting each character exactly once in the - /// original order, and preserves the order of the retained characters. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("f_o_ob_ar"); - /// - /// s.retain(|c| c != '_'); - /// - /// assert_eq!(s, "foobar"); - /// ``` - /// - /// Because the elements are visited exactly once in the original order, - /// external state may be used to decide which elements to keep. - /// - /// ``` - /// let mut s = String::from("abcde"); - /// let keep = [false, true, true, false, true]; - /// let mut iter = keep.iter(); - /// s.retain(|_| *iter.next().unwrap()); - /// assert_eq!(s, "bce"); - /// ``` - #[inline] - #[stable(feature = "string_retain", since = "1.26.0")] - pub fn retain(&mut self, mut f: F) - where - F: FnMut(char) -> bool, - { - struct SetLenOnDrop<'a> { - s: &'a mut String, - idx: usize, - del_bytes: usize, - } - - impl<'a> Drop for SetLenOnDrop<'a> { - fn drop(&mut self) { - let new_len = self.idx - self.del_bytes; - debug_assert!(new_len <= self.s.len()); - unsafe { self.s.vec.set_len(new_len) }; - } - } - - let len = self.len(); - let mut guard = SetLenOnDrop { s: self, idx: 0, del_bytes: 0 }; - - while guard.idx < len { - let ch = - // SAFETY: `guard.idx` is positive-or-zero and less that len so the `get_unchecked` - // is in bound. `self` is valid UTF-8 like string and the returned slice starts at - // a unicode code point so the `Chars` always return one character. - unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap_unchecked() }; - let ch_len = ch.len_utf8(); - - if !f(ch) { - guard.del_bytes += ch_len; - } else if guard.del_bytes > 0 { - // SAFETY: `guard.idx` is in bound and `guard.del_bytes` represent the number of - // bytes that are erased from the string so the resulting `guard.idx - - // guard.del_bytes` always represent a valid unicode code point. - // - // `guard.del_bytes` >= `ch.len_utf8()`, so taking a slice with `ch.len_utf8()` len - // is safe. - ch.encode_utf8(unsafe { - crate::slice::from_raw_parts_mut( - guard.s.as_mut_ptr().add(guard.idx - guard.del_bytes), - ch.len_utf8(), - ) - }); - } - - // Point idx to the next char - guard.idx += ch_len; - } - - drop(guard); - } - - /// Inserts a character into this `String` at a byte position. - /// - /// This is an *O*(*n*) operation as it requires copying every element in the - /// buffer. - /// - /// # Panics - /// - /// Panics if `idx` is larger than the `String`'s length, or if it does not - /// lie on a [`char`] boundary. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::with_capacity(3); - /// - /// s.insert(0, 'f'); - /// s.insert(1, 'o'); - /// s.insert(2, 'o'); - /// - /// assert_eq!("foo", s); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_confusables("set")] - pub fn insert(&mut self, idx: usize, ch: char) { - assert!(self.is_char_boundary(idx)); - let mut bits = [0; 4]; - let bits = ch.encode_utf8(&mut bits).as_bytes(); - - unsafe { - self.insert_bytes(idx, bits); - } - } - - #[cfg(not(no_global_oom_handling))] - unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { - let len = self.len(); - let amt = bytes.len(); - self.vec.reserve(amt); - - unsafe { - ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); - ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); - self.vec.set_len(len + amt); - } - } - - /// Inserts a string slice into this `String` at a byte position. - /// - /// This is an *O*(*n*) operation as it requires copying every element in the - /// buffer. - /// - /// # Panics - /// - /// Panics if `idx` is larger than the `String`'s length, or if it does not - /// lie on a [`char`] boundary. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("bar"); - /// - /// s.insert_str(0, "foo"); - /// - /// assert_eq!("foobar", s); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "insert_str", since = "1.16.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_insert_str")] - pub fn insert_str(&mut self, idx: usize, string: &str) { - assert!(self.is_char_boundary(idx)); - - unsafe { - self.insert_bytes(idx, string.as_bytes()); - } - } - - /// Returns a mutable reference to the contents of this `String`. - /// - /// # Safety - /// - /// This function is unsafe because the returned `&mut Vec` allows writing - /// bytes which are not valid UTF-8. If this constraint is violated, using - /// the original `String` after dropping the `&mut Vec` may violate memory - /// safety, as the rest of the standard library assumes that `String`s are - /// valid UTF-8. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("hello"); - /// - /// unsafe { - /// let vec = s.as_mut_vec(); - /// assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]); - /// - /// vec.reverse(); - /// } - /// assert_eq!(s, "olleh"); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] - pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec { - &mut self.vec - } - - /// Returns the length of this `String`, in bytes, not [`char`]s or - /// graphemes. In other words, it might not be what a human considers the - /// length of the string. - /// - /// # Examples - /// - /// ``` - /// let a = String::from("foo"); - /// assert_eq!(a.len(), 3); - /// - /// let fancy_f = String::from("ƒoo"); - /// assert_eq!(fancy_f.len(), 4); - /// assert_eq!(fancy_f.chars().count(), 3); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] - #[rustc_confusables("length", "size")] - pub const fn len(&self) -> usize { - self.vec.len() - } - - /// Returns `true` if this `String` has a length of zero, and `false` otherwise. - /// - /// # Examples - /// - /// ``` - /// let mut v = String::new(); - /// assert!(v.is_empty()); - /// - /// v.push('a'); - /// assert!(!v.is_empty()); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] - pub const fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Splits the string into two at the given byte index. - /// - /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and - /// the returned `String` contains bytes `[at, len)`. `at` must be on the - /// boundary of a UTF-8 code point. - /// - /// Note that the capacity of `self` does not change. - /// - /// # Panics - /// - /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last - /// code point of the string. - /// - /// # Examples - /// - /// ``` - /// # fn main() { - /// let mut hello = String::from("Hello, World!"); - /// let world = hello.split_off(7); - /// assert_eq!(hello, "Hello, "); - /// assert_eq!(world, "World!"); - /// # } - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "string_split_off", since = "1.16.0")] - #[must_use = "use `.truncate()` if you don't need the other half"] - pub fn split_off(&mut self, at: usize) -> String { - assert!(self.is_char_boundary(at)); - let other = self.vec.split_off(at); - unsafe { String::from_utf8_unchecked(other) } - } - - /// Truncates this `String`, removing all contents. - /// - /// While this means the `String` will have a length of zero, it does not - /// touch its capacity. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("foo"); - /// - /// s.clear(); - /// - /// assert!(s.is_empty()); - /// assert_eq!(0, s.len()); - /// assert_eq!(3, s.capacity()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn clear(&mut self) { - self.vec.clear() - } - - /// Removes the specified range from the string in bulk, returning all - /// removed characters as an iterator. - /// - /// The returned iterator keeps a mutable borrow on the string to optimize - /// its implementation. - /// - /// # Panics - /// - /// Panics if the starting point or end point do not lie on a [`char`] - /// boundary, or if they're out of bounds. - /// - /// # Leaking - /// - /// If the returned iterator goes out of scope without being dropped (due to - /// [`core::mem::forget`], for example), the string may still contain a copy - /// of any drained characters, or may have lost characters arbitrarily, - /// including characters outside the range. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("α is alpha, β is beta"); - /// let beta_offset = s.find('β').unwrap_or(s.len()); - /// - /// // Remove the range up until the β from the string - /// let t: String = s.drain(..beta_offset).collect(); - /// assert_eq!(t, "α is alpha, "); - /// assert_eq!(s, "β is beta"); - /// - /// // A full range clears the string, like `clear()` does - /// s.drain(..); - /// assert_eq!(s, ""); - /// ``` - #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self, range: R) -> Drain<'_> - where - R: RangeBounds, - { - // Memory safety - // - // The String version of Drain does not have the memory safety issues - // of the vector version. The data is just plain bytes. - // Because the range removal happens in Drop, if the Drain iterator is leaked, - // the removal will not happen. - let Range { start, end } = slice::range(range, ..self.len()); - assert!(self.is_char_boundary(start)); - assert!(self.is_char_boundary(end)); - - // Take out two simultaneous borrows. The &mut String won't be accessed - // until iteration is over, in Drop. - let self_ptr = self as *mut _; - // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks. - let chars_iter = unsafe { self.get_unchecked(start..end) }.chars(); - - Drain { start, end, iter: chars_iter, string: self_ptr } - } - - /// Converts a `String` into an iterator over the [`char`]s of the string. - /// - /// As a string consists of valid UTF-8, we can iterate through a string - /// by [`char`]. This method returns such an iterator. - /// - /// It's important to remember that [`char`] represents a Unicode Scalar - /// Value, and might not match your idea of what a 'character' is. Iteration - /// over grapheme clusters may be what you actually want. That functionality - /// is not provided by Rust's standard library, check crates.io instead. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(string_into_chars)] - /// - /// let word = String::from("goodbye"); - /// - /// let mut chars = word.into_chars(); - /// - /// assert_eq!(Some('g'), chars.next()); - /// assert_eq!(Some('o'), chars.next()); - /// assert_eq!(Some('o'), chars.next()); - /// assert_eq!(Some('d'), chars.next()); - /// assert_eq!(Some('b'), chars.next()); - /// assert_eq!(Some('y'), chars.next()); - /// assert_eq!(Some('e'), chars.next()); - /// - /// assert_eq!(None, chars.next()); - /// ``` - /// - /// Remember, [`char`]s might not match your intuition about characters: - /// - /// ``` - /// #![feature(string_into_chars)] - /// - /// let y = String::from("y̆"); - /// - /// let mut chars = y.into_chars(); - /// - /// assert_eq!(Some('y'), chars.next()); // not 'y̆' - /// assert_eq!(Some('\u{0306}'), chars.next()); - /// - /// assert_eq!(None, chars.next()); - /// ``` - /// - /// [`char`]: prim@char - #[inline] - #[must_use = "`self` will be dropped if the result is not used"] - #[unstable(feature = "string_into_chars", issue = "133125")] - pub fn into_chars(self) -> IntoChars { - IntoChars { bytes: self.into_bytes().into_iter() } - } - - /// Removes the specified range in the string, - /// and replaces it with the given string. - /// The given string doesn't need to be the same length as the range. - /// - /// # Panics - /// - /// Panics if the starting point or end point do not lie on a [`char`] - /// boundary, or if they're out of bounds. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("α is alpha, β is beta"); - /// let beta_offset = s.find('β').unwrap_or(s.len()); - /// - /// // Replace the range up until the β from the string - /// s.replace_range(..beta_offset, "Α is capital alpha; "); - /// assert_eq!(s, "Α is capital alpha; β is beta"); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature = "splice", since = "1.27.0")] - pub fn replace_range(&mut self, range: R, replace_with: &str) - where - R: RangeBounds, - { - // Memory safety - // - // Replace_range does not have the memory safety issues of a vector Splice. - // of the vector version. The data is just plain bytes. - - // WARNING: Inlining this variable would be unsound (#81138) - let start = range.start_bound(); - match start { - Included(&n) => assert!(self.is_char_boundary(n)), - Excluded(&n) => assert!(self.is_char_boundary(n + 1)), - Unbounded => {} - }; - // WARNING: Inlining this variable would be unsound (#81138) - let end = range.end_bound(); - match end { - Included(&n) => assert!(self.is_char_boundary(n + 1)), - Excluded(&n) => assert!(self.is_char_boundary(n)), - Unbounded => {} - }; - - // Using `range` again would be unsound (#81138) - // We assume the bounds reported by `range` remain the same, but - // an adversarial implementation could change between calls - unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes()); - } - - /// Converts this `String` into a [Box]<[str]>. - /// - /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`]. - /// Note that this call may reallocate and copy the bytes of the string. - /// - /// [`shrink_to_fit`]: String::shrink_to_fit - /// [str]: prim@str "str" - /// - /// # Examples - /// - /// ``` - /// let s = String::from("hello"); - /// - /// let b = s.into_boxed_str(); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature = "box_str", since = "1.4.0")] - #[must_use = "`self` will be dropped if the result is not used"] - #[inline] - pub fn into_boxed_str(self) -> Box { - let slice = self.vec.into_boxed_slice(); - unsafe { from_boxed_utf8_unchecked(slice) } - } - - /// Consumes and leaks the `String`, returning a mutable reference to the contents, - /// `&'a mut str`. - /// - /// The caller has free choice over the returned lifetime, including `'static`. Indeed, - /// this function is ideally used for data that lives for the remainder of the program's life, - /// as dropping the returned reference will cause a memory leak. - /// - /// It does not reallocate or shrink the `String`, so the leaked allocation may include unused - /// capacity that is not part of the returned slice. If you want to discard excess capacity, - /// call [`into_boxed_str`], and then [`Box::leak`] instead. However, keep in mind that - /// trimming the capacity may result in a reallocation and copy. - /// - /// [`into_boxed_str`]: Self::into_boxed_str - /// - /// # Examples - /// - /// ``` - /// let x = String::from("bucket"); - /// let static_ref: &'static mut str = x.leak(); - /// assert_eq!(static_ref, "bucket"); - /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): - /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. - /// # drop(unsafe { Box::from_raw(static_ref) }); - /// ``` - #[stable(feature = "string_leak", since = "1.72.0")] - #[inline] - pub fn leak<'a>(self) -> &'a mut str { - let slice = self.vec.leak(); - unsafe { from_utf8_unchecked_mut(slice) } - } -} - -impl FromUtf8Error { - /// Returns a slice of [`u8`]s bytes that were attempted to convert to a `String`. - /// - /// # Examples - /// - /// ``` - /// // some invalid bytes, in a vector - /// let bytes = vec![0, 159]; - /// - /// let value = String::from_utf8(bytes); - /// - /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); - /// ``` - #[must_use] - #[stable(feature = "from_utf8_error_as_bytes", since = "1.26.0")] - pub fn as_bytes(&self) -> &[u8] { - &self.bytes[..] - } - - /// Converts the bytes into a `String` lossily, substituting invalid UTF-8 - /// sequences with replacement characters. - /// - /// See [`String::from_utf8_lossy`] for more details on replacement of - /// invalid sequences, and [`String::from_utf8_lossy_owned`] for the - /// `String` function which corresponds to this function. - /// - /// # Examples - /// - /// ``` - /// #![feature(string_from_utf8_lossy_owned)] - /// // some invalid bytes - /// let input: Vec = b"Hello \xF0\x90\x80World".into(); - /// let output = String::from_utf8(input).unwrap_or_else(|e| e.into_utf8_lossy()); - /// - /// assert_eq!(String::from("Hello �World"), output); - /// ``` - #[must_use] - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] - pub fn into_utf8_lossy(self) -> String { - const REPLACEMENT: &str = "\u{FFFD}"; - - let mut res = { - let mut v = Vec::with_capacity(self.bytes.len()); - - // `Utf8Error::valid_up_to` returns the maximum index of validated - // UTF-8 bytes. Copy the valid bytes into the output buffer. - v.extend_from_slice(&self.bytes[..self.error.valid_up_to()]); - - // SAFETY: This is safe because the only bytes present in the buffer - // were validated as UTF-8 by the call to `String::from_utf8` which - // produced this `FromUtf8Error`. - unsafe { String::from_utf8_unchecked(v) } - }; - - let iter = self.bytes[self.error.valid_up_to()..].utf8_chunks(); - - for chunk in iter { - res.push_str(chunk.valid()); - if !chunk.invalid().is_empty() { - res.push_str(REPLACEMENT); - } - } - - res - } - - /// Returns the bytes that were attempted to convert to a `String`. - /// - /// This method is carefully constructed to avoid allocation. It will - /// consume the error, moving out the bytes, so that a copy of the bytes - /// does not need to be made. - /// - /// # Examples - /// - /// ``` - /// // some invalid bytes, in a vector - /// let bytes = vec![0, 159]; - /// - /// let value = String::from_utf8(bytes); - /// - /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); - /// ``` - #[must_use = "`self` will be dropped if the result is not used"] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_bytes(self) -> Vec { - self.bytes - } - - /// Fetch a `Utf8Error` to get more details about the conversion failure. - /// - /// The [`Utf8Error`] type provided by [`std::str`] represents an error that may - /// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's - /// an analogue to `FromUtf8Error`. See its documentation for more details - /// on using it. - /// - /// [`std::str`]: core::str "std::str" - /// [`&str`]: prim@str "&str" - /// - /// # Examples - /// - /// ``` - /// // some invalid bytes, in a vector - /// let bytes = vec![0, 159]; - /// - /// let error = String::from_utf8(bytes).unwrap_err().utf8_error(); - /// - /// // the first byte is invalid here - /// assert_eq!(1, error.valid_up_to()); - /// ``` - #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn utf8_error(&self) -> Utf8Error { - self.error - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for FromUtf8Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.error, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for FromUtf16Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt("invalid utf-16: lone surrogate found", f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf8Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "invalid utf-8" - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf16Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "invalid utf-16" - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for String { - fn clone(&self) -> Self { - String { vec: self.vec.clone() } - } - - /// Clones the contents of `source` into `self`. - /// - /// This method is preferred over simply assigning `source.clone()` to `self`, - /// as it avoids reallocation if possible. - fn clone_from(&mut self, source: &Self) { - self.vec.clone_from(&source.vec); - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for String { - fn from_iter>(iter: I) -> String { - let mut buf = String::new(); - buf.extend(iter); - buf - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "string_from_iter_by_ref", since = "1.17.0")] -impl<'a> FromIterator<&'a char> for String { - fn from_iter>(iter: I) -> String { - let mut buf = String::new(); - buf.extend(iter); - buf - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> FromIterator<&'a str> for String { - fn from_iter>(iter: I) -> String { - let mut buf = String::new(); - buf.extend(iter); - buf - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "extend_string", since = "1.4.0")] -impl FromIterator for String { - fn from_iter>(iter: I) -> String { - let mut iterator = iter.into_iter(); - - // Because we're iterating over `String`s, we can avoid at least - // one allocation by getting the first string from the iterator - // and appending to it all the subsequent strings. - match iterator.next() { - None => String::new(), - Some(mut buf) => { - buf.extend(iterator); - buf - } - } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_str2", since = "1.45.0")] -impl FromIterator> for String { - fn from_iter>>(iter: I) -> String { - let mut buf = String::new(); - buf.extend(iter); - buf - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "herd_cows", since = "1.19.0")] -impl<'a> FromIterator> for String { - fn from_iter>>(iter: I) -> String { - let mut iterator = iter.into_iter(); - - // Because we're iterating over CoWs, we can (potentially) avoid at least - // one allocation by getting the first item and appending to it all the - // subsequent items. - match iterator.next() { - None => String::new(), - Some(cow) => { - let mut buf = cow.into_owned(); - buf.extend(iterator); - buf - } - } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl Extend for String { - fn extend>(&mut self, iter: I) { - let iterator = iter.into_iter(); - let (lower_bound, _) = iterator.size_hint(); - self.reserve(lower_bound); - iterator.for_each(move |c| self.push(c)); - } - - #[inline] - fn extend_one(&mut self, c: char) { - self.push(c); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - self.reserve(additional); - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a> Extend<&'a char> for String { - fn extend>(&mut self, iter: I) { - self.extend(iter.into_iter().cloned()); - } - - #[inline] - fn extend_one(&mut self, &c: &'a char) { - self.push(c); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - self.reserve(additional); - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> Extend<&'a str> for String { - fn extend>(&mut self, iter: I) { - iter.into_iter().for_each(move |s| self.push_str(s)); - } - - #[inline] - fn extend_one(&mut self, s: &'a str) { - self.push_str(s); - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_str2", since = "1.45.0")] -impl Extend> for String { - fn extend>>(&mut self, iter: I) { - iter.into_iter().for_each(move |s| self.push_str(&s)); - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "extend_string", since = "1.4.0")] -impl Extend for String { - fn extend>(&mut self, iter: I) { - iter.into_iter().for_each(move |s| self.push_str(&s)); - } - - #[inline] - fn extend_one(&mut self, s: String) { - self.push_str(&s); - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "herd_cows", since = "1.19.0")] -impl<'a> Extend> for String { - fn extend>>(&mut self, iter: I) { - iter.into_iter().for_each(move |s| self.push_str(&s)); - } - - #[inline] - fn extend_one(&mut self, s: Cow<'a, str>) { - self.push_str(&s); - } -} - -/// A convenience impl that delegates to the impl for `&str`. -/// -/// # Examples -/// -/// ``` -/// assert_eq!(String::from("Hello world").find("world"), Some(6)); -/// ``` -#[unstable( - feature = "pattern", - reason = "API not fully fleshed out and ready to be stabilized", - issue = "27721" -)] -impl<'b> Pattern for &'b String { - type Searcher<'a> = <&'b str as Pattern>::Searcher<'a>; - - fn into_searcher(self, haystack: &str) -> <&'b str as Pattern>::Searcher<'_> { - self[..].into_searcher(haystack) - } - - #[inline] - fn is_contained_in(self, haystack: &str) -> bool { - self[..].is_contained_in(haystack) - } - - #[inline] - fn is_prefix_of(self, haystack: &str) -> bool { - self[..].is_prefix_of(haystack) - } - - #[inline] - fn strip_prefix_of(self, haystack: &str) -> Option<&str> { - self[..].strip_prefix_of(haystack) - } - - #[inline] - fn is_suffix_of<'a>(self, haystack: &'a str) -> bool - where - Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, - { - self[..].is_suffix_of(haystack) - } - - #[inline] - fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> - where - Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, - { - self[..].strip_suffix_of(haystack) - } - - #[inline] - fn as_utf8_pattern(&self) -> Option> { - Some(Utf8Pattern::StringPattern(self.as_bytes())) - } -} - -macro_rules! impl_eq { - ($lhs:ty, $rhs: ty) => { - #[stable(feature = "rust1", since = "1.0.0")] - #[allow(unused_lifetimes)] - impl<'a, 'b> PartialEq<$rhs> for $lhs { - #[inline] - fn eq(&self, other: &$rhs) -> bool { - PartialEq::eq(&self[..], &other[..]) - } - #[inline] - fn ne(&self, other: &$rhs) -> bool { - PartialEq::ne(&self[..], &other[..]) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[allow(unused_lifetimes)] - impl<'a, 'b> PartialEq<$lhs> for $rhs { - #[inline] - fn eq(&self, other: &$lhs) -> bool { - PartialEq::eq(&self[..], &other[..]) - } - #[inline] - fn ne(&self, other: &$lhs) -> bool { - PartialEq::ne(&self[..], &other[..]) - } - } - }; -} - -impl_eq! { String, str } -impl_eq! { String, &'a str } -#[cfg(not(no_global_oom_handling))] -impl_eq! { Cow<'a, str>, str } -#[cfg(not(no_global_oom_handling))] -impl_eq! { Cow<'a, str>, &'b str } -#[cfg(not(no_global_oom_handling))] -impl_eq! { Cow<'a, str>, String } - -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for String { - /// Creates an empty `String`. - #[inline] - fn default() -> String { - String::new() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for String { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for String { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for String { - #[inline] - fn hash(&self, hasher: &mut H) { - (**self).hash(hasher) - } -} - -/// Implements the `+` operator for concatenating two strings. -/// -/// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if -/// necessary). This is done to avoid allocating a new `String` and copying the entire contents on -/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by -/// repeated concatenation. -/// -/// The string on the right-hand side is only borrowed; its contents are copied into the returned -/// `String`. -/// -/// # Examples -/// -/// Concatenating two `String`s takes the first by value and borrows the second: -/// -/// ``` -/// let a = String::from("hello"); -/// let b = String::from(" world"); -/// let c = a + &b; -/// // `a` is moved and can no longer be used here. -/// ``` -/// -/// If you want to keep using the first `String`, you can clone it and append to the clone instead: -/// -/// ``` -/// let a = String::from("hello"); -/// let b = String::from(" world"); -/// let c = a.clone() + &b; -/// // `a` is still valid here. -/// ``` -/// -/// Concatenating `&str` slices can be done by converting the first to a `String`: -/// -/// ``` -/// let a = "hello"; -/// let b = " world"; -/// let c = a.to_string() + b; -/// ``` -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl Add<&str> for String { - type Output = String; - - #[inline] - fn add(mut self, other: &str) -> String { - self.push_str(other); - self - } -} - -/// Implements the `+=` operator for appending to a `String`. -/// -/// This has the same behavior as the [`push_str`][String::push_str] method. -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "stringaddassign", since = "1.12.0")] -impl AddAssign<&str> for String { - #[inline] - fn add_assign(&mut self, other: &str) { - self.push_str(other); - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for String -where - I: slice::SliceIndex, -{ - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &I::Output { - index.index(self.as_str()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut for String -where - I: slice::SliceIndex, -{ - #[inline] - fn index_mut(&mut self, index: I) -> &mut I::Output { - index.index_mut(self.as_mut_str()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Deref for String { - type Target = str; - - #[inline] - fn deref(&self) -> &str { - self.as_str() - } -} - -#[unstable(feature = "deref_pure_trait", issue = "87121")] -unsafe impl ops::DerefPure for String {} - -#[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::DerefMut for String { - #[inline] - fn deref_mut(&mut self) -> &mut str { - self.as_mut_str() - } -} - -/// A type alias for [`Infallible`]. -/// -/// This alias exists for backwards compatibility, and may be eventually deprecated. -/// -/// [`Infallible`]: core::convert::Infallible "convert::Infallible" -#[stable(feature = "str_parse_error", since = "1.5.0")] -pub type ParseError = core::convert::Infallible; - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl FromStr for String { - type Err = core::convert::Infallible; - #[inline] - fn from_str(s: &str) -> Result { - Ok(String::from(s)) - } -} - -/// A trait for converting a value to a `String`. -/// -/// This trait is automatically implemented for any type which implements the -/// [`Display`] trait. As such, `ToString` shouldn't be implemented directly: -/// [`Display`] should be implemented instead, and you get the `ToString` -/// implementation for free. -/// -/// [`Display`]: fmt::Display -#[cfg_attr(not(test), rustc_diagnostic_item = "ToString")] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait ToString { - /// Converts the given value to a `String`. - /// - /// # Examples - /// - /// ``` - /// let i = 5; - /// let five = String::from("5"); - /// - /// assert_eq!(five, i.to_string()); - /// ``` - #[rustc_conversion_suggestion] - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "to_string_method")] - fn to_string(&self) -> String; -} - -/// # Panics -/// -/// In this implementation, the `to_string` method panics -/// if the `Display` implementation returns an error. -/// This indicates an incorrect `Display` implementation -/// since `fmt::Write for String` never returns an error itself. -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl ToString for T { - #[inline] - fn to_string(&self) -> String { - ::spec_to_string(self) - } -} - -#[cfg(not(no_global_oom_handling))] -trait SpecToString { - fn spec_to_string(&self) -> String; -} - -#[cfg(not(no_global_oom_handling))] -impl SpecToString for T { - // A common guideline is to not inline generic functions. However, - // removing `#[inline]` from this method causes non-negligible regressions. - // See , the last attempt - // to try to remove it. - #[inline] - default fn spec_to_string(&self) -> String { - let mut buf = String::new(); - let mut formatter = - core::fmt::Formatter::new(&mut buf, core::fmt::FormattingOptions::new()); - // Bypass format_args!() to avoid write_str with zero-length strs - fmt::Display::fmt(self, &mut formatter) - .expect("a Display implementation returned an error unexpectedly"); - buf - } -} - -#[cfg(not(no_global_oom_handling))] -impl SpecToString for core::ascii::Char { - #[inline] - fn spec_to_string(&self) -> String { - self.as_str().to_owned() - } -} - -#[cfg(not(no_global_oom_handling))] -impl SpecToString for char { - #[inline] - fn spec_to_string(&self) -> String { - String::from(self.encode_utf8(&mut [0; 4])) - } -} - -#[cfg(not(no_global_oom_handling))] -impl SpecToString for bool { - #[inline] - fn spec_to_string(&self) -> String { - String::from(if *self { "true" } else { "false" }) - } -} - -#[cfg(not(no_global_oom_handling))] -impl SpecToString for u8 { - #[inline] - fn spec_to_string(&self) -> String { - let mut buf = String::with_capacity(3); - let mut n = *self; - if n >= 10 { - if n >= 100 { - buf.push((b'0' + n / 100) as char); - n %= 100; - } - buf.push((b'0' + n / 10) as char); - n %= 10; - } - buf.push((b'0' + n) as char); - buf - } -} - -#[cfg(not(no_global_oom_handling))] -impl SpecToString for i8 { - #[inline] - fn spec_to_string(&self) -> String { - let mut buf = String::with_capacity(4); - if self.is_negative() { - buf.push('-'); - } - let mut n = self.unsigned_abs(); - if n >= 10 { - if n >= 100 { - buf.push('1'); - n -= 100; - } - buf.push((b'0' + n / 10) as char); - n %= 10; - } - buf.push((b'0' + n) as char); - buf - } -} +} // Generic/generated code can sometimes have multiple, nested references // for strings, including `&&&str`s that would never be written @@ -2854,7 +566,7 @@ macro_rules! to_string_str { } )+ }; -} + } #[cfg(not(no_global_oom_handling))] to_string_str! { @@ -2881,10 +593,10 @@ impl SpecToString for Cow<'_, str> { } #[cfg(not(no_global_oom_handling))] -impl SpecToString for String { +impl SpecToString for string::String { #[inline] fn spec_to_string(&self) -> String { - self.to_owned() + self[..].to_owned() } } @@ -2896,255 +608,6 @@ impl SpecToString for fmt::Arguments<'_> { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRef for String { - #[inline] - fn as_ref(&self) -> &str { - self - } -} - -#[stable(feature = "string_as_mut", since = "1.43.0")] -impl AsMut for String { - #[inline] - fn as_mut(&mut self) -> &mut str { - self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRef<[u8]> for String { - #[inline] - fn as_ref(&self) -> &[u8] { - self.as_bytes() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl From<&str> for String { - /// Converts a `&str` into a [`String`]. - /// - /// The result is allocated on the heap. - #[inline] - fn from(s: &str) -> String { - s.to_owned() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "from_mut_str_for_string", since = "1.44.0")] -impl From<&mut str> for String { - /// Converts a `&mut str` into a [`String`]. - /// - /// The result is allocated on the heap. - #[inline] - fn from(s: &mut str) -> String { - s.to_owned() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "from_ref_string", since = "1.35.0")] -impl From<&String> for String { - /// Converts a `&String` into a [`String`]. - /// - /// This clones `s` and returns the clone. - #[inline] - fn from(s: &String) -> String { - s.clone() - } -} - -// note: test pulls in std, which causes errors here -#[cfg(not(test))] -#[stable(feature = "string_from_box", since = "1.18.0")] -impl From> for String { - /// Converts the given boxed `str` slice to a [`String`]. - /// It is notable that the `str` slice is owned. - /// - /// # Examples - /// - /// ``` - /// let s1: String = String::from("hello world"); - /// let s2: Box = s1.into_boxed_str(); - /// let s3: String = String::from(s2); - /// - /// assert_eq!("hello world", s3) - /// ``` - fn from(s: Box) -> String { - s.into_string() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_str", since = "1.20.0")] -impl From for Box { - /// Converts the given [`String`] to a boxed `str` slice that is owned. - /// - /// # Examples - /// - /// ``` - /// let s1: String = String::from("hello world"); - /// let s2: Box = Box::from(s1); - /// let s3: String = String::from(s2); - /// - /// assert_eq!("hello world", s3) - /// ``` - fn from(s: String) -> Box { - s.into_boxed_str() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "string_from_cow_str", since = "1.14.0")] -impl<'a> From> for String { - /// Converts a clone-on-write string to an owned - /// instance of [`String`]. - /// - /// This extracts the owned string, - /// clones the string if it is not already owned. - /// - /// # Example - /// - /// ``` - /// # use std::borrow::Cow; - /// // If the string is not owned... - /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); - /// // It will allocate on the heap and copy the string. - /// let owned: String = String::from(cow); - /// assert_eq!(&owned[..], "eggplant"); - /// ``` - fn from(s: Cow<'a, str>) -> String { - s.into_owned() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&'a str> for Cow<'a, str> { - /// Converts a string slice into a [`Borrowed`] variant. - /// No heap allocation is performed, and the string - /// is not copied. - /// - /// # Example - /// - /// ``` - /// # use std::borrow::Cow; - /// assert_eq!(Cow::from("eggplant"), Cow::Borrowed("eggplant")); - /// ``` - /// - /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" - #[inline] - fn from(s: &'a str) -> Cow<'a, str> { - Cow::Borrowed(s) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From for Cow<'a, str> { - /// Converts a [`String`] into an [`Owned`] variant. - /// No heap allocation is performed, and the string - /// is not copied. - /// - /// # Example - /// - /// ``` - /// # use std::borrow::Cow; - /// let s = "eggplant".to_string(); - /// let s2 = "eggplant".to_string(); - /// assert_eq!(Cow::from(s), Cow::<'static, str>::Owned(s2)); - /// ``` - /// - /// [`Owned`]: crate::borrow::Cow::Owned "borrow::Cow::Owned" - #[inline] - fn from(s: String) -> Cow<'a, str> { - Cow::Owned(s) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "cow_from_string_ref", since = "1.28.0")] -impl<'a> From<&'a String> for Cow<'a, str> { - /// Converts a [`String`] reference into a [`Borrowed`] variant. - /// No heap allocation is performed, and the string - /// is not copied. - /// - /// # Example - /// - /// ``` - /// # use std::borrow::Cow; - /// let s = "eggplant".to_string(); - /// assert_eq!(Cow::from(&s), Cow::Borrowed("eggplant")); - /// ``` - /// - /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" - #[inline] - fn from(s: &'a String) -> Cow<'a, str> { - Cow::Borrowed(s.as_str()) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "cow_str_from_iter", since = "1.12.0")] -impl<'a> FromIterator for Cow<'a, str> { - fn from_iter>(it: I) -> Cow<'a, str> { - Cow::Owned(FromIterator::from_iter(it)) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "cow_str_from_iter", since = "1.12.0")] -impl<'a, 'b> FromIterator<&'b str> for Cow<'a, str> { - fn from_iter>(it: I) -> Cow<'a, str> { - Cow::Owned(FromIterator::from_iter(it)) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "cow_str_from_iter", since = "1.12.0")] -impl<'a> FromIterator for Cow<'a, str> { - fn from_iter>(it: I) -> Cow<'a, str> { - Cow::Owned(FromIterator::from_iter(it)) - } -} - -#[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] -impl From for Vec { - /// Converts the given [`String`] to a vector [`Vec`] that holds values of type [`u8`]. - /// - /// # Examples - /// - /// ``` - /// let s1 = String::from("hello world"); - /// let v1 = Vec::from(s1); - /// - /// for b in v1 { - /// println!("{b}"); - /// } - /// ``` - fn from(string: String) -> Vec { - string.into_bytes() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Write for String { - #[inline] - fn write_str(&mut self, s: &str) -> fmt::Result { - self.push_str(s); - Ok(()) - } - - #[inline] - fn write_char(&mut self, c: char) -> fmt::Result { - self.push(c); - Ok(()) - } -} - /// An iterator over the [`char`]s of a string. /// /// This struct is created by the [`into_chars`] method on [`String`]. @@ -3152,126 +615,8 @@ impl fmt::Write for String { /// /// [`char`]: prim@char /// [`into_chars`]: String::into_chars -#[cfg_attr(not(no_global_oom_handling), derive(Clone))] -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[unstable(feature = "string_into_chars", issue = "133125")] -pub struct IntoChars { - bytes: vec::IntoIter, -} - -#[unstable(feature = "string_into_chars", issue = "133125")] -impl fmt::Debug for IntoChars { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("IntoChars").field(&self.as_str()).finish() - } -} - -impl IntoChars { - /// Views the underlying data as a subslice of the original data. - /// - /// # Examples - /// - /// ``` - /// #![feature(string_into_chars)] - /// - /// let mut chars = String::from("abc").into_chars(); - /// - /// assert_eq!(chars.as_str(), "abc"); - /// chars.next(); - /// assert_eq!(chars.as_str(), "bc"); - /// chars.next(); - /// chars.next(); - /// assert_eq!(chars.as_str(), ""); - /// ``` - #[unstable(feature = "string_into_chars", issue = "133125")] - #[must_use] - #[inline] - pub fn as_str(&self) -> &str { - // SAFETY: `bytes` is a valid UTF-8 string. - unsafe { str::from_utf8_unchecked(self.bytes.as_slice()) } - } - - /// Consumes the `IntoChars`, returning the remaining string. - /// - /// # Examples - /// - /// ``` - /// #![feature(string_into_chars)] - /// - /// let chars = String::from("abc").into_chars(); - /// assert_eq!(chars.into_string(), "abc"); - /// - /// let mut chars = String::from("def").into_chars(); - /// chars.next(); - /// assert_eq!(chars.into_string(), "ef"); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "string_into_chars", issue = "133125")] - #[inline] - pub fn into_string(self) -> String { - // Safety: `bytes` are kept in UTF-8 form, only removing whole `char`s at a time. - unsafe { String::from_utf8_unchecked(self.bytes.collect()) } - } - - #[inline] - fn iter(&self) -> CharIndices<'_> { - self.as_str().char_indices() - } -} - -#[unstable(feature = "string_into_chars", issue = "133125")] -impl Iterator for IntoChars { - type Item = char; - - #[inline] - fn next(&mut self) -> Option { - let mut iter = self.iter(); - match iter.next() { - None => None, - Some((_, ch)) => { - let offset = iter.offset(); - // `offset` is a valid index. - let _ = self.bytes.advance_by(offset); - Some(ch) - } - } - } - - #[inline] - fn count(self) -> usize { - self.iter().count() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter().size_hint() - } - - #[inline] - fn last(mut self) -> Option { - self.next_back() - } -} - -#[unstable(feature = "string_into_chars", issue = "133125")] -impl DoubleEndedIterator for IntoChars { - #[inline] - fn next_back(&mut self) -> Option { - let len = self.as_str().len(); - let mut iter = self.iter(); - match iter.next_back() { - None => None, - Some((idx, ch)) => { - // `idx` is a valid index. - let _ = self.bytes.advance_back_by(len - idx); - Some(ch) - } - } - } -} - #[unstable(feature = "string_into_chars", issue = "133125")] -impl FusedIterator for IntoChars {} +pub type IntoChars = string::IntoChars; /// A draining iterator for `String`. /// @@ -3280,119 +625,4 @@ impl FusedIterator for IntoChars {} /// /// [`drain`]: String::drain #[stable(feature = "drain", since = "1.6.0")] -pub struct Drain<'a> { - /// Will be used as &'a mut String in the destructor - string: *mut String, - /// Start of part to remove - start: usize, - /// End of part to remove - end: usize, - /// Current remaining range to remove - iter: Chars<'a>, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Drain").field(&self.as_str()).finish() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_> {} -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_> {} - -#[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_> { - fn drop(&mut self) { - unsafe { - // Use Vec::drain. "Reaffirm" the bounds checks to avoid - // panic code being inserted again. - let self_vec = (*self.string).as_mut_vec(); - if self.start <= self.end && self.end <= self_vec.len() { - self_vec.drain(self.start..self.end); - } - } - } -} - -impl<'a> Drain<'a> { - /// Returns the remaining (sub)string of this iterator as a slice. - /// - /// # Examples - /// - /// ``` - /// let mut s = String::from("abc"); - /// let mut drain = s.drain(..); - /// assert_eq!(drain.as_str(), "abc"); - /// let _ = drain.next().unwrap(); - /// assert_eq!(drain.as_str(), "bc"); - /// ``` - #[must_use] - #[stable(feature = "string_drain_as_str", since = "1.55.0")] - pub fn as_str(&self) -> &str { - self.iter.as_str() - } -} - -#[stable(feature = "string_drain_as_str", since = "1.55.0")] -impl<'a> AsRef for Drain<'a> { - fn as_ref(&self) -> &str { - self.as_str() - } -} - -#[stable(feature = "string_drain_as_str", since = "1.55.0")] -impl<'a> AsRef<[u8]> for Drain<'a> { - fn as_ref(&self) -> &[u8] { - self.as_str().as_bytes() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_> { - type Item = char; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } - - #[inline] - fn last(mut self) -> Option { - self.next_back() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_> { - #[inline] - fn next_back(&mut self) -> Option { - self.iter.next_back() - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_> {} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "from_char_for_string", since = "1.46.0")] -impl From for String { - /// Allocates an owned [`String`] from a single character. - /// - /// # Example - /// ```rust - /// let c: char = 'a'; - /// let s: String = String::from(c); - /// assert_eq!("a", &s[..]); - /// ``` - #[inline] - fn from(c: char) -> Self { - c.to_string() - } -} +pub type Drain<'a> = string::Drain<'a, Global>; diff --git a/library/alloc/src/string/string.rs b/library/alloc/src/string/string.rs new file mode 100644 index 0000000000000..993375f11c389 --- /dev/null +++ b/library/alloc/src/string/string.rs @@ -0,0 +1,3175 @@ +//! A UTF-8–encoded, growable string, with allocator support. +//! +//! This module only exists due to type parameter defaults not affecting inference, +//! otherwise, [`alloc::string::String`][crate::string::String] would be the canonical location of `String`, +//! instead of a type alias. + +#![unstable(feature = "string_allocator_api", issue = "32838")] + +use core::cmp::Ordering; +use core::error::Error; +use core::iter::FusedIterator; +#[cfg(not(no_global_oom_handling))] +use core::iter::from_fn; +#[cfg(not(no_global_oom_handling))] +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{self, Range, RangeBounds}; +#[cfg(not(no_global_oom_handling))] +use core::ops::{Add, AddAssign}; +use core::str::pattern::{Pattern, Utf8Pattern}; +use core::{fmt, hash, ptr, slice}; + +use crate::alloc::{Allocator, Global}; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +use crate::str::{self, CharIndices, Chars, Utf8Error, from_utf8_unchecked_mut}; +#[cfg(not(no_global_oom_handling))] +use crate::str::{FromStr, from_boxed_utf8_unchecked}; +use crate::string::ToString; +use crate::vec::{self, Vec}; + +/// A UTF-8–encoded, growable string, with allocator support. +/// +/// The documentation for this type is located at [`alloc::string::String`][crate::string::String]. +/// +/// This is due to type parameter defaults not affecting inference. +/// Otherwise, `alloc::string::String` would be the canonical location of `String`, +/// instead of a type alias. +#[cfg_attr(not(test), lang = "String")] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct String<#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> { + vec: Vec, +} + +/// A possible error value when converting a `String` from a UTF-8 byte vector. +/// +/// This type is the error type for the [`from_utf8`] method on [`String`]. It +/// is designed in such a way to carefully avoid reallocations: the +/// [`into_bytes`] method will give back the byte vector that was used in the +/// conversion attempt. +/// +/// [`from_utf8`]: String::from_utf8 +/// [`into_bytes`]: FromUtf8Error::into_bytes +/// +/// The [`Utf8Error`] type provided by [`std::str`] represents an error that may +/// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's +/// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error` +/// through the [`utf8_error`] method. +/// +/// [`Utf8Error`]: str::Utf8Error "std::str::Utf8Error" +/// [`std::str`]: core::str "std::str" +/// [`&str`]: prim@str "&str" +/// [`utf8_error`]: FromUtf8Error::utf8_error +/// +/// # Examples +/// +/// ``` +/// // some invalid bytes, in a vector +/// let bytes = vec![0, 159]; +/// +/// let value = String::from_utf8(bytes); +/// +/// assert!(value.is_err()); +/// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(no_global_oom_handling), derive(Clone))] +pub struct FromUtf8Error< + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + bytes: Vec, + error: Utf8Error, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for FromUtf8Error {} // FIXME(zachs18): Structural(Partial)Eq? + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for FromUtf8Error { + fn eq(&self, other: &Self) -> bool { + self.bytes == other.bytes && self.error == other.error + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for FromUtf8Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FromUtf8Error") + .field("bytes", &self.bytes) + .field("error", &self.error) + .finish() + } +} + +/// A possible error value when converting a `String` from a UTF-16 byte slice. +/// +/// This type is the error type for the [`from_utf16`] method on [`String`]. +/// +/// [`from_utf16`]: String::from_utf16 +/// +/// # Examples +/// +/// ``` +/// // 𝄞muic +/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, +/// 0xD800, 0x0069, 0x0063]; +/// +/// assert!(String::from_utf16(v).is_err()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct FromUtf16Error(()); + +impl String { + /// Creates a new empty `String`. + /// + /// Given that the `String` is empty, this will not allocate any initial + /// buffer. While that means that this initial operation is very + /// inexpensive, it may cause excessive allocation later when you add + /// data. If you have an idea of how much data the `String` will hold, + /// consider the [`with_capacity`] method to prevent excessive + /// re-allocation. + /// + /// [`with_capacity`]: String::with_capacity + /// + /// # Examples + /// + /// ``` + /// let s = String::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_new")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub const fn new() -> String { + String { vec: Vec::new() } + } + + /// Creates a new empty `String` with at least the specified capacity. + /// + /// `String`s have an internal buffer to hold their data. The capacity is + /// the length of that buffer, and can be queried with the [`capacity`] + /// method. This method creates an empty `String`, but one with an initial + /// buffer that can hold at least `capacity` bytes. This is useful when you + /// may be appending a bunch of data to the `String`, reducing the number of + /// reallocations it needs to do. + /// + /// [`capacity`]: String::capacity + /// + /// If the given capacity is `0`, no allocation will occur, and this method + /// is identical to the [`new`] method. + /// + /// [`new`]: String::new + /// + /// # Examples + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// + /// // The String contains no chars, even though it has capacity for more + /// assert_eq!(s.len(), 0); + /// + /// // These are all done without reallocating... + /// let cap = s.capacity(); + /// for _ in 0..10 { + /// s.push('a'); + /// } + /// + /// assert_eq!(s.capacity(), cap); + /// + /// // ...but this may make the string reallocate + /// s.push('a'); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn with_capacity(capacity: usize) -> String { + String { vec: Vec::with_capacity(capacity) } + } + + /// Creates a new empty `String` with at least the specified capacity. + /// + /// # Errors + /// + /// Returns [`Err`] if the capacity exceeds `isize::MAX` bytes, + /// or if the memory allocator reports failure. + /// + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result { + Ok(String { vec: Vec::try_with_capacity(capacity)? }) + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Since we don't + // require this method for testing purposes, I'll just stub it + // NB see the slice::hack module in slice.rs for more information + #[inline] + #[cfg(test)] + #[allow(missing_docs)] + pub fn from_str(_: &str) -> String { + panic!("not available with cfg(test)"); + } +} + +impl String { + /// Creates a new empty `String` with the provided allocator. + /// + /// Given that the `String` is empty, this will not allocate any initial + /// buffer. While that means that this initial operation is very + /// inexpensive, it may cause excessive allocation later when you add + /// data. If you have an idea of how much data the `String` will hold, + /// consider the [`with_capacity_in`] method to prevent excessive + /// re-allocation. + /// + /// [`with_capacity_in`]: String::with_capacity_in + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(string_allocator_api)] + /// #![feature(allocator_api)] + /// + /// use std::string::string::String; + /// use std::alloc::System; + /// + /// let s = String::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + pub const fn new_in(alloc: A) -> String { + String { vec: Vec::new_in(alloc) } + } + + /// Creates a new empty `String` with at least the specified capacity with the provided allocator. + /// + /// `String`s have an internal buffer to hold their data. The capacity is + /// the length of that buffer, and can be queried with the [`capacity`] + /// method. This method creates an empty `String`, but one with an initial + /// buffer that can hold at least `capacity` bytes. This is useful when you + /// may be appending a bunch of data to the `String`, reducing the number of + /// reallocations it needs to do. + /// + /// [`capacity`]: String::capacity + /// + /// If the given capacity is `0`, no allocation will occur, and this method + /// is identical to the [`new_in`] method. + /// + /// [`new_in`]: String::new_in + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(string_allocator_api)] + /// #![feature(allocator_api)] + /// + /// use std::string::string::String; + /// use std::alloc::System; + /// + /// let mut s = String::with_capacity_in(10, System); + /// + /// // The String contains no chars, even though it has capacity for more + /// assert_eq!(s.len(), 0); + /// + /// // These are all done without reallocating... + /// let cap = s.capacity(); + /// for _ in 0..10 { + /// s.push('a'); + /// } + /// + /// assert_eq!(s.capacity(), cap); + /// + /// // ...but this may make the string reallocate + /// s.push('a'); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + pub fn with_capacity_in(capacity: usize, alloc: A) -> String { + String { vec: Vec::with_capacity_in(capacity, alloc) } + } + + /// Creates a new empty `String` with at least the specified capacity with the provided allocator. + /// + /// # Errors + /// + /// Returns [`Err`] if the capacity exceeds `isize::MAX` bytes, + /// or if the memory allocator reports failure. + /// + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result, TryReserveError> { + Ok(String { vec: Vec::try_with_capacity_in(capacity, alloc)? }) + } + + /// Converts a vector of bytes to a `String`. + /// + /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes + /// ([`Vec`]) is made of bytes, so this function converts between the + /// two. Not all byte slices are valid `String`s, however: `String` + /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that + /// the bytes are valid UTF-8, and then does the conversion. + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the validity check, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the check. + /// + /// This method will take care to not copy the vector, for efficiency's + /// sake. + /// + /// If you need a [`&str`] instead of a `String`, consider + /// [`str::from_utf8`]. + /// + /// The inverse of this method is [`into_bytes`]. + /// + /// # Errors + /// + /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the + /// provided bytes are not UTF-8. The vector you moved in is also included. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// // We know these bytes are valid, so we'll use `unwrap()`. + /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// // some invalid bytes, in a vector + /// let sparkle_heart = vec![0, 159, 146, 150]; + /// + /// assert!(String::from_utf8(sparkle_heart).is_err()); + /// ``` + /// + /// See the docs for [`FromUtf8Error`] for more details on what you can do + /// with this error. + /// + /// [`from_utf8_unchecked`]: String::from_utf8_unchecked + /// [`Vec`]: crate::vec::Vec "Vec" + /// [`&str`]: prim@str "&str" + /// [`into_bytes`]: String::into_bytes + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_from_utf8")] + pub fn from_utf8(vec: Vec) -> Result, FromUtf8Error> { + match str::from_utf8(&vec) { + Ok(..) => Ok(String { vec }), + Err(e) => Err(FromUtf8Error { bytes: vec, error: e }), + } + } + + /// Decomposes a `String` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the string (in bytes), the allocated capacity of the data + /// (in bytes), and the allocator. These are the same arguments in the same order as + /// the arguments to [`from_raw_parts_in`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `String`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `String` with the [`from_raw_parts_in`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts_in`]: String::from_raw_parts_in + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// #![feature(string_allocator_api)] + /// #![feature(allocator_api)] + /// use std::string::string::String; + /// use std::alloc::System; + /// let mut s = String::new_in(System); + /// s.push_str("hello"); + /// + /// let (ptr, len, cap, alloc) = s.into_raw_parts_with_alloc(); + /// + /// let rebuilt = unsafe { String::from_raw_parts_in(ptr, len, cap, alloc) }; + /// assert_eq!(rebuilt, "hello"); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts_with_alloc(self) -> (*mut u8, usize, usize, A) { + self.vec.into_raw_parts_with_alloc() + } + + /// Creates a new `String` from a length, capacity, pointer, and allocator. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * The memory at `buf` needs to have been previously allocated by the + /// allocator `alloc`, with a required alignment of exactly 1. + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the correct value. + /// * The first `length` bytes at `buf` need to be valid UTF-8. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example, it is normally **not** safe to + /// build a `String` from a pointer to a C `char` array containing UTF-8 + /// _unless_ you are certain that array was originally allocated by `alloc`. + /// + /// The ownership of `buf` is effectively transferred to the + /// `String` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(string_allocator_api)] + /// #![feature(allocator_api)] + /// + /// use std::string::string::String; + /// use std::mem; + /// use std::alloc::System; + /// + /// unsafe { + /// let mut s = String::new_in(System); + /// s.push_str("hello"); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent automatically dropping the String's data + /// let mut s = mem::ManuallyDrop::new(s); + /// + /// let ptr = s.as_mut_ptr(); + /// let len = s.len(); + /// let capacity = s.capacity(); + /// let alloc = s.allocator().clone(); + /// + /// let s = String::from_raw_parts_in(ptr, len, capacity, alloc); + /// + /// assert_eq!("hello", s); + /// } + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub unsafe fn from_raw_parts_in( + buf: *mut u8, + length: usize, + capacity: usize, + alloc: A, + ) -> String { + unsafe { String { vec: Vec::from_raw_parts_in(buf, length, capacity, alloc) } } + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.vec.allocator() + } + + fn from_utf8_lossy_in(v: &[u8], alloc: A) -> Result<&str, String> { + let mut iter = v.utf8_chunks(); + + let first_valid = if let Some(chunk) = iter.next() { + let valid = chunk.valid(); + if chunk.invalid().is_empty() { + debug_assert_eq!(valid.len(), v.len()); + return Ok(valid); + } + valid + } else { + return Ok(""); + }; + + const REPLACEMENT: &str = "\u{FFFD}"; + + let mut res = String::with_capacity_in(v.len(), alloc); + res.push_str(first_valid); + res.push_str(REPLACEMENT); + + for chunk in iter { + res.push_str(chunk.valid()); + if !chunk.invalid().is_empty() { + res.push_str(REPLACEMENT); + } + } + + Err(res) + } +} + +impl String { + /// Converts a slice of bytes to a string, including invalid characters. + /// + /// Strings are made of bytes ([`u8`]), and a slice of bytes + /// ([`&[u8]`][byteslice]) is made of bytes, so this function converts + /// between the two. Not all byte slices are valid strings, however: strings + /// are required to be valid UTF-8. During this conversion, + /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with + /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: � + /// + /// [byteslice]: prim@slice + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the conversion, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the checks. + /// + /// [`from_utf8_unchecked`]: String::from_utf8_unchecked + /// + /// This function returns a [`Cow<'a, str>`]. If our byte slice is invalid + /// UTF-8, then we need to insert the replacement characters, which will + /// change the size of the string, and hence, require a `String`. But if + /// it's already valid UTF-8, we don't need a new allocation. This return + /// type allows us to handle both cases. + /// + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = String::from_utf8_lossy(&sparkle_heart); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// // some invalid bytes + /// let input = b"Hello \xF0\x90\x80World"; + /// let output = String::from_utf8_lossy(input); + /// + /// assert_eq!("Hello �World", output); + /// ``` + #[must_use] + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { + match String::from_utf8_lossy_in(v, Global) { + Ok(s) => Cow::Borrowed(s), + Err(s) => Cow::Owned(s), + } + } + + /// Converts a [`Vec`] to a `String`, substituting invalid UTF-8 + /// sequences with replacement characters. + /// + /// See [`from_utf8_lossy`] for more details. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// + /// Note that this function does not guarantee reuse of the original `Vec` + /// allocation. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = String::from_utf8_lossy_owned(sparkle_heart); + /// + /// assert_eq!(String::from("💖"), sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some invalid bytes + /// let input: Vec = b"Hello \xF0\x90\x80World".into(); + /// let output = String::from_utf8_lossy_owned(input); + /// + /// assert_eq!(String::from("Hello �World"), output); + /// ``` + #[must_use] + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] + pub fn from_utf8_lossy_owned(v: Vec) -> String { + if let Cow::Owned(string) = String::from_utf8_lossy(&v) { + string + } else { + // SAFETY: `String::from_utf8_lossy`'s contract ensures that if + // it returns a `Cow::Borrowed`, it is a valid UTF-8 string. + // Otherwise, it returns a new allocation of an owned `String`, with + // replacement characters for invalid sequences, which is returned + // above. + unsafe { String::from_utf8_unchecked(v) } + } + } + + /// Decode a native endian UTF-16–encoded vector `v` into a `String`, + /// returning [`Err`] if `v` contains any invalid data. + /// + /// # Examples + /// + /// ``` + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0x0073, 0x0069, 0x0063]; + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16(v).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0xD800, 0x0069, 0x0063]; + /// assert!(String::from_utf16(v).is_err()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf16(v: &[u16]) -> Result { + // This isn't done via collect::>() for performance reasons. + // FIXME: the function can be simplified again when #48994 is closed. + let mut ret = String::with_capacity(v.len()); + for c in char::decode_utf16(v.iter().cloned()) { + if let Ok(c) = c { + ret.push(c); + } else { + return Err(FromUtf16Error(())); + } + } + Ok(ret) + } + + /// Decode a native endian UTF-16–encoded slice `v` into a `String`, + /// replacing invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// ``` + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0x0073, 0xDD1E, 0x0069, 0x0063, + /// 0xD834]; + /// + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16_lossy(v)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[must_use] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf16_lossy(v: &[u16]) -> String { + char::decode_utf16(v.iter().cloned()) + .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) + .collect() + } + + /// Decode a UTF-16LE–encoded vector `v` into a `String`, + /// returning [`Err`] if `v` contains any invalid data. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // 𝄞music + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x73, 0x00, 0x69, 0x00, 0x63, 0x00]; + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16le(v).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x00, 0xD8, 0x69, 0x00, 0x63, 0x00]; + /// assert!(String::from_utf16le(v).is_err()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] + pub fn from_utf16le(v: &[u8]) -> Result { + if v.len() % 2 != 0 { + return Err(FromUtf16Error(())); + } + match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { + (true, ([], v, [])) => Self::from_utf16(v), + _ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes)) + .collect::>() + .map_err(|_| FromUtf16Error(())), + } + } + + /// Decode a UTF-16LE–encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // 𝄞music + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x73, 0x00, 0x1E, 0xDD, 0x69, 0x00, 0x63, 0x00, + /// 0x34, 0xD8]; + /// + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16le_lossy(v)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] + pub fn from_utf16le_lossy(v: &[u8]) -> String { + match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { + (true, ([], v, [])) => Self::from_utf16_lossy(v), + (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", + _ => { + let mut iter = v.array_chunks::<2>(); + let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes)) + .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) + .collect(); + if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } + } + } + } + + /// Decode a UTF-16BE–encoded vector `v` into a `String`, + /// returning [`Err`] if `v` contains any invalid data. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // 𝄞music + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0x00, 0x73, 0x00, 0x69, 0x00, 0x63]; + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16be(v).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0xD8, 0x00, 0x00, 0x69, 0x00, 0x63]; + /// assert!(String::from_utf16be(v).is_err()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] + pub fn from_utf16be(v: &[u8]) -> Result { + if v.len() % 2 != 0 { + return Err(FromUtf16Error(())); + } + match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { + (true, ([], v, [])) => Self::from_utf16(v), + _ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes)) + .collect::>() + .map_err(|_| FromUtf16Error(())), + } + } + + /// Decode a UTF-16BE–encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // 𝄞music + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0x00, 0x73, 0xDD, 0x1E, 0x00, 0x69, 0x00, 0x63, + /// 0xD8, 0x34]; + /// + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16be_lossy(v)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] + pub fn from_utf16be_lossy(v: &[u8]) -> String { + match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { + (true, ([], v, [])) => Self::from_utf16_lossy(v), + (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", + _ => { + let mut iter = v.array_chunks::<2>(); + let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes)) + .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) + .collect(); + if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } + } + } + } + + /// Decomposes a `String` into its raw components: `(pointer, length, capacity)`. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the string (in bytes), and the allocated capacity of the data + /// (in bytes). These are the same arguments in the same order as + /// the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `String`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `String` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: String::from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let s = String::from("hello"); + /// + /// let (ptr, len, cap) = s.into_raw_parts(); + /// + /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; + /// assert_eq!(rebuilt, "hello"); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { + self.vec.into_raw_parts() + } + + /// Creates a new `String` from a pointer, a length and a capacity. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * The memory at `buf` needs to have been previously allocated by the + /// same allocator the standard library uses, with a required alignment of exactly 1. + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the correct value. + /// * The first `length` bytes at `buf` need to be valid UTF-8. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example, it is normally **not** safe to + /// build a `String` from a pointer to a C `char` array containing UTF-8 + /// _unless_ you are certain that array was originally allocated by the + /// Rust standard library's allocator. + /// + /// The ownership of `buf` is effectively transferred to the + /// `String` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// # Examples + /// + /// ``` + /// use std::mem; + /// + /// unsafe { + /// let s = String::from("hello"); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent automatically dropping the String's data + /// let mut s = mem::ManuallyDrop::new(s); + /// + /// let ptr = s.as_mut_ptr(); + /// let len = s.len(); + /// let capacity = s.capacity(); + /// + /// let s = String::from_raw_parts(ptr, len, capacity); + /// + /// assert_eq!(String::from("hello"), s); + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { + unsafe { String { vec: Vec::from_raw_parts(buf, length, capacity) } } + } +} + +impl String { + /// Converts a vector of bytes to a `String` without checking that the + /// string contains valid UTF-8. + /// + /// See the safe version, [`from_utf8`], for more details. + /// + /// [`from_utf8`]: String::from_utf8 + /// + /// # Safety + /// + /// This function is unsafe because it does not check that the bytes passed + /// to it are valid UTF-8. If this constraint is violated, it may cause + /// memory unsafety issues with future users of the `String`, as the rest of + /// the standard library assumes that `String`s are valid UTF-8. + /// + /// # Examples + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = unsafe { + /// String::from_utf8_unchecked(sparkle_heart) + /// }; + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_utf8_unchecked(bytes: Vec) -> String { + String { vec: bytes } + } + + /// Converts a `String` into a byte vector. + /// + /// This consumes the `String`, so we do not need to copy its contents. + /// + /// # Examples + /// + /// ``` + /// let s = String::from("hello"); + /// let bytes = s.into_bytes(); + /// + /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]); + /// ``` + #[inline] + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn into_bytes(self) -> Vec { + self.vec + } + + /// Extracts a string slice containing the entire `String`. + /// + /// # Examples + /// + /// ``` + /// let s = String::from("foo"); + /// + /// assert_eq!("foo", s.as_str()); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "string_as_str", since = "1.7.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_str(&self) -> &str { + // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error + // at construction. + unsafe { str::from_utf8_unchecked(self.vec.as_slice()) } + } + + /// Converts a `String` into a mutable string slice. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foobar"); + /// let s_mut_str = s.as_mut_str(); + /// + /// s_mut_str.make_ascii_uppercase(); + /// + /// assert_eq!("FOOBAR", s_mut_str); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "string_as_str", since = "1.7.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_mut_str(&mut self) -> &mut str { + // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error + // at construction. + unsafe { str::from_utf8_unchecked_mut(self.vec.as_mut_slice()) } + } + + /// Appends a given string slice onto the end of this `String`. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.push_str("bar"); + /// + /// assert_eq!("foobar", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("append", "push")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_push_str")] + pub fn push_str(&mut self, string: &str) { + self.vec.extend_from_slice(string.as_bytes()) + } + + /// Copies elements from `src` range to the end of the string. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_extend_from_within)] + /// let mut string = String::from("abcde"); + /// + /// string.extend_from_within(2..); + /// assert_eq!(string, "abcdecde"); + /// + /// string.extend_from_within(..2); + /// assert_eq!(string, "abcdecdeab"); + /// + /// string.extend_from_within(4..8); + /// assert_eq!(string, "abcdecdeabecde"); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_extend_from_within", issue = "103806")] + pub fn extend_from_within(&mut self, src: R) + where + R: RangeBounds, + { + let src @ Range { start, end } = slice::range(src, ..self.len()); + + assert!(self.is_char_boundary(start)); + assert!(self.is_char_boundary(end)); + + self.vec.extend_from_within(src); + } + + /// Returns this `String`'s capacity, in bytes. + /// + /// # Examples + /// + /// ``` + /// let s = String::with_capacity(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn capacity(&self) -> usize { + self.vec.capacity() + } + + /// Reserves capacity for at least `additional` bytes more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity overflows [`usize`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::new(); + /// + /// s.reserve(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + /// + /// This might not actually increase the capacity: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of at least 10 + /// let capacity = s.capacity(); + /// assert_eq!(2, s.len()); + /// assert!(capacity >= 10); + /// + /// // Since we already have at least an extra 8 capacity, calling this... + /// s.reserve(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(capacity, s.capacity()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + self.vec.reserve(additional) + } + + /// Reserves the minimum capacity for at least `additional` bytes more than + /// the current length. Unlike [`reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional`. Does nothing if the capacity is already + /// sufficient. + /// + /// [`reserve`]: String::reserve + /// + /// # Panics + /// + /// Panics if the new capacity overflows [`usize`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::new(); + /// + /// s.reserve_exact(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + /// + /// This might not actually increase the capacity: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of at least 10 + /// let capacity = s.capacity(); + /// assert_eq!(2, s.len()); + /// assert!(capacity >= 10); + /// + /// // Since we already have at least an extra 8 capacity, calling this... + /// s.reserve_exact(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(capacity, s.capacity()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.vec.reserve_exact(additional) + } + + /// Tries to reserve capacity for at least `additional` bytes more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut output = String::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.push_str(data); + /// + /// Ok(output) + /// } + /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); + /// ``` + #[stable(feature = "try_reserve", since = "1.57.0")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.vec.try_reserve(additional) + } + + /// Tries to reserve the minimum capacity for at least `additional` bytes + /// more than the current length. Unlike [`try_reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `try_reserve_exact`, capacity will be greater than or + /// equal to `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: String::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut output = String::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.push_str(data); + /// + /// Ok(output) + /// } + /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); + /// ``` + #[stable(feature = "try_reserve", since = "1.57.0")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.vec.try_reserve_exact(additional) + } + + /// Shrinks the capacity of this `String` to match its length. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to_fit(); + /// assert_eq!(3, s.capacity()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn shrink_to_fit(&mut self) { + self.vec.shrink_to_fit() + } + + /// Shrinks the capacity of this `String` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "shrink_to", since = "1.56.0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.vec.shrink_to(min_capacity) + } + + /// Appends the given [`char`] to the end of this `String`. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("abc"); + /// + /// s.push('1'); + /// s.push('2'); + /// s.push('3'); + /// + /// assert_eq!("abc123", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push(&mut self, ch: char) { + match ch.len_utf8() { + 1 => self.vec.push(ch as u8), + _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()), + } + } + + /// Returns a byte slice of this `String`'s contents. + /// + /// The inverse of this method is [`from_utf8`]. + /// + /// [`from_utf8`]: String::from_utf8 + /// + /// # Examples + /// + /// ``` + /// let s = String::from("hello"); + /// + /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_bytes(&self) -> &[u8] { + self.vec.as_slice() + } + + /// Shortens this `String` to the specified length. + /// + /// If `new_len` is greater than or equal to the string's current length, this has no + /// effect. + /// + /// Note that this method has no effect on the allocated capacity + /// of the string + /// + /// # Panics + /// + /// Panics if `new_len` does not lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("hello"); + /// + /// s.truncate(2); + /// + /// assert_eq!("he", s); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn truncate(&mut self, new_len: usize) { + if new_len <= self.len() { + assert!(self.is_char_boundary(new_len)); + self.vec.truncate(new_len) + } + } + + /// Removes the last character from the string buffer and returns it. + /// + /// Returns [`None`] if this `String` is empty. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("abč"); + /// + /// assert_eq!(s.pop(), Some('č')); + /// assert_eq!(s.pop(), Some('b')); + /// assert_eq!(s.pop(), Some('a')); + /// + /// assert_eq!(s.pop(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop(&mut self) -> Option { + let ch = self.chars().rev().next()?; + let newlen = self.len() - ch.len_utf8(); + unsafe { + self.vec.set_len(newlen); + } + Some(ch) + } + + /// Removes a [`char`] from this `String` at a byte position and returns it. + /// + /// This is an *O*(*n*) operation, as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than or equal to the `String`'s length, + /// or if it does not lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("abç"); + /// + /// assert_eq!(s.remove(0), 'a'); + /// assert_eq!(s.remove(1), 'ç'); + /// assert_eq!(s.remove(0), 'b'); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] + pub fn remove(&mut self, idx: usize) -> char { + let ch = match self[idx..].chars().next() { + Some(ch) => ch, + None => panic!("cannot remove a char from the end of a string"), + }; + + let next = idx + ch.len_utf8(); + let len = self.len(); + unsafe { + ptr::copy(self.vec.as_ptr().add(next), self.vec.as_mut_ptr().add(idx), len - next); + self.vec.set_len(len - (next - idx)); + } + ch + } + + /// Remove all matches of pattern `pat` in the `String`. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_remove_matches)] + /// let mut s = String::from("Trees are not green, the sky is not blue."); + /// s.remove_matches("not "); + /// assert_eq!("Trees are green, the sky is blue.", s); + /// ``` + /// + /// Matches will be detected and removed iteratively, so in cases where + /// patterns overlap, only the first pattern will be removed: + /// + /// ``` + /// #![feature(string_remove_matches)] + /// let mut s = String::from("banana"); + /// s.remove_matches("ana"); + /// assert_eq!("bna", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")] + pub fn remove_matches(&mut self, pat: P) { + use core::str::pattern::Searcher; + + let rejections = { + let mut searcher = pat.into_searcher(self); + // Per Searcher::next: + // + // A Match result needs to contain the whole matched pattern, + // however Reject results may be split up into arbitrary many + // adjacent fragments. Both ranges may have zero length. + // + // In practice the implementation of Searcher::next_match tends to + // be more efficient, so we use it here and do some work to invert + // matches into rejections since that's what we want to copy below. + let mut front = 0; + let rejections: Vec<_> = from_fn(|| { + let (start, end) = searcher.next_match()?; + let prev_front = front; + front = end; + Some((prev_front, start)) + }) + .collect(); + rejections.into_iter().chain(core::iter::once((front, self.len()))) + }; + + let mut len = 0; + let ptr = self.vec.as_mut_ptr(); + + for (start, end) in rejections { + let count = end - start; + if start != len { + // SAFETY: per Searcher::next: + // + // The stream of Match and Reject values up to a Done will + // contain index ranges that are adjacent, non-overlapping, + // covering the whole haystack, and laying on utf8 + // boundaries. + unsafe { + ptr::copy(ptr.add(start), ptr.add(len), count); + } + } + len += count; + } + + unsafe { + self.vec.set_len(len); + } + } + + /// Retains only the characters specified by the predicate. + /// + /// In other words, remove all characters `c` such that `f(c)` returns `false`. + /// This method operates in place, visiting each character exactly once in the + /// original order, and preserves the order of the retained characters. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("f_o_ob_ar"); + /// + /// s.retain(|c| c != '_'); + /// + /// assert_eq!(s, "foobar"); + /// ``` + /// + /// Because the elements are visited exactly once in the original order, + /// external state may be used to decide which elements to keep. + /// + /// ``` + /// let mut s = String::from("abcde"); + /// let keep = [false, true, true, false, true]; + /// let mut iter = keep.iter(); + /// s.retain(|_| *iter.next().unwrap()); + /// assert_eq!(s, "bce"); + /// ``` + #[inline] + #[stable(feature = "string_retain", since = "1.26.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(char) -> bool, + { + struct SetLenOnDrop<'a, A: Allocator> { + s: &'a mut String, + idx: usize, + del_bytes: usize, + } + + impl<'a, A: Allocator> Drop for SetLenOnDrop<'a, A> { + fn drop(&mut self) { + let new_len = self.idx - self.del_bytes; + debug_assert!(new_len <= self.s.len()); + unsafe { self.s.vec.set_len(new_len) }; + } + } + + let len = self.len(); + let mut guard = SetLenOnDrop { s: self, idx: 0, del_bytes: 0 }; + + while guard.idx < len { + let ch = + // SAFETY: `guard.idx` is positive-or-zero and less that len so the `get_unchecked` + // is in bound. `self` is valid UTF-8 like string and the returned slice starts at + // a unicode code point so the `Chars` always return one character. + unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap_unchecked() }; + let ch_len = ch.len_utf8(); + + if !f(ch) { + guard.del_bytes += ch_len; + } else if guard.del_bytes > 0 { + // SAFETY: `guard.idx` is in bound and `guard.del_bytes` represent the number of + // bytes that are erased from the string so the resulting `guard.idx - + // guard.del_bytes` always represent a valid unicode code point. + // + // `guard.del_bytes` >= `ch.len_utf8()`, so taking a slice with `ch.len_utf8()` len + // is safe. + ch.encode_utf8(unsafe { + crate::slice::from_raw_parts_mut( + guard.s.as_mut_ptr().add(guard.idx - guard.del_bytes), + ch.len_utf8(), + ) + }); + } + + // Point idx to the next char + guard.idx += ch_len; + } + + drop(guard); + } + + /// Inserts a character into this `String` at a byte position. + /// + /// This is an *O*(*n*) operation as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::with_capacity(3); + /// + /// s.insert(0, 'f'); + /// s.insert(1, 'o'); + /// s.insert(2, 'o'); + /// + /// assert_eq!("foo", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("set")] + pub fn insert(&mut self, idx: usize, ch: char) { + assert!(self.is_char_boundary(idx)); + let mut bits = [0; 4]; + let bits = ch.encode_utf8(&mut bits).as_bytes(); + + unsafe { + self.insert_bytes(idx, bits); + } + } + + #[cfg(not(no_global_oom_handling))] + unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { + let len = self.len(); + let amt = bytes.len(); + self.vec.reserve(amt); + + unsafe { + ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); + ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); + self.vec.set_len(len + amt); + } + } + + /// Inserts a string slice into this `String` at a byte position. + /// + /// This is an *O*(*n*) operation as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("bar"); + /// + /// s.insert_str(0, "foo"); + /// + /// assert_eq!("foobar", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "insert_str", since = "1.16.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_insert_str")] + pub fn insert_str(&mut self, idx: usize, string: &str) { + assert!(self.is_char_boundary(idx)); + + unsafe { + self.insert_bytes(idx, string.as_bytes()); + } + } + + /// Returns a mutable reference to the contents of this `String`. + /// + /// # Safety + /// + /// This function is unsafe because the returned `&mut Vec` allows writing + /// bytes which are not valid UTF-8. If this constraint is violated, using + /// the original `String` after dropping the `&mut Vec` may violate memory + /// safety, as the rest of the standard library assumes that `String`s are + /// valid UTF-8. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("hello"); + /// + /// unsafe { + /// let vec = s.as_mut_vec(); + /// assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]); + /// + /// vec.reverse(); + /// } + /// assert_eq!(s, "olleh"); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec { + &mut self.vec + } + + /// Returns the length of this `String`, in bytes, not [`char`]s or + /// graphemes. In other words, it might not be what a human considers the + /// length of the string. + /// + /// # Examples + /// + /// ``` + /// let a = String::from("foo"); + /// assert_eq!(a.len(), 3); + /// + /// let fancy_f = String::from("ƒoo"); + /// assert_eq!(fancy_f.len(), 4); + /// assert_eq!(fancy_f.chars().count(), 3); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + #[rustc_confusables("length", "size")] + pub const fn len(&self) -> usize { + self.vec.len() + } + + /// Returns `true` if this `String` has a length of zero, and `false` otherwise. + /// + /// # Examples + /// + /// ``` + /// let mut v = String::new(); + /// assert!(v.is_empty()); + /// + /// v.push('a'); + /// assert!(!v.is_empty()); + /// ``` + #[inline] + #[must_use] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the string into two at the given byte index. + /// + /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and + /// the returned `String` contains bytes `[at, len)`. `at` must be on the + /// boundary of a UTF-8 code point. + /// + /// Note that the capacity of `self` does not change. + /// + /// # Panics + /// + /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last + /// code point of the string. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// let mut hello = String::from("Hello, World!"); + /// let world = hello.split_off(7); + /// assert_eq!(hello, "Hello, "); + /// assert_eq!(world, "World!"); + /// # } + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "string_split_off", since = "1.16.0")] + #[must_use = "use `.truncate()` if you don't need the other half"] + pub fn split_off(&mut self, at: usize) -> String + where + A: Clone, + { + assert!(self.is_char_boundary(at)); + let other = self.vec.split_off(at); + unsafe { String::from_utf8_unchecked(other) } + } + + /// Truncates this `String`, removing all contents. + /// + /// While this means the `String` will have a length of zero, it does not + /// touch its capacity. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.clear(); + /// + /// assert!(s.is_empty()); + /// assert_eq!(0, s.len()); + /// assert_eq!(3, s.capacity()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.vec.clear() + } + + /// Removes the specified range from the string in bulk, returning all + /// removed characters as an iterator. + /// + /// The returned iterator keeps a mutable borrow on the string to optimize + /// its implementation. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`core::mem::forget`], for example), the string may still contain a copy + /// of any drained characters, or may have lost characters arbitrarily, + /// including characters outside the range. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("α is alpha, β is beta"); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Remove the range up until the β from the string + /// let t: String = s.drain(..beta_offset).collect(); + /// assert_eq!(t, "α is alpha, "); + /// assert_eq!(s, "β is beta"); + /// + /// // A full range clears the string, like `clear()` does + /// s.drain(..); + /// assert_eq!(s, ""); + /// ``` + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_, A> + where + R: RangeBounds, + { + // Memory safety + // + // The String version of Drain does not have the memory safety issues + // of the vector version. The data is just plain bytes. + // Because the range removal happens in Drop, if the Drain iterator is leaked, + // the removal will not happen. + let Range { start, end } = slice::range(range, ..self.len()); + assert!(self.is_char_boundary(start)); + assert!(self.is_char_boundary(end)); + + // Take out two simultaneous borrows. The &mut String won't be accessed + // until iteration is over, in Drop. + let self_ptr = self as *mut _; + // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks. + let chars_iter = unsafe { self.get_unchecked(start..end) }.chars(); + + Drain { start, end, iter: chars_iter, string: self_ptr } + } + + /// Converts a `String` into an iterator over the [`char`]s of the string. + /// + /// As a string consists of valid UTF-8, we can iterate through a string + /// by [`char`]. This method returns such an iterator. + /// + /// It's important to remember that [`char`] represents a Unicode Scalar + /// Value, and might not match your idea of what a 'character' is. Iteration + /// over grapheme clusters may be what you actually want. That functionality + /// is not provided by Rust's standard library, check crates.io instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(string_into_chars)] + /// + /// let word = String::from("goodbye"); + /// + /// let mut chars = word.into_chars(); + /// + /// assert_eq!(Some('g'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('d'), chars.next()); + /// assert_eq!(Some('b'), chars.next()); + /// assert_eq!(Some('y'), chars.next()); + /// assert_eq!(Some('e'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + /// + /// Remember, [`char`]s might not match your intuition about characters: + /// + /// ``` + /// #![feature(string_into_chars)] + /// + /// let y = String::from("y̆"); + /// + /// let mut chars = y.into_chars(); + /// + /// assert_eq!(Some('y'), chars.next()); // not 'y̆' + /// assert_eq!(Some('\u{0306}'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + /// + /// [`char`]: prim@char + #[inline] + #[must_use = "`self` will be dropped if the result is not used"] + #[unstable(feature = "string_into_chars", issue = "133125")] + pub fn into_chars(self) -> IntoChars { + IntoChars { bytes: self.into_bytes().into_iter() } + } + + /// Removes the specified range in the string, + /// and replaces it with the given string. + /// The given string doesn't need to be the same length as the range. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("α is alpha, β is beta"); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Replace the range up until the β from the string + /// s.replace_range(..beta_offset, "Α is capital alpha; "); + /// assert_eq!(s, "Α is capital alpha; β is beta"); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "splice", since = "1.27.0")] + pub fn replace_range(&mut self, range: R, replace_with: &str) + where + R: RangeBounds, + { + // Memory safety + // + // Replace_range does not have the memory safety issues of a vector Splice. + // of the vector version. The data is just plain bytes. + + // WARNING: Inlining this variable would be unsound (#81138) + let start = range.start_bound(); + match start { + Included(&n) => assert!(self.is_char_boundary(n)), + Excluded(&n) => assert!(self.is_char_boundary(n + 1)), + Unbounded => {} + }; + // WARNING: Inlining this variable would be unsound (#81138) + let end = range.end_bound(); + match end { + Included(&n) => assert!(self.is_char_boundary(n + 1)), + Excluded(&n) => assert!(self.is_char_boundary(n)), + Unbounded => {} + }; + + // Using `range` again would be unsound (#81138) + // We assume the bounds reported by `range` remain the same, but + // an adversarial implementation could change between calls + unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes()); + } + + /// Converts this `String` into a [Box]<[str]>. + /// + /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`]. + /// Note that this call may reallocate and copy the bytes of the string. + /// + /// [`shrink_to_fit`]: String::shrink_to_fit + /// [str]: prim@str "str" + /// + /// # Examples + /// + /// ``` + /// let s = String::from("hello"); + /// + /// let b = s.into_boxed_str(); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "box_str", since = "1.4.0")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub fn into_boxed_str(self) -> Box { + let slice = self.vec.into_boxed_slice(); + unsafe { from_boxed_utf8_unchecked(slice) } + } + + /// Consumes and leaks the `String`, returning a mutable reference to the contents, + /// `&'a mut str`. + /// + /// The caller has free choice over the returned lifetime, including `'static`. Indeed, + /// this function is ideally used for data that lives for the remainder of the program's life, + /// as dropping the returned reference will cause a memory leak. + /// + /// It does not reallocate or shrink the `String`, so the leaked allocation may include unused + /// capacity that is not part of the returned slice. If you want to discard excess capacity, + /// call [`into_boxed_str`], and then [`Box::leak`] instead. However, keep in mind that + /// trimming the capacity may result in a reallocation and copy. + /// + /// [`into_boxed_str`]: Self::into_boxed_str + /// + /// # Examples + /// + /// ``` + /// let x = String::from("bucket"); + /// let static_ref: &'static mut str = x.leak(); + /// assert_eq!(static_ref, "bucket"); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); + /// ``` + #[stable(feature = "string_leak", since = "1.72.0")] + #[inline] + pub fn leak<'a>(self) -> &'a mut str + where + A: 'a, + { + let slice = self.vec.leak(); + unsafe { from_utf8_unchecked_mut(slice) } + } +} + +impl FromUtf8Error { + /// Returns a slice of [`u8`]s bytes that were attempted to convert to a `String`. + /// + /// # Examples + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let value = String::from_utf8(bytes); + /// + /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); + /// ``` + #[must_use] + #[stable(feature = "from_utf8_error_as_bytes", since = "1.26.0")] + pub fn as_bytes(&self) -> &[u8] { + &self.bytes[..] + } + + /// Converts the bytes into a `String` lossily, substituting invalid UTF-8 + /// sequences with replacement characters. + /// + /// See [`String::from_utf8_lossy`] for more details on replacement of + /// invalid sequences, and [`String::from_utf8_lossy_owned`] for the + /// `String` function which corresponds to this function. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some invalid bytes + /// let input: Vec = b"Hello \xF0\x90\x80World".into(); + /// let output = String::from_utf8(input).unwrap_or_else(|e| e.into_utf8_lossy()); + /// + /// assert_eq!(String::from("Hello �World"), output); + /// ``` + #[must_use] + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] + pub fn into_utf8_lossy(self) -> String { + const REPLACEMENT: &str = "\u{FFFD}"; + + let mut res = { + let mut v = Vec::with_capacity(self.bytes.len()); + + // `Utf8Error::valid_up_to` returns the maximum index of validated + // UTF-8 bytes. Copy the valid bytes into the output buffer. + v.extend_from_slice(&self.bytes[..self.error.valid_up_to()]); + + // SAFETY: This is safe because the only bytes present in the buffer + // were validated as UTF-8 by the call to `String::from_utf8` which + // produced this `FromUtf8Error`. + unsafe { String::from_utf8_unchecked(v) } + }; + + let iter = self.bytes[self.error.valid_up_to()..].utf8_chunks(); + + for chunk in iter { + res.push_str(chunk.valid()); + if !chunk.invalid().is_empty() { + res.push_str(REPLACEMENT); + } + } + + res + } + + /// Returns the bytes that were attempted to convert to a `String`. + /// + /// This method is carefully constructed to avoid allocation. It will + /// consume the error, moving out the bytes, so that a copy of the bytes + /// does not need to be made. + /// + /// # Examples + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let value = String::from_utf8(bytes); + /// + /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_bytes(self) -> Vec { + self.bytes + } + + /// Fetch a `Utf8Error` to get more details about the conversion failure. + /// + /// The [`Utf8Error`] type provided by [`std::str`] represents an error that may + /// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's + /// an analogue to `FromUtf8Error`. See its documentation for more details + /// on using it. + /// + /// [`std::str`]: core::str "std::str" + /// [`&str`]: prim@str "&str" + /// + /// # Examples + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let error = String::from_utf8(bytes).unwrap_err().utf8_error(); + /// + /// // the first byte is invalid here + /// assert_eq!(1, error.valid_up_to()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn utf8_error(&self) -> Utf8Error { + self.error + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FromUtf8Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.error, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FromUtf16Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt("invalid utf-16: lone surrogate found", f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for FromUtf8Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "invalid utf-8" + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for FromUtf16Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "invalid utf-16" + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for String { + fn clone(&self) -> Self { + String { vec: self.vec.clone() } + } + + /// Clones the contents of `source` into `self`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. + fn clone_from(&mut self, source: &Self) { + self.vec.clone_from(&source.vec); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_from_iter_by_ref", since = "1.17.0")] +impl<'a> FromIterator<&'a char> for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> FromIterator<&'a str> for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "extend_string", since = "1.4.0")] +impl FromIterator for String { + fn from_iter>(iter: I) -> String { + let mut iterator = iter.into_iter(); + + // Because we're iterating over `String`s, we can avoid at least + // one allocation by getting the first string from the iterator + // and appending to it all the subsequent strings. + match iterator.next() { + None => String::new(), + Some(mut buf) => { + buf.extend(iterator); + buf + } + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_str2", since = "1.45.0")] +impl FromIterator> for String { + fn from_iter>>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "herd_cows", since = "1.19.0")] +impl<'a> FromIterator> for String { + fn from_iter>>(iter: I) -> String { + let mut iterator = iter.into_iter(); + + // Because we're iterating over CoWs, we can (potentially) avoid at least + // one allocation by getting the first item and appending to it all the + // subsequent items. + match iterator.next() { + None => String::new(), + Some(cow) => { + let mut buf = cow.into_owned(); + buf.extend(iterator); + buf + } + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for String { + fn extend>(&mut self, iter: I) { + let iterator = iter.into_iter(); + let (lower_bound, _) = iterator.size_hint(); + self.reserve(lower_bound); + iterator.for_each(move |c| self.push(c)); + } + + #[inline] + fn extend_one(&mut self, c: char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, A: Allocator> Extend<&'a char> for String { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &c: &'a char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, A: Allocator> Extend<&'a str> for String { + fn extend>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(s)); + } + + #[inline] + fn extend_one(&mut self, s: &'a str) { + self.push_str(s); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_str2", since = "1.45.0")] +impl Extend> for String { + fn extend>>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "extend_string", since = "1.4.0")] +impl Extend> for String { + fn extend>>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } + + #[inline] + fn extend_one(&mut self, s: String) { + self.push_str(&s); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "herd_cows", since = "1.19.0")] +impl<'a, A: Allocator> Extend> for String { + fn extend>>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } + + #[inline] + fn extend_one(&mut self, s: Cow<'a, str>) { + self.push_str(&s); + } +} + +/// A convenience impl that delegates to the impl for `&str`. +/// +/// # Examples +/// +/// ``` +/// assert_eq!(String::from("Hello world").find("world"), Some(6)); +/// ``` +#[unstable( + feature = "pattern", + reason = "API not fully fleshed out and ready to be stabilized", + issue = "27721" +)] +impl<'b, A: Allocator> Pattern for &'b String { + type Searcher<'a> = <&'b str as Pattern>::Searcher<'a>; + + fn into_searcher(self, haystack: &str) -> <&'b str as Pattern>::Searcher<'_> { + self[..].into_searcher(haystack) + } + + #[inline] + fn is_contained_in(self, haystack: &str) -> bool { + self[..].is_contained_in(haystack) + } + + #[inline] + fn is_prefix_of(self, haystack: &str) -> bool { + self[..].is_prefix_of(haystack) + } + + #[inline] + fn strip_prefix_of(self, haystack: &str) -> Option<&str> { + self[..].strip_prefix_of(haystack) + } + + #[inline] + fn is_suffix_of<'a>(self, haystack: &'a str) -> bool + where + Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, + { + self[..].is_suffix_of(haystack) + } + + #[inline] + fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> + where + Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, + { + self[..].strip_suffix_of(haystack) + } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + Some(Utf8Pattern::StringPattern(self.as_bytes())) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq> for String { + #[inline] + fn eq(&self, other: &String) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + #[inline] + fn ne(&self, other: &String) -> bool { + PartialEq::ne(&self[..], &other[..]) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for String {} // FIXME(zachs18): Structural(Partial)Eq? + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd> for String { + #[inline] + fn partial_cmp(&self, other: &String) -> Option { + str::partial_cmp(&self[..], &other[..]) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for String { + #[inline] + fn cmp(&self, other: &String) -> Ordering { + str::cmp(&self[..], &other[..]) + } +} + +macro_rules! impl_eq { + ([$($vars:tt)*] $lhs:ty, $rhs: ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unused_lifetimes)] + impl<'a, 'b, $($vars)*> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + #[inline] + fn ne(&self, other: &$rhs) -> bool { + PartialEq::ne(&self[..], &other[..]) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unused_lifetimes)] + impl<'a, 'b, $($vars)*> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + #[inline] + fn ne(&self, other: &$lhs) -> bool { + PartialEq::ne(&self[..], &other[..]) + } + } + }; +} + +impl_eq! { [A: Allocator] String, str } +impl_eq! { [A: Allocator] String, &'a str } +#[cfg(not(no_global_oom_handling))] +impl_eq! { [] Cow<'a, str>, str } +#[cfg(not(no_global_oom_handling))] +impl_eq! { [] Cow<'a, str>, &'b str } +#[cfg(not(no_global_oom_handling))] +impl_eq! { [A: Allocator] Cow<'a, str>, String } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for String { + /// Creates an empty `String`. + #[inline] + fn default() -> String { + String::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for String { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for String { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for String { + #[inline] + fn hash(&self, hasher: &mut H) { + (**self).hash(hasher) + } +} + +/// Implements the `+` operator for concatenating two strings. +/// +/// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if +/// necessary). This is done to avoid allocating a new `String` and copying the entire contents on +/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by +/// repeated concatenation. +/// +/// The string on the right-hand side is only borrowed; its contents are copied into the returned +/// `String`. +/// +/// # Examples +/// +/// Concatenating two `String`s takes the first by value and borrows the second: +/// +/// ``` +/// let a = String::from("hello"); +/// let b = String::from(" world"); +/// let c = a + &b; +/// // `a` is moved and can no longer be used here. +/// ``` +/// +/// If you want to keep using the first `String`, you can clone it and append to the clone instead: +/// +/// ``` +/// let a = String::from("hello"); +/// let b = String::from(" world"); +/// let c = a.clone() + &b; +/// // `a` is still valid here. +/// ``` +/// +/// Concatenating `&str` slices can be done by converting the first to a `String`: +/// +/// ``` +/// let a = "hello"; +/// let b = " world"; +/// let c = a.to_string() + b; +/// ``` +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Add<&str> for String { + type Output = String; + + #[inline] + fn add(mut self, other: &str) -> String { + self.push_str(other); + self + } +} + +/// Implements the `+=` operator for appending to a `String`. +/// +/// This has the same behavior as the [`push_str`][String::push_str] method. +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "stringaddassign", since = "1.12.0")] +impl AddAssign<&str> for String { + #[inline] + fn add_assign(&mut self, other: &str) { + self.push_str(other); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Index for String +where + I: slice::SliceIndex, + A: Allocator, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &I::Output { + index.index(self.as_str()) + } +} + +#[stable(feature = "derefmut_for_string", since = "1.3.0")] +impl ops::IndexMut for String +where + I: slice::SliceIndex, + A: Allocator, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut I::Output { + index.index_mut(self.as_mut_str()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for String { + type Target = str; + + #[inline] + fn deref(&self) -> &str { + self.as_str() + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl ops::DerefPure for String {} + +#[stable(feature = "derefmut_for_string", since = "1.3.0")] +impl ops::DerefMut for String { + #[inline] + fn deref_mut(&mut self) -> &mut str { + self.as_mut_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl FromStr for String { + type Err = core::convert::Infallible; + #[inline] + fn from_str(s: &str) -> Result { + Ok(String::from(s)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for String { + #[inline] + fn as_ref(&self) -> &str { + self + } +} + +#[stable(feature = "string_as_mut", since = "1.43.0")] +impl AsMut for String { + #[inline] + fn as_mut(&mut self) -> &mut str { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[u8]> for String { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&str> for String { + /// Converts a `&str` into a [`String`]. + /// + /// The result is allocated on the heap. + #[inline] + fn from(s: &str) -> String { + s.to_owned() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_mut_str_for_string", since = "1.44.0")] +impl From<&mut str> for String { + /// Converts a `&mut str` into a [`String`]. + /// + /// The result is allocated on the heap. + #[inline] + fn from(s: &mut str) -> String { + s.to_owned() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_ref_string", since = "1.35.0")] +impl From<&String> for String { + /// Converts a `&String` into a [`String`]. + /// + /// This clones `s` and returns the clone. + #[inline] + fn from(s: &String) -> String { + s.clone() + } +} + +// note: test pulls in std, which causes errors here +#[cfg(not(test))] +#[stable(feature = "string_from_box", since = "1.18.0")] +impl From> for String { + /// Converts the given boxed `str` slice to a [`String`]. + /// It is notable that the `str` slice is owned. + /// + /// # Examples + /// + /// ``` + /// let s1: String = String::from("hello world"); + /// let s2: Box = s1.into_boxed_str(); + /// let s3: String = String::from(s2); + /// + /// assert_eq!("hello world", s3) + /// ``` + fn from(s: Box) -> String { + s.into_string() + } +} + +// When compiling in test mode, `Box` is not actually local, so this impl is incoherent +// since `A` is the "main" type. +// To work around this, restrict this impl to `A = Global` under cfg(test). +#[cfg(not(test))] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_str", since = "1.20.0")] +impl From> for Box { + /// Converts the given [`String`] to a boxed `str` slice that is owned. + /// + /// # Examples + /// + /// ``` + /// let s1: String = String::from("hello world"); + /// let s2: Box = Box::from(s1); + /// let s3: String = String::from(s2); + /// + /// assert_eq!("hello world", s3) + /// ``` + fn from(s: String) -> Box { + s.into_boxed_str() + } +} + +// See above `impl From> for Box` +#[cfg(test)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_str", since = "1.20.0")] +impl From for Box { + /// Converts the given [`String`] to a boxed `str` slice that is owned. + /// + /// # Examples + /// + /// ``` + /// let s1: String = String::from("hello world"); + /// let s2: Box = Box::from(s1); + /// let s3: String = String::from(s2); + /// + /// assert_eq!("hello world", s3) + /// ``` + fn from(s: String) -> Box { + s.into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_from_cow_str", since = "1.14.0")] +impl<'a> From> for String { + /// Converts a clone-on-write string to an owned + /// instance of [`String`]. + /// + /// This extracts the owned string, + /// clones the string if it is not already owned. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// // If the string is not owned... + /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); + /// // It will allocate on the heap and copy the string. + /// let owned: String = String::from(cow); + /// assert_eq!(&owned[..], "eggplant"); + /// ``` + fn from(s: Cow<'a, str>) -> String { + s.into_owned() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From<&'a str> for Cow<'a, str> { + /// Converts a string slice into a [`Borrowed`] variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// assert_eq!(Cow::from("eggplant"), Cow::Borrowed("eggplant")); + /// ``` + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" + #[inline] + fn from(s: &'a str) -> Cow<'a, str> { + Cow::Borrowed(s) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From for Cow<'a, str> { + /// Converts a [`String`] into an [`Owned`] variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// let s = "eggplant".to_string(); + /// let s2 = "eggplant".to_string(); + /// assert_eq!(Cow::from(s), Cow::<'static, str>::Owned(s2)); + /// ``` + /// + /// [`Owned`]: crate::borrow::Cow::Owned "borrow::Cow::Owned" + #[inline] + fn from(s: String) -> Cow<'a, str> { + Cow::Owned(s) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_from_string_ref", since = "1.28.0")] +impl<'a, A: Allocator> From<&'a String> for Cow<'a, str> { + /// Converts a [`String`] reference into a [`Borrowed`] variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// let s = "eggplant".to_string(); + /// assert_eq!(Cow::from(&s), Cow::Borrowed("eggplant")); + /// ``` + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" + #[inline] + fn from(s: &'a String) -> Cow<'a, str> { + Cow::Borrowed(s.as_str()) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a> FromIterator for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a, 'b> FromIterator<&'b str> for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a> FromIterator for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] +impl From> for Vec { + /// Converts the given [`String`] to a vector [`Vec`] that holds values of type [`u8`]. + /// + /// # Examples + /// + /// ``` + /// let s1 = String::from("hello world"); + /// let v1 = Vec::from(s1); + /// + /// for b in v1 { + /// println!("{b}"); + /// } + /// ``` + fn from(string: String) -> Vec { + string.into_bytes() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Write for String { + #[inline] + fn write_str(&mut self, s: &str) -> fmt::Result { + self.push_str(s); + Ok(()) + } + + #[inline] + fn write_char(&mut self, c: char) -> fmt::Result { + self.push(c); + Ok(()) + } +} + +/// An iterator over the [`char`]s of a string. +/// +/// This struct is created by the [`into_chars`] method on [`String`]. +/// See its documentation for more. +/// +/// [`char`]: prim@char +/// [`into_chars`]: String::into_chars +#[cfg_attr(not(no_global_oom_handling), derive(Clone))] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[unstable(feature = "string_into_chars", issue = "133125")] +pub struct IntoChars { + bytes: vec::IntoIter, +} + +#[unstable(feature = "string_into_chars", issue = "133125")] +impl fmt::Debug for IntoChars { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoChars").field(&self.as_str()).finish() + } +} + +impl IntoChars { + /// Views the underlying data as a subslice of the original data. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_into_chars)] + /// + /// let mut chars = String::from("abc").into_chars(); + /// + /// assert_eq!(chars.as_str(), "abc"); + /// chars.next(); + /// assert_eq!(chars.as_str(), "bc"); + /// chars.next(); + /// chars.next(); + /// assert_eq!(chars.as_str(), ""); + /// ``` + #[unstable(feature = "string_into_chars", issue = "133125")] + #[must_use] + #[inline] + pub fn as_str(&self) -> &str { + // SAFETY: `bytes` is a valid UTF-8 string. + unsafe { str::from_utf8_unchecked(self.bytes.as_slice()) } + } + + #[inline] + fn iter(&self) -> CharIndices<'_> { + self.as_str().char_indices() + } +} + +impl IntoChars { + /// Consumes the `IntoChars`, returning the remaining string. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_into_chars)] + /// + /// let chars = String::from("abc").into_chars(); + /// assert_eq!(chars.into_string(), "abc"); + /// + /// let mut chars = String::from("def").into_chars(); + /// chars.next(); + /// assert_eq!(chars.into_string(), "ef"); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_into_chars", issue = "133125")] + #[inline] + pub fn into_string(self) -> String { + // Safety: `bytes` are kept in UTF-8 form, only removing whole `char`s at a time. + unsafe { String::from_utf8_unchecked(self.bytes.collect()) } + } +} + +#[unstable(feature = "string_into_chars", issue = "133125")] +impl Iterator for IntoChars { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + let mut iter = self.iter(); + match iter.next() { + None => None, + Some((_, ch)) => { + let offset = iter.offset(); + // `offset` is a valid index. + let _ = self.bytes.advance_by(offset); + Some(ch) + } + } + } + + #[inline] + fn count(self) -> usize { + self.iter().count() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter().size_hint() + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[unstable(feature = "string_into_chars", issue = "133125")] +impl DoubleEndedIterator for IntoChars { + #[inline] + fn next_back(&mut self) -> Option { + let len = self.as_str().len(); + let mut iter = self.iter(); + match iter.next_back() { + None => None, + Some((idx, ch)) => { + // `idx` is a valid index. + let _ = self.bytes.advance_back_by(len - idx); + Some(ch) + } + } + } +} + +#[unstable(feature = "string_into_chars", issue = "133125")] +impl FusedIterator for IntoChars {} + +/// A draining iterator for `String`. +/// +/// This struct is created by the [`drain`] method on [`String`]. See its +/// documentation for more. +/// +/// [`drain`]: String::drain +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain<'a, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> +{ + /// Will be used as &'a mut String in the destructor + string: *mut String, + /// Start of part to remove + start: usize, + /// End of part to remove + end: usize, + /// Current remaining range to remove + iter: Chars<'a>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain").field(&self.as_str()).finish() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, A> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, A> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, A> { + fn drop(&mut self) { + unsafe { + // Use Vec::drain. "Reaffirm" the bounds checks to avoid + // panic code being inserted again. + let self_vec = (*self.string).as_mut_vec(); + if self.start <= self.end && self.end <= self_vec.len() { + self_vec.drain(self.start..self.end); + } + } + } +} + +impl<'a, A: Allocator> Drain<'a, A> { + /// Returns the remaining (sub)string of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("abc"); + /// let mut drain = s.drain(..); + /// assert_eq!(drain.as_str(), "abc"); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_str(), "bc"); + /// ``` + #[must_use] + #[stable(feature = "string_drain_as_str", since = "1.55.0")] + pub fn as_str(&self) -> &str { + self.iter.as_str() + } +} + +#[stable(feature = "string_drain_as_str", since = "1.55.0")] +impl<'a, A: Allocator> AsRef for Drain<'a, A> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +#[stable(feature = "string_drain_as_str", since = "1.55.0")] +impl<'a, A: Allocator> AsRef<[u8]> for Drain<'a, A> { + fn as_ref(&self) -> &[u8] { + self.as_str().as_bytes() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, A> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, A> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, A> {} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_char_for_string", since = "1.46.0")] +impl From for String { + /// Allocates an owned [`String`] from a single character. + /// + /// # Example + /// ```rust + /// let c: char = 'a'; + /// let s: String = String::from(c); + /// assert_eq!("a", &s[..]); + /// ``` + #[inline] + fn from(c: char) -> Self { + c.to_string() + } +} diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 17d9455592787..bdb88573e56c9 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -709,7 +709,7 @@ impl fmt::Debug for TypeId { /// ```rust /// assert_eq!( /// std::any::type_name::>(), -/// "core::option::Option", +/// "core::option::Option", /// ); /// ``` #[must_use] diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs index ccb1cc4e974d6..d2db63f962711 100644 --- a/library/core/src/borrow.rs +++ b/library/core/src/borrow.rs @@ -43,7 +43,7 @@ /// [`Box`]: ../../std/boxed/struct.Box.html /// [`Mutex`]: ../../std/sync/struct.Mutex.html /// [`Rc`]: ../../std/rc/struct.Rc.html -/// [`String`]: ../../std/string/struct.String.html +/// [`String`]: ../../std/string/type.String.html /// [`borrow`]: Borrow::borrow /// /// # Examples @@ -151,7 +151,7 @@ /// /// [`Hash`]: crate::hash::Hash /// [`HashMap`]: ../../std/collections/struct.HashMap.html -/// [`String`]: ../../std/string/struct.String.html +/// [`String`]: ../../std/string/type.String.html #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Borrow"] pub trait Borrow { diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index ccfdbf0eb704d..b94bbbce5ad2c 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -75,7 +75,7 @@ impl char { /// decoding error. /// /// It can occur, for example, when giving ill-formed UTF-8 bytes to - /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy). + /// [`String::from_utf8_lossy`](../std/string/type.String.html#method.from_utf8_lossy). #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}'; diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index e468f4f0f7e66..745a43ec818a9 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -200,7 +200,7 @@ pub const fn identity(x: T) -> T { /// [`Borrow`]: crate::borrow::Borrow /// [`Eq`]: crate::cmp::Eq /// [`Ord`]: crate::cmp::Ord -/// [`String`]: ../../std/string/struct.String.html +/// [`String`]: ../../std/string/type.String.html /// /// ``` /// fn is_hello>(s: T) { @@ -439,7 +439,7 @@ pub trait AsMut { /// is_hello(s); /// ``` /// -/// [`String`]: ../../std/string/struct.String.html +/// [`String`]: ../../std/string/type.String.html /// [`Vec`]: ../../std/vec/struct.Vec.html #[rustc_diagnostic_item = "Into"] #[stable(feature = "rust1", since = "1.0.0")] @@ -569,13 +569,13 @@ pub trait Into: Sized { /// } /// ``` /// -/// [`String`]: ../../std/string/struct.String.html +/// [`String`]: ../../std/string/type.String.html /// [`from`]: From::from /// [book]: ../../book/ch09-00-error-handling.html #[rustc_diagnostic_item = "From"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(on( - all(_Self = "&str", T = "alloc::string::String"), + all(_Self = "&str", T = "alloc::string::string::String"), note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix", ))] #[doc(search_unbox)] diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 97bb21c8a36e8..8a26c64464c28 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -264,7 +264,7 @@ pub trait FromIterator: Sized { label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" ), on( - _Self = "alloc::string::String", + _Self = "alloc::string::string::String", label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" ), on( diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 91c3a4b29b539..1e2ce216c0a20 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1958,7 +1958,7 @@ pub trait Iterator { /// ``` /// /// [`iter`]: Iterator::next - /// [`String`]: ../../std/string/struct.String.html + /// [`String`]: ../../std/string/type.String.html /// [`char`]: type@char #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 18ada14d101b5..a074502ac3262 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -404,7 +404,7 @@ marker_impls! { /// while variables captured by mutable reference never implement `Copy`. /// /// [`Vec`]: ../../std/vec/struct.Vec.html -/// [`String`]: ../../std/string/struct.String.html +/// [`String`]: ../../std/string/type.String.html /// [`size_of::`]: crate::mem::size_of /// [impls]: #implementors #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 11490ea2bfcb4..d36c27e6273db 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -100,7 +100,7 @@ /// [method resolution]: ../../reference/expressions/method-call-expr.html /// [type coercions]: ../../reference/type-coercions.html /// [box]: ../../alloc/boxed/struct.Box.html -/// [string]: ../../alloc/string/struct.String.html +/// [string]: ../../alloc/string/type.String.html /// [vec]: ../../alloc/vec/struct.Vec.html /// [rc]: ../../alloc/rc/struct.Rc.html /// [cow]: ../../alloc/borrow/enum.Cow.html @@ -226,7 +226,7 @@ impl const Deref for &mut T { /// [method resolution]: ../../reference/expressions/method-call-expr.html /// [type coercions]: ../../reference/type-coercions.html /// [box]: ../../alloc/boxed/struct.Box.html -/// [string]: ../../alloc/string/struct.String.html +/// [string]: ../../alloc/string/type.String.html /// [rc]: ../../alloc/rc/struct.Rc.html /// [cow]: ../../alloc/borrow/enum.Cow.html /// diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs index 37d9a28fb99c0..2790536b22c9c 100644 --- a/library/core/src/ops/index.rs +++ b/library/core/src/ops/index.rs @@ -153,7 +153,7 @@ see chapter in The Book " ), on( - _Self = "alloc::string::String", + _Self = "alloc::string::string::String", note = "you can use `.chars().nth()` or `.bytes().nth()` see chapter in The Book " ), diff --git a/library/core/src/option.rs b/library/core/src/option.rs index a9f06b92ad5dd..e4c4e548542a7 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -690,8 +690,8 @@ impl Option { /// reference to the value inside the original. /// /// [`map`]: Option::map - /// [String]: ../../std/string/struct.String.html "String" - /// [`String`]: ../../std/string/struct.String.html "String" + /// [String]: ../../std/string/type.String.html "String" + /// [`String`]: ../../std/string/type.String.html "String" /// /// ``` /// let text: Option = Some("Hello, world!".to_string()); @@ -1099,7 +1099,7 @@ impl Option { /// Calculates the length of an Option<[String]> as an /// Option<[usize]>, consuming the original: /// - /// [String]: ../../std/string/struct.String.html "String" + /// [String]: ../../std/string/type.String.html "String" /// ``` /// let maybe_some_string = Some(String::from("Hello, World!")); /// // `Option::map` takes self *by value*, consuming `maybe_some_string` @@ -2138,7 +2138,7 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// to the value inside the original. /// /// [`map`]: Option::map - /// [String]: ../../std/string/struct.String.html "String" + /// [String]: ../../std/string/type.String.html "String" /// /// ``` /// let s: Option = Some(String::from("Hello, Rustaceans!")); diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 2a0bf89fcf7a9..8b6e8603af015 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -916,7 +916,7 @@ //! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len //! [`VecDeque`]: ../../std/collections/struct.VecDeque.html //! [VecDeque]: ../../std/collections/struct.VecDeque.html "collections::VecDeque" -//! [`String`]: ../../std/string/struct.String.html "String" +//! [`String`]: ../../std/string/type.String.html "String" #![stable(feature = "pin", since = "1.33.0")] diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index c5f029363e589..b59f19bee37fe 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -188,7 +188,7 @@ mod prim_bool {} /// because `!` coerces to `Result` automatically. /// /// [`String::from_str`]: str::FromStr::from_str -/// [`String`]: ../std/string/struct.String.html +/// [`String`]: ../std/string/type.String.html /// [`FromStr`]: str::FromStr /// /// # `!` and traits @@ -406,7 +406,7 @@ mod prim_never {} /// assert_eq!(5, s.len() * std::mem::size_of::()); /// ``` /// -/// [`String`]: ../std/string/struct.String.html +/// [`String`]: ../std/string/type.String.html /// /// As always, remember that a human intuition for 'character' might not map to /// Unicode's definitions. For example, despite looking similar, the 'é' diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index aafa19c0dd3d3..7b4be326e0e43 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -161,7 +161,10 @@ mod private_slice_index { #[rustc_on_unimplemented( on(T = "str", label = "string indices are ranges of `usize`",), on( - all(any(T = "str", T = "&str", T = "alloc::string::String"), _Self = "{integer}"), + all( + any(T = "str", T = "&str", T = "alloc::string::string::String"), + _Self = "{integer}" + ), note = "you can use `.chars().nth()` or `.bytes().nth()`\n\ for more information, see chapter 8 in The Book: \ " diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index de68f80aa0c8e..37692a18ce568 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -23,7 +23,7 @@ use crate::{mem, ptr}; /// If you need a `String` instead of a `&str`, consider /// [`String::from_utf8`][string]. /// -/// [string]: ../../std/string/struct.String.html#method.from_utf8 +/// [string]: ../../std/string/type.String.html#method.from_utf8 /// /// Because you can stack-allocate a `[u8; N]`, and you can take a /// [`&[u8]`][byteslice] of it, this function is one way to have a diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs index 4c8231a2286e1..c362bef33fae3 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -9,7 +9,7 @@ use crate::fmt; /// As such, the `from_utf8` family of functions and methods for both [`String`]s /// and [`&str`]s make use of this error, for example. /// -/// [`String`]: ../../std/string/struct.String.html#method.from_utf8 +/// [`String`]: ../../std/string/type.String.html#method.from_utf8 /// [`&str`]: super::from_utf8 /// /// # Examples diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index ed2cefc59a51c..ef2b93dfd6500 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -172,7 +172,7 @@ impl fmt::Debug for Debug<'_> { /// } /// ``` /// -/// [`String::from_utf8_lossy`]: ../../std/string/struct.String.html#method.from_utf8_lossy +/// [`String::from_utf8_lossy`]: ../../std/string/type.String.html#method.from_utf8_lossy #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "utf8_chunks", since = "1.79.0")] #[derive(Clone)] diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 6aab22177ab9d..b8a67e1b05c01 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -35,7 +35,7 @@ impl Poll { /// Converts a Poll<[String]> into a Poll<[usize]>, consuming /// the original: /// - /// [String]: ../../std/string/struct.String.html "String" + /// [String]: ../../std/string/type.String.html "String" /// ``` /// # use core::task::Poll; /// let poll_some_string = Poll::Ready(String::from("Hello, World!")); diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index c4c8dbccd7a44..c72e2ecddeeb8 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -5,12 +5,14 @@ mod tests; use core::clone::CloneToUninit; +use crate::alloc::Allocator; use crate::borrow::{Borrow, Cow}; use crate::collections::TryReserveError; use crate::hash::{Hash, Hasher}; use crate::ops::{self, Range}; use crate::rc::Rc; use crate::str::FromStr; +use crate::string::string::String; use crate::sync::Arc; use crate::sys::os_str::{Buf, Slice}; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -1650,7 +1652,7 @@ impl AsRef for str { } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef for String { +impl AsRef for String { #[inline] fn as_ref(&self) -> &OsStr { (&**self).as_ref() diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index acb3a0578e505..64402c07b147b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -372,6 +372,7 @@ #![feature(map_try_insert)] #![feature(new_zeroed_alloc)] #![feature(slice_concat_trait)] +#![feature(string_allocator_api)] #![feature(thin_box)] #![feature(try_reserve_kind)] #![feature(try_with_capacity)] diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index d649357a56d71..ed55fe9def453 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -68,7 +68,7 @@ impl<'a> PanicHookInfo<'a> { /// (or, in Rust 2018 and earlier, `panic!(x)` where `x` is something other than a string) /// can result in a panic payload other than a `&'static str` or `String`. /// - /// [`String`]: ../../std/string/struct.String.html + /// [`String`]: ../../std/string/type.String.html /// /// # Examples /// diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 7fd08a97f1f20..21c59c818aea2 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -72,6 +72,7 @@ mod tests; use core::clone::CloneToUninit; +use crate::alloc::Allocator; use crate::borrow::{Borrow, Cow}; use crate::collections::TryReserveError; use crate::error::Error; @@ -81,6 +82,7 @@ use crate::iter::FusedIterator; use crate::ops::{self, Deref}; use crate::rc::Rc; use crate::str::FromStr; +use crate::string::string::String; use crate::sync::Arc; use crate::sys::path::{MAIN_SEP_STR, is_sep_byte, is_verbatim_sep, parse_prefix}; use crate::{cmp, fmt, fs, io, sys}; @@ -3352,7 +3354,7 @@ impl AsRef for str { } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef for String { +impl AsRef for String { #[inline] fn as_ref(&self) -> &Path { Path::new(self) diff --git a/library/std/tests/type-name-unsized.rs b/library/std/tests/type-name-unsized.rs index 2974668b2ce71..2053a6e1a846c 100644 --- a/library/std/tests/type-name-unsized.rs +++ b/library/std/tests/type-name-unsized.rs @@ -48,7 +48,7 @@ impl Trait for i32 { } fn bar() { - check!(T::Assoc, "alloc::string::String"); + check!(T::Assoc, "alloc::string::string::String"); check!(T, "i32"); } diff --git a/src/doc/book b/src/doc/book index fa312a343fbff..eb5549f7b84bb 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit fa312a343fbff01bc6cef393e326817f70719813 +Subproject commit eb5549f7b84bbdca1099747ef0626af2992162c0 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index ddbf1b4e2858f..833e9058aca50 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit ddbf1b4e2858fedb71b7c42eb15c4576517dc125 +Subproject commit 833e9058aca503fe30df719ea6c079b8b2c9efc7 diff --git a/src/doc/unstable-book/src/language-features/string-deref-patterns.md b/src/doc/unstable-book/src/language-features/string-deref-patterns.md index 3723830751e80..7c72cdcc3ca86 100644 --- a/src/doc/unstable-book/src/language-features/string-deref-patterns.md +++ b/src/doc/unstable-book/src/language-features/string-deref-patterns.md @@ -42,4 +42,4 @@ pub fn is_it_the_answer(value: Value) -> bool { } ``` -[its `Deref` implementation]: https://doc.rust-lang.org/std/string/struct.String.html#impl-Deref-for-String +[its `Deref` implementation]: https://doc.rust-lang.org/std/string/type.String.html#impl-Deref-for-String diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index 1528a8b1226ca..71dc839b91f7c 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -40,7 +40,7 @@ - + {(char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8} (char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8 diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py index af03e8ede9c3f..332d9d012552f 100644 --- a/src/etc/rust_types.py +++ b/src/etc/rust_types.py @@ -37,7 +37,7 @@ class RustType(object): STD_PATHBUF = "StdPathBuf" -STD_STRING_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)String$") +STD_STRING_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)String<.+>$") STD_STR_REGEX = re.compile(r"^&(mut )?str$") STD_SLICE_REGEX = re.compile(r"^&(mut )?\[.+\]$") STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::([a-z_]+::)+)OsString$") diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index 9d07a14718da1..c281fcec4fc63 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -33,7 +33,7 @@ impl ArithmeticSideEffects { allowed_binary.extend([ ("f32", FxHashSet::from_iter(["f32"])), ("f64", FxHashSet::from_iter(["f64"])), - ("std::string::String", FxHashSet::from_iter(["str"])), + ("std::string::string::String", FxHashSet::from_iter(["str"])), ]); for (lhs, rhs) in &conf.arithmetic_side_effects_allowed_binary { allowed_binary.entry(lhs).or_default().insert(rhs); diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs index 7bd4d6e993b47..2ffffd25cb23e 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs @@ -25,11 +25,11 @@ declare_clippy_lint! { /// /// ### Example /// ```no_run - /// let foo: String = String::new(); + /// let foo: usize = usize::MAX; /// ``` /// Use instead: /// ```no_run - /// let foo = String::new(); + /// let foo = usize::MAX; /// ``` #[clippy::version = "1.72.0"] pub REDUNDANT_TYPE_ANNOTATIONS, diff --git a/src/tools/clippy/clippy_lints/src/types/box_collection.rs b/src/tools/clippy/clippy_lints/src/types/box_collection.rs index 24fe4e08a5b44..d31f8cca3cf8f 100644 --- a/src/tools/clippy/clippy_lints/src/types/box_collection.rs +++ b/src/tools/clippy/clippy_lints/src/types/box_collection.rs @@ -47,6 +47,7 @@ fn get_std_collection(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option | sym::BTreeMap | sym::BTreeSet | sym::BinaryHeap + | sym::String ) }) .or_else(|| { diff --git a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs index d691f1878b11b..cf5946ee33d79 100644 --- a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs +++ b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs @@ -109,6 +109,7 @@ fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static let path = match cx.tcx.get_diagnostic_name(id) { Some(sym::OsString) => "std::ffi::OsStr", Some(sym::PathBuf) => "std::path::Path", + Some(sym::String) => "str", _ if Some(id) == cx.tcx.lang_items().string() => "str", _ => return None, }; diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 5e452c6d2ac09..2c55daac80c29 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -3,7 +3,8 @@ use clippy_utils::source::{snippet, snippet_with_context}; use clippy_utils::sugg::{DiagExt as _, Sugg}; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; use clippy_utils::{ - get_parent_expr, is_inherent_method_call, is_trait_item, is_trait_method, is_ty_alias, path_to_local, + get_parent_expr, is_inherent_method_call, is_string_ty_alias, is_trait_item, is_trait_method, is_ty_alias, + path_to_local, }; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -333,7 +334,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { ExprKind::Call(path, [arg]) => { if let ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && !is_ty_alias(qpath) + && (!is_ty_alias(qpath) || is_string_ty_alias(cx, qpath)) { let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(arg); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 5a5227af90743..81a539e9ace10 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -350,6 +350,18 @@ pub fn is_ty_alias(qpath: &QPath<'_>) -> bool { } } +/// Checks if the given `QPath` belongs to the specific type alias +/// `std::string::String`/`alloc::string::String`. +pub fn is_string_ty_alias(cx: &LateContext<'_>, qpath: &QPath<'_>) -> bool { + match *qpath { + QPath::Resolved(_, path) => { + matches!(path.res, Res::Def(DefKind::TyAlias, id) if cx.tcx.get_diagnostic_name(id) == Some(sym::String)) + }, + QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => is_string_ty_alias(cx, &qpath), + _ => false, + } +} + /// Checks if the method call given in `expr` belongs to the given trait. /// This is a deprecated function, consider using [`is_trait_method`]. pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool { diff --git a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr index 39b8634be109a..42e11b2188576 100644 --- a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr +++ b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr @@ -1,4 +1,4 @@ -error: holding a disallowed type across an await point `std::string::String` +error: holding a disallowed type across an await point `std::string::string::String` --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:5:9 | LL | let _x = String::from("hello"); @@ -14,7 +14,7 @@ error: holding a disallowed type across an await point `std::net::Ipv4Addr` LL | let x = Ipv4Addr::new(127, 0, 0, 1); | ^ -error: holding a disallowed type across an await point `std::string::String` +error: holding a disallowed type across an await point `std::string::string::String` --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:33:13 | LL | let _x = String::from("hi!"); diff --git a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/clippy.toml b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/clippy.toml index 79990096b84e0..ac4e97069f1c6 100644 --- a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/clippy.toml +++ b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/clippy.toml @@ -1,4 +1,4 @@ await-holding-invalid-types = [ - { path = "std::string::String", reason = "strings are bad" }, + { path = "std::string::string::String", reason = "strings are bad" }, "std::net::Ipv4Addr", ] diff --git a/src/tools/clippy/tests/ui/crashes/ice-3969.rs b/src/tools/clippy/tests/ui/crashes/ice-3969.rs index ac09ce08753af..df231c85d2da0 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3969.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-3969.rs @@ -40,7 +40,7 @@ where fn use_op(s: String) -> String where String: ::std::ops::Neg, - //~^ ERROR: trait bound std::string::String: std::ops::Neg does not depend on any type + //~^ ERROR: trait bound std::string::string::String: std::ops::Neg does not depend on any type { -s } diff --git a/src/tools/clippy/tests/ui/crashes/ice-3969.stderr b/src/tools/clippy/tests/ui/crashes/ice-3969.stderr index 285efee36bd85..e479da0c3ab63 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3969.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-3969.stderr @@ -19,7 +19,7 @@ error: trait bound str: std::marker::Sized does not depend on any type or lifeti LL | str: Sized, | ^^^^^ -error: trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters +error: trait bound std::string::string::String: std::ops::Neg does not depend on any type or lifetime parameters --> tests/ui/crashes/ice-3969.rs:42:13 | LL | String: ::std::ops::Neg, diff --git a/src/tools/clippy/tests/ui/duplicated_attributes.rs b/src/tools/clippy/tests/ui/duplicated_attributes.rs index 874f5d22075c1..36cd2f61b6cb0 100644 --- a/src/tools/clippy/tests/ui/duplicated_attributes.rs +++ b/src/tools/clippy/tests/ui/duplicated_attributes.rs @@ -21,7 +21,10 @@ fn foo() {} fn bar() {} // No warning: -#[rustc_on_unimplemented(on(_Self = "&str", label = "`a"), on(_Self = "alloc::string::String", label = "a"))] +#[rustc_on_unimplemented( + on(_Self = "&str", label = "`a"), + on(_Self = "alloc::string::string::String", label = "a") +)] trait Abc {} #[proc_macro_attr::duplicated_attr()] // Should not warn! diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr index f913ae0bb5067..2866214382f52 100644 --- a/src/tools/clippy/tests/ui/from_over_into.stderr +++ b/src/tools/clippy/tests/ui/from_over_into.stderr @@ -6,7 +6,7 @@ LL | impl Into for String { | = note: `-D clippy::from-over-into` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::from_over_into)]` -help: replace the `Into` implementation with `From` +help: replace the `Into` implementation with `From` | LL ~ impl From for StringWrapper { LL ~ fn from(val: String) -> Self { @@ -19,7 +19,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: replace the `Into` implementation with `From` +help: replace the `Into` implementation with `From` | LL ~ impl From for SelfType { LL ~ fn from(val: String) -> Self { diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr index 1776b86e40dd3..013caf16c9d3b 100644 --- a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr +++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr @@ -4,7 +4,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: replace the `Into` implementation with `From` + = help: replace the `Into` implementation with `From` = note: `-D clippy::from-over-into` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::from_over_into)]` diff --git a/src/tools/clippy/tests/ui/inefficient_to_string.stderr b/src/tools/clippy/tests/ui/inefficient_to_string.stderr index e71e667cf0cfe..4536dc11a650f 100644 --- a/src/tools/clippy/tests/ui/inefficient_to_string.stderr +++ b/src/tools/clippy/tests/ui/inefficient_to_string.stderr @@ -19,21 +19,21 @@ LL | let _: String = rrrstr.to_string(); | = help: `&&str` implements `ToString` through a slower blanket impl, but `str` has a fast specialization of `ToString` -error: calling `to_string` on `&&std::string::String` +error: calling `to_string` on `&&std::string::string::String` --> tests/ui/inefficient_to_string.rs:19:21 | LL | let _: String = rrstring.to_string(); | ^^^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrstring).to_string()` | - = help: `&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString` + = help: `&std::string::string::String` implements `ToString` through a slower blanket impl, but `std::string::string::String` has a fast specialization of `ToString` -error: calling `to_string` on `&&&std::string::String` +error: calling `to_string` on `&&&std::string::string::String` --> tests/ui/inefficient_to_string.rs:20:21 | LL | let _: String = rrrstring.to_string(); | ^^^^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrstring).to_string()` | - = help: `&&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString` + = help: `&&std::string::string::String` implements `ToString` through a slower blanket impl, but `std::string::string::String` has a fast specialization of `ToString` error: calling `to_string` on `&&std::borrow::Cow<'_, str>` --> tests/ui/inefficient_to_string.rs:28:21 diff --git a/src/tools/clippy/tests/ui/mem_forget.rs b/src/tools/clippy/tests/ui/mem_forget.rs index 1f508b3bca289..2f33d1cc88dff 100644 --- a/src/tools/clippy/tests/ui/mem_forget.rs +++ b/src/tools/clippy/tests/ui/mem_forget.rs @@ -28,7 +28,7 @@ fn main() { let string = String::new(); std::mem::forget(string); //~^ ERROR: usage of `mem::forget` on type with `Drop` fields - //~| NOTE: argument has type `std::string::String` + //~| NOTE: argument has type `std::string::string::String` std::mem::forget(7); } diff --git a/src/tools/clippy/tests/ui/mem_forget.stderr b/src/tools/clippy/tests/ui/mem_forget.stderr index 3b0e839e0871a..3444aae3b9965 100644 --- a/src/tools/clippy/tests/ui/mem_forget.stderr +++ b/src/tools/clippy/tests/ui/mem_forget.stderr @@ -30,7 +30,7 @@ error: usage of `mem::forget` on type with `Drop` fields LL | std::mem::forget(string); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: argument has type `std::string::String` + = note: argument has type `std::string::string::String` error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_type_annotations.rs b/src/tools/clippy/tests/ui/redundant_type_annotations.rs index dc9b073ffba85..28ff8c85aed8e 100644 --- a/src/tools/clippy/tests/ui/redundant_type_annotations.rs +++ b/src/tools/clippy/tests/ui/redundant_type_annotations.rs @@ -154,10 +154,10 @@ fn test_complex_types() { } fn test_functions() { - // Everything here should be lint + // Everything here should be lint, except for String, due to #101551 + // FIXME: if generics support is added, the lint should fire here let _return: String = return_a_string(); - //~^ ERROR: redundant type annotation let _return: Pie = return_a_struct(); //~^ ERROR: redundant type annotation @@ -168,8 +168,8 @@ fn test_functions() { let _return: u32 = return_an_int(); //~^ ERROR: redundant type annotation + // FIXME: if generics support is added, the lint should fire here let _return: String = String::new(); - //~^ ERROR: redundant type annotation let new_pie: Pie = Pie::new(); //~^ ERROR: redundant type annotation @@ -180,8 +180,8 @@ fn test_functions() { let _return: u32 = Pie::associated_return_an_int(); //~^ ERROR: redundant type annotation + // FIXME: if generics support is added, the lint should fire here let _return: String = Pie::associated_return_a_string(); - //~^ ERROR: redundant type annotation } fn test_simple_types() { diff --git a/src/tools/clippy/tests/ui/redundant_type_annotations.stderr b/src/tools/clippy/tests/ui/redundant_type_annotations.stderr index 4768f4d3c57ce..b957d25d2ddc2 100644 --- a/src/tools/clippy/tests/ui/redundant_type_annotations.stderr +++ b/src/tools/clippy/tests/ui/redundant_type_annotations.stderr @@ -19,12 +19,6 @@ error: redundant type annotation LL | let v: &Slice = self.return_a_ref_to_struct(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:159:5 - | -LL | let _return: String = return_a_string(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: redundant type annotation --> tests/ui/redundant_type_annotations.rs:162:5 | @@ -43,12 +37,6 @@ error: redundant type annotation LL | let _return: u32 = return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:171:5 - | -LL | let _return: String = String::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: redundant type annotation --> tests/ui/redundant_type_annotations.rs:174:5 | @@ -67,12 +55,6 @@ error: redundant type annotation LL | let _return: u32 = Pie::associated_return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:183:5 - | -LL | let _return: String = Pie::associated_return_a_string(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: redundant type annotation --> tests/ui/redundant_type_annotations.rs:190:5 | @@ -103,5 +85,5 @@ error: redundant type annotation LL | let _var: bool = false; | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr index ed50f3071862e..68e678a9c0f31 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.stderr +++ b/src/tools/clippy/tests/ui/useless_conversion.stderr @@ -52,25 +52,25 @@ error: useless conversion to the same type: `std::ops::Range` LL | let mut n = NUMBERS.into_iter(); | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion.rs:136:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion.rs:137:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion.rs:138:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion.rs:139:13 | LL | let _ = String::from(format!("A: {:04}", 123)); @@ -88,7 +88,7 @@ error: useless conversion to the same type: `std::vec::IntoIter` LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion.rs:142:21 | LL | let _: String = format!("Hello {}", "world").into(); diff --git a/src/tools/clippy/tests/ui/useless_conversion_try.rs b/src/tools/clippy/tests/ui/useless_conversion_try.rs index 23edeae12b83a..711c355d3c55e 100644 --- a/src/tools/clippy/tests/ui/useless_conversion_try.rs +++ b/src/tools/clippy/tests/ui/useless_conversion_try.rs @@ -32,19 +32,19 @@ fn main() { let _: String = "foo".try_into().unwrap(); } let _: String = "foo".to_string().try_into().unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ ERROR: useless conversion to the same type: `std::string::string::String` let _: String = TryFrom::try_from("foo".to_string()).unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ ERROR: useless conversion to the same type: `std::string::string::String` let _ = String::try_from("foo".to_string()).unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ ERROR: useless conversion to the same type: `std::string::string::String` let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ ERROR: useless conversion to the same type: `std::string::string::String` let _: String = format!("Hello {}", "world").try_into().unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ ERROR: useless conversion to the same type: `std::string::string::String` let _: String = String::new().try_into().unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ ERROR: useless conversion to the same type: `std::string::string::String` let _: String = match String::from("_").try_into() { - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ ERROR: useless conversion to the same type: `std::string::string::String` Ok(a) => a, Err(_) => String::new(), }; diff --git a/src/tools/clippy/tests/ui/useless_conversion_try.stderr b/src/tools/clippy/tests/ui/useless_conversion_try.stderr index 30a43629dbd6a..3bd7cafbedd67 100644 --- a/src/tools/clippy/tests/ui/useless_conversion_try.stderr +++ b/src/tools/clippy/tests/ui/useless_conversion_try.stderr @@ -19,7 +19,7 @@ LL | val.try_into().unwrap() | = help: consider removing `.try_into()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion_try.rs:34:21 | LL | let _: String = "foo".to_string().try_into().unwrap(); @@ -27,7 +27,7 @@ LL | let _: String = "foo".to_string().try_into().unwrap(); | = help: consider removing `.try_into()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion_try.rs:36:21 | LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); @@ -35,7 +35,7 @@ LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); | = help: consider removing `TryFrom::try_from()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion_try.rs:38:13 | LL | let _ = String::try_from("foo".to_string()).unwrap(); @@ -43,7 +43,7 @@ LL | let _ = String::try_from("foo".to_string()).unwrap(); | = help: consider removing `String::try_from()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion_try.rs:40:13 | LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); @@ -51,7 +51,7 @@ LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); | = help: consider removing `String::try_from()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion_try.rs:42:21 | LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); @@ -59,7 +59,7 @@ LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); | = help: consider removing `.try_into()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion_try.rs:44:21 | LL | let _: String = String::new().try_into().unwrap(); @@ -67,7 +67,7 @@ LL | let _: String = String::new().try_into().unwrap(); | = help: consider removing `.try_into()` -error: useless conversion to the same type: `std::string::String` +error: useless conversion to the same type: `std::string::string::String` --> tests/ui/useless_conversion_try.rs:46:27 | LL | let _: String = match String::from("_").try_into() { diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 19340b5d07a11..66085cc049451 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -35,6 +35,21 @@ use html5ever::tokenizer::{ // [(generated_documentation_page, &[broken_links])] #[rustfmt::skip] const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[ + // These link to methods on std::string::String (the type alias), + // and linkchecker currently cannot deal with that since type alias doc pages + // seem to be lazily loaded-ish?. + ("core/primitive.char.html", &["#method.from_utf8_lossy"]), + ("core/str/fn.from_utf8.html", &["#method.from_utf8"]), + ("core/str/struct.Utf8Chunks.html", &["#method.from_utf8_lossy"]), + ("core/str/struct.Utf8Error.html", &["#method.from_utf8"]), + ("alloc/str/fn.from_utf8.html", &["#method.from_utf8"]), + ("alloc/str/struct.Utf8Chunks.html", &["#method.from_utf8_lossy"]), + ("alloc/str/struct.Utf8Error.html", &["#method.from_utf8"]), + ("std/primitive.char.html", &["#method.from_utf8_lossy"]), + ("std/str/fn.from_utf8.html", &["#method.from_utf8"]), + ("std/str/struct.Utf8Chunks.html", &["#method.from_utf8_lossy"]), + ("std/str/struct.Utf8Error.html", &["#method.from_utf8"]), + // These try to link to std::collections, but are defined in alloc // https://github.com/rust-lang/rust/issues/74481 ("std/collections/btree_map/struct.BTreeMap.html", &["#insert-and-complex-keys"]), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 14af22c319313..229a17ee2c956 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -10850,7 +10850,7 @@ pub fn is_it_the_answer(value: Value) -> bool { } ``` -[its `Deref` implementation]: https://doc.rust-lang.org/std/string/struct.String.html#impl-Deref-for-String +[its `Deref` implementation]: https://doc.rust-lang.org/std/string/type.String.html#impl-Deref-for-String "##, default_severity: Severity::Allow, warn_since: None, diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 839d23fb9a78c..d484a441906ba 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -3635,7 +3635,6 @@ ui/resolve/issue-21221-1.rs ui/resolve/issue-21221-2.rs ui/resolve/issue-21221-3.rs ui/resolve/issue-21221-4.rs -ui/resolve/issue-22692.rs ui/resolve/issue-2330.rs ui/resolve/issue-23305.rs ui/resolve/issue-2356.rs diff --git a/tests/debuginfo/closures.rs b/tests/debuginfo/closures.rs index f5220a49e29dc..fc1e591651a4f 100644 --- a/tests/debuginfo/closures.rs +++ b/tests/debuginfo/closures.rs @@ -14,7 +14,7 @@ // cdb-check: [+0x[...]] _ref__count : 0x[...] : 2 [Type: int *] // cdb-command:dx consume_closure // cdb-check:consume_closure [Type: closures::main::closure_env$2] -// cdb-check: [+0x[...]] x : [...] [Type: alloc::string::String] +// cdb-check: [+0x[...]] x : [...] [Type: alloc::string::string::String] // cdb-check: [+0x[...]] _ref__base_value : 0x[...] : 42 [Type: int *] // cdb-command:dx simple_closure // cdb-checksimple_closure [Type: closures::main::closure_env$5] diff --git a/tests/debuginfo/coroutine-closure.rs b/tests/debuginfo/coroutine-closure.rs index ffb6ae68a2b8b..84a5a013b7eb8 100644 --- a/tests/debuginfo/coroutine-closure.rs +++ b/tests/debuginfo/coroutine-closure.rs @@ -7,8 +7,8 @@ // cdb-command: g // cdb-command: dx closure // cdb-check:closure [Type: coroutine_closure::main::closure_env$0] -// cdb-check: [+0x[...]] y : "" [Type: alloc::string::String] -// cdb-check: [+0x[...]] x : "" [Type: alloc::string::String] +// cdb-check: [+0x[...]] y : "" [Type: alloc::string::string::String] +// cdb-check: [+0x[...]] x : "" [Type: alloc::string::string::String] #![allow(unused)] fn main() { let x = String::new(); diff --git a/tests/debuginfo/embedded-visualizer.rs b/tests/debuginfo/embedded-visualizer.rs index cbd8691394d54..4cf1c5fa1c223 100644 --- a/tests/debuginfo/embedded-visualizer.rs +++ b/tests/debuginfo/embedded-visualizer.rs @@ -39,7 +39,7 @@ // cdb-command: dx person // cdb-check:person : "Person A" is 10 years old. [Type: dependency_with_embedded_visualizers::Person] // cdb-check: [] [Type: dependency_with_embedded_visualizers::Person] -// cdb-check: [name] : "Person A" [Type: alloc::string::String] +// cdb-check: [name] : "Person A" [Type: alloc::string::string::String] // cdb-check: [age] : 10 [Type: int] // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/marker-types.rs b/tests/debuginfo/marker-types.rs index 6686b057ef7b3..f8eed85c9e295 100644 --- a/tests/debuginfo/marker-types.rs +++ b/tests/debuginfo/marker-types.rs @@ -15,8 +15,8 @@ // cdb-check: [] [Type: core::mem::manually_drop::ManuallyDrop] // cdb-command: dx pin -// cdb-check:pin : Pin(0x[...]: "this") [Type: core::pin::Pin >] -// cdb-check: [] [Type: core::pin::Pin >] +// cdb-check:pin : Pin(0x[...]: "this") [Type: core::pin::Pin > >] +// cdb-check: [] [Type: core::pin::Pin > >] // cdb-check: [len] : 0x4 [Type: unsigned [...]] // cdb-check: [capacity] : 0x4 [Type: unsigned [...]] // cdb-check: [chars] : "this" diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs index d60a7b81944e7..503b84bdc42d0 100644 --- a/tests/debuginfo/msvc-pretty-enums.rs +++ b/tests/debuginfo/msvc-pretty-enums.rs @@ -30,7 +30,7 @@ // lldb-check:(msvc_pretty_enums::CStyleEnum) j = High // lldb-command:v k -// lldb-check:(core::option::Option) k = { value = { 0 = "IAMA optional string!" { vec = size=21 { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 'o' [6] = 'p' [7] = 't' [8] = 'i' [9] = 'o' [10] = 'n' [11] = 'a' [12] = 'l' [13] = ' ' [14] = 's' [15] = 't' [16] = 'r' [17] = 'i' [18] = 'n' [19] = 'g' [20] = '!' } } } } +// lldb-check:(core::option::Option>) k = { value = { 0 = "IAMA optional string!" { vec = size=21 { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 'o' [6] = 'p' [7] = 't' [8] = 'i' [9] = 'o' [10] = 'n' [11] = 'a' [12] = 'l' [13] = ' ' [14] = 's' [15] = 't' [16] = 'r' [17] = 'i' [18] = 'n' [19] = 'g' [20] = '!' } } } } // lldb-command:v l // lldb-check:(core::result::Result) l = { value = { 0 = {} } } @@ -112,9 +112,9 @@ // cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] // // cdb-command: dx k -// cdb-check:k : Some [Type: enum2$ >] -// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] -// +// cdb-check:k : Some [Type: enum2$ > >] +// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::string::String] + // cdb-command: dx l // cdb-check:l : Ok [Type: enum2$ > >] // cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int] diff --git a/tests/debuginfo/pretty-std.rs b/tests/debuginfo/pretty-std.rs index d7c640a5bea3e..da33d65cacab8 100644 --- a/tests/debuginfo/pretty-std.rs +++ b/tests/debuginfo/pretty-std.rs @@ -31,11 +31,11 @@ // gdb-check:$7 = "IAMA OS string 😃" // gdb-command: print some_string -// gdb-check:$8 = core::option::Option::Some("IAMA optional string!") +// gdb-check:$8 = core::option::Option>::Some("IAMA optional string!") // gdb-command: set print elements 5 // gdb-command: print some_string -// gdb-check:$9 = core::option::Option::Some("IAMA "...) +// gdb-check:$9 = core::option::Option>::Some("IAMA "...) // === LLDB TESTS ================================================================================== @@ -123,9 +123,9 @@ // cdb-check: [] [Type: enum2$ >] // cdb-command: dx some_string -// cdb-check:some_string : Some [Type: enum2$ >] -// cdb-check: [] [Type: enum2$ >] -// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] +// cdb-check:some_string : Some [Type: enum2$ > >] +// cdb-check: [] [Type: enum2$ > >] +// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::string::String] // cdb-command: dx linkedlist // cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList] diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 543e74e174417..e552d5f8ce1b4 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -7,7 +7,7 @@ // gdb-command:run // gdb-command:print plain_string -// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: core::num::niche_types::UsizeNoHighBit (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} +// gdb-check:$1 = alloc::string::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: core::num::niche_types::UsizeNoHighBit (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} // gdb-command:print plain_str // gdb-check:$2 = "Hello" @@ -24,7 +24,7 @@ // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:v plain_string -// lldb-check:(alloc::string::String) plain_string = "Hello" { vec = size=5 { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } +// lldb-check:(alloc::string::string::String) plain_string = "Hello" { vec = size=5 { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } // lldb-command:v plain_str // lldb-check:(&str) plain_str = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } @@ -38,7 +38,6 @@ // lldb-command:v str_in_rc // lldb-check:(alloc::rc::Rc<&str, alloc::alloc::Global>) str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } - #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] diff --git a/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir b/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir index 9f52a8cd1e55e..7b08c498531a8 100644 --- a/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir +++ b/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir @@ -5,10 +5,10 @@ fn foo(_1: Option) -> i32 { let mut _0: i32; let mut _2: bool; let mut _3: isize; - let mut _4: &std::string::String; + let mut _4: &std::string::string::String; let mut _5: &str; let mut _6: bool; - let _7: std::option::Option; + let _7: std::option::Option; scope 1 { debug s => _7; } @@ -21,7 +21,7 @@ fn foo(_1: Option) -> i32 { } bb1: { - _4 = &((_1 as Some).0: std::string::String); + _4 = &((_1 as Some).0: std::string::string::String); _5 = ::deref(move _4) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir index 7e033916fd348..0fb0eb0d43b61 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir +++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir @@ -3,14 +3,14 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12:7}) -> () { let mut _0: (); let mut _2: (); - let _3: std::string::String; + let _3: std::string::string::String; let _4: (); let mut _5: (); let mut _6: (); let mut _7: (); let mut _8: u32; scope 1 { - debug _s => (((*_1) as variant#3).0: std::string::String); + debug _s => (((*_1) as variant#3).0: std::string::string::String); } bb0: { @@ -21,7 +21,7 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 bb1: { StorageDead(_5); StorageDead(_4); - drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb2, unwind unreachable]; + drop((((*_1) as variant#3).0: std::string::string::String)) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir index 613ef2909b5e4..b99c2f885e21b 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir +++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir @@ -3,14 +3,14 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12:7}) -> () { let mut _0: (); let mut _2: (); - let _3: std::string::String; + let _3: std::string::string::String; let _4: (); let mut _5: (); let mut _6: (); let mut _7: (); let mut _8: u32; scope 1 { - debug _s => (((*_1) as variant#3).0: std::string::String); + debug _s => (((*_1) as variant#3).0: std::string::string::String); } bb0: { @@ -21,7 +21,7 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 bb1: { StorageDead(_5); StorageDead(_4); - drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb2, unwind: bb5]; + drop((((*_1) as variant#3).0: std::string::string::String)) -> [return: bb2, unwind: bb5]; } bb2: { diff --git a/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-abort.diff b/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-abort.diff index 5ae575f300afb..78a7f79c82029 100644 --- a/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-abort.diff @@ -11,10 +11,10 @@ let mut _6: u16; let mut _7: MyId; let mut _9: u16; - let mut _10: std::marker::PhantomData; + let mut _10: std::marker::PhantomData; let _11: (); let mut _12: u16; - let mut _13: TypedId; + let mut _13: TypedId; let mut _15: u16; let _16: (); let mut _17: u16; @@ -52,7 +52,7 @@ let mut _56: *const i32; scope 1 { debug a => _3; - let _8: TypedId; + let _8: TypedId; scope 2 { debug b => _8; let _14: std::result::Result; diff --git a/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-unwind.diff b/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-unwind.diff index 3119a93fb8912..55d681b2aa35b 100644 --- a/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.aggregate_struct_then_transmute.GVN.panic-unwind.diff @@ -11,10 +11,10 @@ let mut _6: u16; let mut _7: MyId; let mut _9: u16; - let mut _10: std::marker::PhantomData; + let mut _10: std::marker::PhantomData; let _11: (); let mut _12: u16; - let mut _13: TypedId; + let mut _13: TypedId; let mut _15: u16; let _16: (); let mut _17: u16; @@ -52,7 +52,7 @@ let mut _56: *const i32; scope 1 { debug a => _3; - let _8: TypedId; + let _8: TypedId; scope 2 { debug b => _8; let _14: std::result::Result; diff --git a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff index cc9177c90027d..11bbe80ab4ec2 100644 --- a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff @@ -5,8 +5,8 @@ debug r => _1; debug v => _2; let mut _0: (); - let mut _3: *mut std::string::String; - let mut _4: std::string::String; + let mut _3: *mut std::string::string::String; + let mut _4: std::string::string::String; bb0: { StorageLive(_3); diff --git a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff index cc9177c90027d..11bbe80ab4ec2 100644 --- a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff @@ -5,8 +5,8 @@ debug r => _1; debug v => _2; let mut _0: (); - let mut _3: *mut std::string::String; - let mut _4: std::string::String; + let mut _3: *mut std::string::string::String; + let mut _4: std::string::string::String; bb0: { StorageLive(_3); diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index b3eb3e1f8b9d2..2523f831b2c39 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -9,8 +9,8 @@ let mut _4: &bool; let _5: bool; let _6: &bool; - let _7: std::string::String; - let _8: &std::string::String; + let _7: std::string::string::String; + let _8: &std::string::string::String; let mut _9: bool; let mut _10: bool; let mut _11: !; @@ -18,7 +18,7 @@ let mut _13: bool; let mut _14: !; let _15: bool; - let _16: std::string::String; + let _16: std::string::string::String; scope 1 { debug a => _5; debug a => _6; @@ -62,7 +62,7 @@ StorageLive(_15); _15 = copy (_2.1: bool); StorageLive(_16); - _16 = move (_2.2: std::string::String); + _16 = move (_2.2: std::string::string::String); - goto -> bb20; + goto -> bb17; } @@ -72,7 +72,7 @@ StorageLive(_15); _15 = copy (_2.1: bool); StorageLive(_16); - _16 = move (_2.2: std::string::String); + _16 = move (_2.2: std::string::string::String); - goto -> bb20; + goto -> bb17; } @@ -82,7 +82,7 @@ StorageLive(_6); _6 = &(_2.0: bool); StorageLive(_8); - _8 = &(_2.2: std::string::String); + _8 = &(_2.2: std::string::string::String); - _3 = &fake shallow (_2.0: bool); - _4 = &fake shallow (_2.1: bool); StorageLive(_12); @@ -97,7 +97,7 @@ StorageLive(_6); _6 = &(_2.1: bool); StorageLive(_8); - _8 = &(_2.2: std::string::String); + _8 = &(_2.2: std::string::string::String); - _3 = &fake shallow (_2.0: bool); - _4 = &fake shallow (_2.1: bool); StorageLive(_9); @@ -141,7 +141,7 @@ StorageLive(_5); _5 = copy (_2.1: bool); StorageLive(_7); - _7 = move (_2.2: std::string::String); + _7 = move (_2.2: std::string::string::String); - goto -> bb10; + goto -> bb7; } @@ -183,7 +183,7 @@ StorageLive(_5); _5 = copy (_2.0: bool); StorageLive(_7); - _7 = move (_2.2: std::string::String); + _7 = move (_2.2: std::string::string::String); - goto -> bb10; + goto -> bb7; } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index b3eb3e1f8b9d2..2523f831b2c39 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -9,8 +9,8 @@ let mut _4: &bool; let _5: bool; let _6: &bool; - let _7: std::string::String; - let _8: &std::string::String; + let _7: std::string::string::String; + let _8: &std::string::string::String; let mut _9: bool; let mut _10: bool; let mut _11: !; @@ -18,7 +18,7 @@ let mut _13: bool; let mut _14: !; let _15: bool; - let _16: std::string::String; + let _16: std::string::string::String; scope 1 { debug a => _5; debug a => _6; @@ -62,7 +62,7 @@ StorageLive(_15); _15 = copy (_2.1: bool); StorageLive(_16); - _16 = move (_2.2: std::string::String); + _16 = move (_2.2: std::string::string::String); - goto -> bb20; + goto -> bb17; } @@ -72,7 +72,7 @@ StorageLive(_15); _15 = copy (_2.1: bool); StorageLive(_16); - _16 = move (_2.2: std::string::String); + _16 = move (_2.2: std::string::string::String); - goto -> bb20; + goto -> bb17; } @@ -82,7 +82,7 @@ StorageLive(_6); _6 = &(_2.0: bool); StorageLive(_8); - _8 = &(_2.2: std::string::String); + _8 = &(_2.2: std::string::string::String); - _3 = &fake shallow (_2.0: bool); - _4 = &fake shallow (_2.1: bool); StorageLive(_12); @@ -97,7 +97,7 @@ StorageLive(_6); _6 = &(_2.1: bool); StorageLive(_8); - _8 = &(_2.2: std::string::String); + _8 = &(_2.2: std::string::string::String); - _3 = &fake shallow (_2.0: bool); - _4 = &fake shallow (_2.1: bool); StorageLive(_9); @@ -141,7 +141,7 @@ StorageLive(_5); _5 = copy (_2.1: bool); StorageLive(_7); - _7 = move (_2.2: std::string::String); + _7 = move (_2.2: std::string::string::String); - goto -> bb10; + goto -> bb7; } @@ -183,7 +183,7 @@ StorageLive(_5); _5 = copy (_2.0: bool); StorageLive(_7); - _7 = move (_2.2: std::string::String); + _7 = move (_2.2: std::string::string::String); - goto -> bb10; + goto -> bb7; } diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir index 99a7a6b6154d5..1a90ba69aa698 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir @@ -3,7 +3,7 @@ fn main() -> () { let mut _0: (); let _1: (); - let mut _2: std::string::String; + let mut _2: std::string::string::String; let mut _3: &str; let _4: &str; diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir index 7364b329e123a..c1daaafab966a 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir @@ -3,7 +3,7 @@ fn main() -> () { let mut _0: (); let _1: (); - let mut _2: std::string::String; + let mut _2: std::string::string::String; let mut _3: &str; let _4: &str; diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir index 13df2195ab04d..6892357eb3132 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir @@ -2,13 +2,13 @@ fn std::ptr::drop_in_place(_1: *mut [String; 42]) -> () { let mut _0: (); - let mut _2: *mut [std::string::String; 42]; - let mut _3: *mut [std::string::String]; + let mut _2: *mut [std::string::string::String; 42]; + let mut _3: *mut [std::string::string::String]; let mut _4: usize; let mut _5: usize; - let mut _6: *mut std::string::String; + let mut _6: *mut std::string::string::String; let mut _7: bool; - let mut _8: *mut std::string::String; + let mut _8: *mut std::string::string::String; let mut _9: bool; bb0: { @@ -57,7 +57,7 @@ fn std::ptr::drop_in_place(_1: *mut [String; 42]) -> () { bb9: { _2 = &raw mut (*_1); - _3 = move _2 as *mut [std::string::String] (PointerCoercion(Unsize, Implicit)); + _3 = move _2 as *mut [std::string::string::String] (PointerCoercion(Unsize, Implicit)); goto -> bb8; } } diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index 0633b765644d5..abc06f9729ca1 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir @@ -4,9 +4,9 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () { let mut _0: (); let mut _2: usize; let mut _3: usize; - let mut _4: *mut std::string::String; + let mut _4: *mut std::string::string::String; let mut _5: bool; - let mut _6: *mut std::string::String; + let mut _6: *mut std::string::string::String; let mut _7: bool; bb0: { diff --git a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff index 9a4f27a497d18..c219bc837bd1f 100644 --- a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff @@ -4,19 +4,19 @@ fn f() -> () { let mut _0: (); let mut _1: !; - let _2: std::string::String; + let _2: std::string::string::String; let _6: (); - let mut _7: std::string::String; + let mut _7: std::string::string::String; + let mut _8: bool; scope 1 { debug _a => _2; let _3: i32; scope 2 { debug _b => _3; - let _4: std::string::String; + let _4: std::string::string::String; scope 3 { debug _c => _4; - let _5: std::string::String; + let _5: std::string::string::String; scope 4 { debug _d => _5; } diff --git a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff index f13ee78aa368c..9b708d0431a3d 100644 --- a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff @@ -4,19 +4,19 @@ fn f() -> () { let mut _0: (); let mut _1: !; - let _2: std::string::String; + let _2: std::string::string::String; let _6: (); - let mut _7: std::string::String; + let mut _7: std::string::string::String; + let mut _8: bool; scope 1 { debug _a => _2; let _3: i32; scope 2 { debug _b => _3; - let _4: std::string::String; + let _4: std::string::string::String; scope 3 { debug _c => _4; - let _5: std::string::String; + let _5: std::string::string::String; scope 4 { debug _d => _5; } diff --git a/tests/mir-opt/tail_call_drops.f.built.after.panic-abort.mir b/tests/mir-opt/tail_call_drops.f.built.after.panic-abort.mir index e017424a4ccdd..d92b3614798de 100644 --- a/tests/mir-opt/tail_call_drops.f.built.after.panic-abort.mir +++ b/tests/mir-opt/tail_call_drops.f.built.after.panic-abort.mir @@ -3,18 +3,18 @@ fn f() -> () { let mut _0: (); let mut _1: !; - let _2: std::string::String; + let _2: std::string::string::String; let _6: (); - let mut _7: std::string::String; + let mut _7: std::string::string::String; scope 1 { debug _a => _2; let _3: i32; scope 2 { debug _b => _3; - let _4: std::string::String; + let _4: std::string::string::String; scope 3 { debug _c => _4; - let _5: std::string::String; + let _5: std::string::string::String; scope 4 { debug _d => _5; } diff --git a/tests/mir-opt/tail_call_drops.f.built.after.panic-unwind.mir b/tests/mir-opt/tail_call_drops.f.built.after.panic-unwind.mir index e017424a4ccdd..d92b3614798de 100644 --- a/tests/mir-opt/tail_call_drops.f.built.after.panic-unwind.mir +++ b/tests/mir-opt/tail_call_drops.f.built.after.panic-unwind.mir @@ -3,18 +3,18 @@ fn f() -> () { let mut _0: (); let mut _1: !; - let _2: std::string::String; + let _2: std::string::string::String; let _6: (); - let mut _7: std::string::String; + let mut _7: std::string::string::String; scope 1 { debug _a => _2; let _3: i32; scope 2 { debug _b => _3; - let _4: std::string::String; + let _4: std::string::string::String; scope 3 { debug _c => _4; - let _5: std::string::String; + let _5: std::string::string::String; scope 4 { debug _d => _5; } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff index a8c57d2cfe009..d190ed2bfa9b7 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff @@ -6,21 +6,21 @@ debug _arg2 => _2; let mut _0: (); let mut _3: !; - let _4: std::string::String; + let _4: std::string::string::String; let _8: (); - let mut _9: std::string::String; - let mut _10: std::string::String; - let mut _11: std::string::String; + let mut _9: std::string::string::String; + let mut _10: std::string::string::String; + let mut _11: std::string::string::String; + let mut _12: bool; scope 1 { debug _a => _4; let _5: i32; scope 2 { debug _b => _5; - let _6: std::string::String; + let _6: std::string::string::String; scope 3 { debug _c => _6; - let _7: std::string::String; + let _7: std::string::string::String; scope 4 { debug _d => _7; } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff index a8c57d2cfe009..d190ed2bfa9b7 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff @@ -6,21 +6,21 @@ debug _arg2 => _2; let mut _0: (); let mut _3: !; - let _4: std::string::String; + let _4: std::string::string::String; let _8: (); - let mut _9: std::string::String; - let mut _10: std::string::String; - let mut _11: std::string::String; + let mut _9: std::string::string::String; + let mut _10: std::string::string::String; + let mut _11: std::string::string::String; + let mut _12: bool; scope 1 { debug _a => _4; let _5: i32; scope 2 { debug _b => _5; - let _6: std::string::String; + let _6: std::string::string::String; scope 3 { debug _c => _6; - let _7: std::string::String; + let _7: std::string::string::String; scope 4 { debug _d => _7; } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-abort.mir b/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-abort.mir index f89b98a320536..4a73f36666033 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-abort.mir +++ b/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-abort.mir @@ -5,20 +5,20 @@ fn f_with_arg(_1: String, _2: String) -> () { debug _arg2 => _2; let mut _0: (); let mut _3: !; - let _4: std::string::String; + let _4: std::string::string::String; let _8: (); - let mut _9: std::string::String; - let mut _10: std::string::String; - let mut _11: std::string::String; + let mut _9: std::string::string::String; + let mut _10: std::string::string::String; + let mut _11: std::string::string::String; scope 1 { debug _a => _4; let _5: i32; scope 2 { debug _b => _5; - let _6: std::string::String; + let _6: std::string::string::String; scope 3 { debug _c => _6; - let _7: std::string::String; + let _7: std::string::string::String; scope 4 { debug _d => _7; } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-unwind.mir b/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-unwind.mir index f89b98a320536..4a73f36666033 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-unwind.mir +++ b/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-unwind.mir @@ -5,20 +5,20 @@ fn f_with_arg(_1: String, _2: String) -> () { debug _arg2 => _2; let mut _0: (); let mut _3: !; - let _4: std::string::String; + let _4: std::string::string::String; let _8: (); - let mut _9: std::string::String; - let mut _10: std::string::String; - let mut _11: std::string::String; + let mut _9: std::string::string::String; + let mut _10: std::string::string::String; + let mut _11: std::string::string::String; scope 1 { debug _a => _4; let _5: i32; scope 2 { debug _b => _5; - let _6: std::string::String; + let _6: std::string::string::String; scope 3 { debug _c => _6; - let _7: std::string::String; + let _7: std::string::string::String; scope 4 { debug _d => _7; } diff --git a/tests/rustdoc/check-source-code-urls-to-def.rs b/tests/rustdoc/check-source-code-urls-to-def.rs index 8703287abc553..cbb2575b6a015 100644 --- a/tests/rustdoc/check-source-code-urls-to-def.rs +++ b/tests/rustdoc/check-source-code-urls-to-def.rs @@ -28,7 +28,7 @@ impl Foo { fn babar() {} -//@ has - '//pre[@class="rust"]//a/@href' '/struct.String.html' +//@ has - '//pre[@class="rust"]//a/@href' '/type.String.html' //@ has - '//pre[@class="rust"]//a/@href' '/primitive.u32.html' //@ has - '//pre[@class="rust"]//a/@href' '/primitive.str.html' //@ count - '//pre[@class="rust"]//a[@href="#23"]' 5 diff --git a/tests/rustdoc/decl-trailing-whitespace.declaration.html b/tests/rustdoc/decl-trailing-whitespace.declaration.html index 0cc3f0fa244e1..5978bb90f02b6 100644 --- a/tests/rustdoc/decl-trailing-whitespace.declaration.html +++ b/tests/rustdoc/decl-trailing-whitespace.declaration.html @@ -2,16 +2,16 @@ // Required methods fn poll_write( self, - cx: &mut Option<String>, + cx: &mut Option<String>, buf: &mut [usize], ) -> Option<Result<usize, Error>>; - fn poll_flush(self, cx: &mut Option<String>) -> Option<Result<(), Error>>; - fn poll_close(self, cx: &mut Option<String>) -> Option<Result<(), Error>>; + fn poll_flush(self, cx: &mut Option<String>) -> Option<Result<(), Error>>; + fn poll_close(self, cx: &mut Option<String>) -> Option<Result<(), Error>>; // Provided method fn poll_write_vectored( self, - cx: &mut Option<String>, + cx: &mut Option<String>, bufs: &[usize], ) -> Option<Result<usize, Error>> { ... } } \ No newline at end of file diff --git a/tests/rustdoc/intra-doc/associated-items.rs b/tests/rustdoc/intra-doc/associated-items.rs index 84cfd06111df7..caed10804dd4f 100644 --- a/tests/rustdoc/intra-doc/associated-items.rs +++ b/tests/rustdoc/intra-doc/associated-items.rs @@ -4,7 +4,7 @@ /// [`String::from`] is ambiguous as to which `From` impl /// [Vec::into_iter()] uses a disambiguator //@ has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter' -//@ has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/string/struct.String.html#method.from"]' 'String::from' +//@ has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/string/string/struct.String.html#method.from"]' 'String::from' //@ has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter' pub fn foo() {} diff --git a/tests/rustdoc/masked.rs b/tests/rustdoc/masked.rs index 4f361ca881e3f..12b9ba1c15cd3 100644 --- a/tests/rustdoc/masked.rs +++ b/tests/rustdoc/masked.rs @@ -9,9 +9,9 @@ extern crate masked; //@ !hasraw 'search-index.js' 'masked_method' -//@ !hasraw 'foo/struct.String.html' 'MaskedTrait' -//@ !hasraw 'foo/struct.String.html' 'MaskedBlanketTrait' -//@ !hasraw 'foo/struct.String.html' 'masked_method' +//@ !hasraw 'foo/type.String.html' 'MaskedTrait' +//@ !hasraw 'foo/type.String.html' 'MaskedBlanketTrait' +//@ !hasraw 'foo/type.String.html' 'masked_method' pub use std::string::String; //@ !hasraw 'foo/trait.Clone.html' 'MaskedStruct' diff --git a/tests/ui/associated-inherent-types/dispatch-on-self-type-2.stderr b/tests/ui/associated-inherent-types/dispatch-on-self-type-2.stderr index c9a48872af40e..52a01fa903a09 100644 --- a/tests/ui/associated-inherent-types/dispatch-on-self-type-2.stderr +++ b/tests/ui/associated-inherent-types/dispatch-on-self-type-2.stderr @@ -5,6 +5,9 @@ LL | let _: Parameterized<(), ()>::Output = String::new(); | ----------------------------- ^^^^^^^^^^^^^ expected `bool`, found `String` | | | expected due to this + | + = note: expected type `bool` + found struct `String` error[E0308]: mismatched types --> $DIR/dispatch-on-self-type-2.rs:16:47 diff --git a/tests/ui/associated-types/hr-associated-type-bound-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-1.stderr index 5b00e714194d6..1719f1ee73b35 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-1.rs:3:33 | @@ -20,7 +20,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | 1i32.f("abc"); | ^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X::f` --> $DIR/hr-associated-type-bound-1.rs:3:33 | diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr index 07d3afb74e416..633d715f07a06 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type V = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Y` --> $DIR/hr-associated-type-bound-param-1.rs:4:36 | @@ -20,7 +20,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | 1u8.g("abc"); | ^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Y::g` --> $DIR/hr-associated-type-bound-param-1.rs:4:36 | diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr index 74cc2083d26fe..3a228160cf6f8 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | T: Z<'a, u16>, | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -20,7 +20,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type W = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -36,7 +36,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | T: Z<'a, u16>, | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -53,7 +53,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | ::clone(x); | ^^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z::W` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -69,7 +69,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | ::clone(x); | ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -85,7 +85,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | 1u16.h("abc"); | ^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z::h` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr index 06dca48b61645..d5b1a7667eb52 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-3.rs:4:33 | @@ -20,7 +20,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | <(i32,) as X<(i32,)>>::f("abc"); | ^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X::f` --> $DIR/hr-associated-type-bound-param-3.rs:4:33 | diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr index da0cf6f55ba7c..aad5cd7d194f9 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-4.rs:4:36 | @@ -20,7 +20,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | <(i32,) as X>::f("abc"); | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X::f` --> $DIR/hr-associated-type-bound-param-4.rs:4:36 | diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr index dd576577dce72..a185f1dceffc0 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-5.rs:17:45 | @@ -20,7 +20,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-5.rs:17:45 | @@ -36,7 +36,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | >>::f("abc"); | ^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X::f` --> $DIR/hr-associated-type-bound-param-5.rs:15:33 | diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index bdfcbed71e9a6..6c21acb57d7ee 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -7,7 +7,7 @@ LL | trait Trait: Iterator = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(<::Item as std::marker::Copy>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } error: rustc_dump_predicates @@ -19,7 +19,7 @@ LL | type Assoc: std::ops::Deref = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(<::Item as std::marker::Copy>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(

, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(

, polarity:Positive), bound_vars: [] } diff --git a/tests/ui/attributes/rustc_confusables_std_cases.stderr b/tests/ui/attributes/rustc_confusables_std_cases.stderr index 7bf96241ca725..1e37af95e0c67 100644 --- a/tests/ui/attributes/rustc_confusables_std_cases.stderr +++ b/tests/ui/attributes/rustc_confusables_std_cases.stderr @@ -89,7 +89,7 @@ LL | String::new().push(""); | arguments to this method are incorrect | note: method defined here - --> $SRC_DIR/alloc/src/string.rs:LL:COL + --> $SRC_DIR/alloc/src/string/string.rs:LL:COL help: you might have meant to use `push_str` | LL | String::new().push_str(""); diff --git a/tests/ui/binop/binop-bitxor-str.stderr b/tests/ui/binop/binop-bitxor-str.stderr index 9d9ec6c5af6be..65c220add657f 100644 --- a/tests/ui/binop/binop-bitxor-str.stderr +++ b/tests/ui/binop/binop-bitxor-str.stderr @@ -7,7 +7,7 @@ LL | fn main() { let x = "a".to_string() ^ "b".to_string(); } | String | note: the foreign item type `String` doesn't implement `BitXor` - --> $SRC_DIR/alloc/src/string.rs:LL:COL + --> $SRC_DIR/alloc/src/string/string.rs:LL:COL | = note: not implement `BitXor` diff --git a/tests/ui/block-result/consider-removing-last-semi.stderr b/tests/ui/block-result/consider-removing-last-semi.stderr index d30ab1293431b..aab109a48b176 100644 --- a/tests/ui/block-result/consider-removing-last-semi.stderr +++ b/tests/ui/block-result/consider-removing-last-semi.stderr @@ -8,6 +8,9 @@ LL | pub fn f() -> String { LL | 0u8; LL | "bla".to_string(); | - help: remove this semicolon to return this value + | + = note: expected struct `String` + found unit type `()` error[E0308]: mismatched types --> $DIR/consider-removing-last-semi.rs:8:15 @@ -19,6 +22,9 @@ LL | pub fn g() -> String { LL | "this won't work".to_string(); LL | "removeme".to_string(); | - help: remove this semicolon to return this value + | + = note: expected struct `String` + found unit type `()` error[E0308]: mismatched types --> $DIR/consider-removing-last-semi.rs:13:25 diff --git a/tests/ui/block-result/issue-13428.stderr b/tests/ui/block-result/issue-13428.stderr index c119b69da2294..76ad1db061235 100644 --- a/tests/ui/block-result/issue-13428.stderr +++ b/tests/ui/block-result/issue-13428.stderr @@ -5,6 +5,9 @@ LL | fn foo() -> String { | --- ^^^^^^ expected `String`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `String` + found unit type `()` error[E0308]: mismatched types --> $DIR/issue-13428.rs:11:13 @@ -16,6 +19,9 @@ LL | fn bar() -> String { LL | "foobar".to_string() LL | ; | - help: remove this semicolon to return this value + | + = note: expected struct `String` + found unit type `()` error: aborting due to 2 previous errors diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr index 3af7e7cddb31d..dbcf6d181c288 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.stderr +++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr @@ -68,6 +68,8 @@ LL | | return String::from("test"); LL | | } | |_____^ expected `String`, found `()` | + = note: expected struct `String` + found unit type `()` = note: `for` loops evaluate to unit type `()` help: consider returning a value here | diff --git a/tests/ui/consts/miri_unleashed/assoc_const_2.rs b/tests/ui/consts/miri_unleashed/assoc_const_2.rs index 5490c0963915b..5b5476cbeca0f 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const_2.rs +++ b/tests/ui/consts/miri_unleashed/assoc_const_2.rs @@ -7,7 +7,7 @@ trait Foo { } trait Bar { - const F: u32 = 100 / U::X; //~ ERROR evaluation of `>::F` failed + const F: u32 = 100 / U::X; //~ ERROR evaluation of `>::F` failed } impl Foo for () { diff --git a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr index e923d95b7550c..9f7960a2fb92e 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr +++ b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of `>::F` failed +error[E0080]: evaluation of `>::F` failed --> $DIR/assoc_const_2.rs:10:20 | LL | const F: u32 = 100 / U::X; diff --git a/tests/ui/deref-patterns/gate.stderr b/tests/ui/deref-patterns/gate.stderr index e3cbded339d7f..bf94ed8703fe7 100644 --- a/tests/ui/deref-patterns/gate.stderr +++ b/tests/ui/deref-patterns/gate.stderr @@ -5,6 +5,9 @@ LL | match String::new() { | ------------- this expression has type `String` LL | "" | _ => {} | ^^ expected `String`, found `&str` + | + = note: expected struct `String` + found reference `&'static str` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr index 856c92217b924..254ae967e171a 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr @@ -7,6 +7,9 @@ LL | 42 | ^^- help: try using a conversion method: `.to_string()` | | | expected `String`, found integer + | + = note: expected struct `String` + found type `{integer}` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr index 3c737f095ce1e..ce640f485e7e4 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr @@ -6,6 +6,9 @@ LL | fn lol(&self) -> impl Deref { LL | LL | &1i32 | ----- return type was inferred to be `&i32` here + | + = note: expected struct `String` + found type `i32` error: aborting due to 1 previous error diff --git a/tests/ui/inference/deref-suggestion.stderr b/tests/ui/inference/deref-suggestion.stderr index 096989db0b4e8..e4f665640151e 100644 --- a/tests/ui/inference/deref-suggestion.stderr +++ b/tests/ui/inference/deref-suggestion.stderr @@ -7,6 +7,8 @@ LL | foo(s); | | expected `String`, found `&String` | arguments to this function are incorrect | + = note: expected struct `String` + found reference `&String` note: function defined here --> $DIR/deref-suggestion.rs:5:4 | @@ -39,6 +41,8 @@ LL | foo(&"aaa".to_owned()); | | | arguments to this function are incorrect | + = note: expected struct `String` + found reference `&String` note: function defined here --> $DIR/deref-suggestion.rs:5:4 | @@ -58,6 +62,8 @@ LL | foo(&mut "aaa".to_owned()); | | | arguments to this function are incorrect | + = note: expected struct `String` + found mutable reference `&mut String` note: function defined here --> $DIR/deref-suggestion.rs:5:4 | diff --git a/tests/ui/inference/issue-71732.stderr b/tests/ui/inference/issue-71732.stderr index af8b310fd1d9c..994e90b03fd2a 100644 --- a/tests/ui/inference/issue-71732.stderr +++ b/tests/ui/inference/issue-71732.stderr @@ -7,7 +7,8 @@ LL | .get(&"key".into()) | cannot infer type of the type parameter `Q` declared on the method `get` | = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: - - impl Borrow for String; + - impl Borrow for String + where A: Allocator; - impl Borrow for T where T: ?Sized; note: required by a bound in `HashMap::::get` diff --git a/tests/ui/inference/issue-72616.stderr b/tests/ui/inference/issue-72616.stderr index a26f9a1ff5618..96389ffeed03d 100644 --- a/tests/ui/inference/issue-72616.stderr +++ b/tests/ui/inference/issue-72616.stderr @@ -8,12 +8,8 @@ LL | if String::from("a") == "a".try_into().unwrap() {} | = note: cannot satisfy `String: PartialEq<_>` = help: the following types implement trait `PartialEq`: - `String` implements `PartialEq<&str>` `String` implements `PartialEq` `String` implements `PartialEq` - `String` implements `PartialEq>` - `String` implements `PartialEq` - `String` implements `PartialEq` help: try using a fully qualified path to specify the expected types | LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap() {} diff --git a/tests/ui/issues/issue-53348.rs b/tests/ui/issues/issue-53348.rs index 66800d9e92961..cc2bd520a4466 100644 --- a/tests/ui/issues/issue-53348.rs +++ b/tests/ui/issues/issue-53348.rs @@ -10,6 +10,7 @@ fn main() { a = *i.to_string(); //~^ ERROR mismatched types //~| NOTE expected `String`, found `str` + //~| NOTE expected struct `String` v2.push(a); } } diff --git a/tests/ui/issues/issue-53348.stderr b/tests/ui/issues/issue-53348.stderr index 38fa98e65e138..e057af322c503 100644 --- a/tests/ui/issues/issue-53348.stderr +++ b/tests/ui/issues/issue-53348.stderr @@ -6,6 +6,9 @@ LL | let mut a = String::new(); LL | for i in v { LL | a = *i.to_string(); | ^^^^^^^^^^^^^^ expected `String`, found `str` + | + = note: expected struct `String` + found type `str` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-61106.stderr b/tests/ui/issues/issue-61106.stderr index f825141fa062a..3e7c502b78375 100644 --- a/tests/ui/issues/issue-61106.stderr +++ b/tests/ui/issues/issue-61106.stderr @@ -6,6 +6,8 @@ LL | foo(x.clone()); | | | arguments to this function are incorrect | + = note: expected reference `&str` + found struct `String` note: function defined here --> $DIR/issue-61106.rs:6:4 | diff --git a/tests/ui/json/json-bom-plus-crlf-multifile.stderr b/tests/ui/json/json-bom-plus-crlf-multifile.stderr index 9c88a7e5a2564..2189baf5653f4 100644 --- a/tests/ui/json/json-bom-plus-crlf-multifile.stderr +++ b/tests/ui/json/json-bom-plus-crlf-multifile.stderr @@ -24,7 +24,8 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":623,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":613,"byte_end":619,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":623,"byte_end":623,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types: expected `String`, found integer +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":623,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":613,"byte_end":619,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":623,"byte_end":623,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -52,7 +53,8 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":683,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":673,"byte_end":679,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":683,"byte_end":683,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types: expected `String`, found integer +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":683,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":673,"byte_end":679,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":683,"byte_end":683,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -80,7 +82,8 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":747,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":736,"byte_end":742,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":747,"byte_end":747,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types: expected `String`, found integer +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":747,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":736,"byte_end":742,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":747,"byte_end":747,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -108,7 +111,8 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":802,"byte_end":810,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":793,"byte_end":799,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types: expected `String`, found `()` +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":802,"byte_end":810,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":793,"byte_end":799,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `String` +found unit type `()`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types: expected `String`, found `()` "} {"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors "} diff --git a/tests/ui/json/json-bom-plus-crlf.stderr b/tests/ui/json/json-bom-plus-crlf.stderr index fee70431bdfbf..feaeaed15fac3 100644 --- a/tests/ui/json/json-bom-plus-crlf.stderr +++ b/tests/ui/json/json-bom-plus-crlf.stderr @@ -24,7 +24,8 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":672,"byte_end":673,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":663,"byte_end":669,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":673,"byte_end":673,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types: expected `String`, found integer +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":672,"byte_end":673,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":663,"byte_end":669,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":673,"byte_end":673,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -52,7 +53,8 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":732,"byte_end":733,"line_start":20,"line_end":20,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":723,"byte_end":729,"line_start":20,"line_end":20,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":733,"byte_end":733,"line_start":20,"line_end":20,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:20:22: error[E0308]: mismatched types: expected `String`, found integer +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":732,"byte_end":733,"line_start":20,"line_end":20,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":723,"byte_end":729,"line_start":20,"line_end":20,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":733,"byte_end":733,"line_start":20,"line_end":20,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:20:22: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -80,7 +82,8 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":796,"byte_end":797,"line_start":24,"line_end":24,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":792,"line_start":23,"line_end":23,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":797,"byte_end":797,"line_start":24,"line_end":24,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:24:1: error[E0308]: mismatched types: expected `String`, found integer +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":796,"byte_end":797,"line_start":24,"line_end":24,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":792,"line_start":23,"line_end":23,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":797,"byte_end":797,"line_start":24,"line_end":24,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:24:1: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -108,7 +111,8 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":852,"byte_end":860,"line_start":26,"line_end":27,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":843,"byte_end":849,"line_start":26,"line_end":26,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:26:22: error[E0308]: mismatched types: expected `String`, found `()` +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":852,"byte_end":860,"line_start":26,"line_end":27,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":843,"byte_end":849,"line_start":26,"line_end":26,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `String` +found unit type `()`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:26:22: error[E0308]: mismatched types: expected `String`, found `()` "} {"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors "} diff --git a/tests/ui/lazy-type-alias/trailing-where-clause.stderr b/tests/ui/lazy-type-alias/trailing-where-clause.stderr index 93cd3145928b7..126715eb6faf5 100644 --- a/tests/ui/lazy-type-alias/trailing-where-clause.stderr +++ b/tests/ui/lazy-type-alias/trailing-where-clause.stderr @@ -8,7 +8,6 @@ LL | let _: Alias<()>; `String` implements `From<&String>` `String` implements `From<&mut str>` `String` implements `From<&str>` - `String` implements `From>` `String` implements `From>` `String` implements `From` note: required by a bound in `Alias` diff --git a/tests/ui/minus-string.stderr b/tests/ui/minus-string.stderr index cf63ec2441670..987e2bb12eead 100644 --- a/tests/ui/minus-string.stderr +++ b/tests/ui/minus-string.stderr @@ -5,7 +5,7 @@ LL | fn main() { -"foo".to_string(); } | ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-` | note: the foreign item type `String` doesn't implement `Neg` - --> $SRC_DIR/alloc/src/string.rs:LL:COL + --> $SRC_DIR/alloc/src/string/string.rs:LL:COL | = note: not implement `Neg` diff --git a/tests/ui/mismatched_types/abridged.stderr b/tests/ui/mismatched_types/abridged.stderr index 6d2fb1ce9cf62..cc0d7fbf6db32 100644 --- a/tests/ui/mismatched_types/abridged.stderr +++ b/tests/ui/mismatched_types/abridged.stderr @@ -82,6 +82,8 @@ LL | fn f() -> String { LL | 1+2 | ^^^ expected `String`, found integer | + = note: expected struct `String` + found type `{integer}` help: try using a conversion method | LL | (1+2).to_string() @@ -95,6 +97,8 @@ LL | fn g() -> String { LL | -2 | ^^ expected `String`, found integer | + = note: expected struct `String` + found type `{integer}` help: try using a conversion method | LL | (-2).to_string() diff --git a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr index 225d7503a02a4..07de2aa79b469 100644 --- a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr +++ b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr @@ -43,6 +43,8 @@ error[E0308]: mismatched types LL | let s = Demo { a }; | ^ expected `String`, found integer | + = note: expected struct `String` + found type `{integer}` help: try using a conversion method | LL | let s = Demo { a: a.to_string() }; diff --git a/tests/ui/pattern/issue-115599.rs b/tests/ui/pattern/issue-115599.rs index 47fe6b87da942..57deed065405e 100644 --- a/tests/ui/pattern/issue-115599.rs +++ b/tests/ui/pattern/issue-115599.rs @@ -3,5 +3,5 @@ const CONST_STRING: String = String::new(); fn main() { let empty_str = String::from(""); if let CONST_STRING = empty_str {} - //~^ ERROR constant of non-structural type `Vec` in a pattern + //~^ ERROR constant of non-structural type `String` in a pattern } diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr index 69d10728ccdd7..99823a4fb9caf 100644 --- a/tests/ui/pattern/issue-115599.stderr +++ b/tests/ui/pattern/issue-115599.stderr @@ -1,4 +1,4 @@ -error: constant of non-structural type `Vec` in a pattern +error: constant of non-structural type `String` in a pattern --> $DIR/issue-115599.rs:5:12 | LL | const CONST_STRING: String = String::new(); @@ -6,9 +6,9 @@ LL | const CONST_STRING: String = String::new(); ... LL | if let CONST_STRING = empty_str {} | ^^^^^^^^^^^^ constant of non-structural type - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + --> $SRC_DIR/alloc/src/string/string.rs:LL:COL | - = note: `Vec` must be annotated with `#[derive(PartialEq)]` to be usable in patterns + = note: `String` must be annotated with `#[derive(PartialEq)]` to be usable in patterns | = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details diff --git a/tests/ui/pattern/pat-type-err-formal-param.stderr b/tests/ui/pattern/pat-type-err-formal-param.stderr index c100aa6070f7e..c94079285761b 100644 --- a/tests/ui/pattern/pat-type-err-formal-param.stderr +++ b/tests/ui/pattern/pat-type-err-formal-param.stderr @@ -5,6 +5,9 @@ LL | fn foo(Tuple(_): String) {} | ^^^^^^^^ ------ expected due to this | | | expected `String`, found `Tuple` + | + = note: expected struct `String` + found struct `Tuple` error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/signature-proc-macro-attribute.stderr b/tests/ui/proc-macro/signature-proc-macro-attribute.stderr index ce832eaa5c7af..bd957410a0221 100644 --- a/tests/ui/proc-macro/signature-proc-macro-attribute.stderr +++ b/tests/ui/proc-macro/signature-proc-macro-attribute.stderr @@ -5,7 +5,7 @@ LL | pub fn bad_input(input: String) -> TokenStream { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | = note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(std::string::String) -> proc_macro::TokenStream` + found signature `fn(std::string::string::String) -> proc_macro::TokenStream` error: attribute proc macro has incorrect signature --> $DIR/signature-proc-macro-attribute.rs:16:1 @@ -14,7 +14,7 @@ LL | pub fn bad_output(input: TokenStream) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | = note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(proc_macro::TokenStream) -> std::string::String` + found signature `fn(proc_macro::TokenStream) -> std::string::string::String` error: attribute proc macro has incorrect signature --> $DIR/signature-proc-macro-attribute.rs:22:1 @@ -23,7 +23,7 @@ LL | pub fn bad_everything(input: String) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | = note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(std::string::String) -> std::string::String` + found signature `fn(std::string::string::String) -> std::string::string::String` error: attribute proc macro has incorrect signature --> $DIR/signature-proc-macro-attribute.rs:28:52 @@ -32,7 +32,7 @@ LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream { | ^^^^^^ incorrect number of function parameters | = note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream` + found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::string::String) -> proc_macro::TokenStream` error: aborting due to 4 previous errors diff --git a/tests/ui/proc-macro/signature-proc-macro-derive.stderr b/tests/ui/proc-macro/signature-proc-macro-derive.stderr index 03c6abad17d91..c8bc1290ceb99 100644 --- a/tests/ui/proc-macro/signature-proc-macro-derive.stderr +++ b/tests/ui/proc-macro/signature-proc-macro-derive.stderr @@ -2,28 +2,28 @@ error: derive proc macro has incorrect signature --> $DIR/signature-proc-macro-derive.rs:10:25 | LL | pub fn bad_input(input: String) -> TokenStream { - | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String` + | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::string::String` | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(std::string::String) -> proc_macro::TokenStream` + found signature `fn(std::string::string::String) -> proc_macro::TokenStream` error: derive proc macro has incorrect signature --> $DIR/signature-proc-macro-derive.rs:16:42 | LL | pub fn bad_output(input: TokenStream) -> String { - | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String` + | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::string::String` | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(proc_macro::TokenStream) -> std::string::String` + found signature `fn(proc_macro::TokenStream) -> std::string::string::String` error: derive proc macro has incorrect signature --> $DIR/signature-proc-macro-derive.rs:22:30 | LL | pub fn bad_everything(input: String) -> String { - | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String` + | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::string::String` | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(std::string::String) -> std::string::String` + found signature `fn(std::string::string::String) -> std::string::string::String` error: derive proc macro has incorrect signature --> $DIR/signature-proc-macro-derive.rs:28:36 @@ -32,7 +32,7 @@ LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream { | ^^^^^^^^^^^ incorrect number of function parameters | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream` + found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::string::String) -> proc_macro::TokenStream` error: aborting due to 4 previous errors diff --git a/tests/ui/proc-macro/signature-proc-macro.stderr b/tests/ui/proc-macro/signature-proc-macro.stderr index dd2cb0570daa2..9d9fc50e195bf 100644 --- a/tests/ui/proc-macro/signature-proc-macro.stderr +++ b/tests/ui/proc-macro/signature-proc-macro.stderr @@ -2,28 +2,28 @@ error: function-like proc macro has incorrect signature --> $DIR/signature-proc-macro.rs:10:25 | LL | pub fn bad_input(input: String) -> TokenStream { - | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String` + | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::string::String` | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(std::string::String) -> proc_macro::TokenStream` + found signature `fn(std::string::string::String) -> proc_macro::TokenStream` error: function-like proc macro has incorrect signature --> $DIR/signature-proc-macro.rs:16:42 | LL | pub fn bad_output(input: TokenStream) -> String { - | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String` + | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::string::String` | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(proc_macro::TokenStream) -> std::string::String` + found signature `fn(proc_macro::TokenStream) -> std::string::string::String` error: function-like proc macro has incorrect signature --> $DIR/signature-proc-macro.rs:22:30 | LL | pub fn bad_everything(input: String) -> String { - | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String` + | ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::string::String` | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(std::string::String) -> std::string::String` + found signature `fn(std::string::string::String) -> std::string::string::String` error: function-like proc macro has incorrect signature --> $DIR/signature-proc-macro.rs:28:36 @@ -32,7 +32,7 @@ LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream { | ^^^^^^^^^^^ incorrect number of function parameters | = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` - found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream` + found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::string::String) -> proc_macro::TokenStream` error: aborting due to 4 previous errors diff --git a/tests/ui/query-system/query_depth.stderr b/tests/ui/query-system/query_depth.stderr index f738b01ed6ca7..8b2673638bc8b 100644 --- a/tests/ui/query-system/query_depth.stderr +++ b/tests/ui/query-system/query_depth.stderr @@ -5,7 +5,7 @@ LL | fn main() { | ^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "128"]` attribute to your crate (`query_depth`) - = note: query depth increased by 65 when computing layout of `core::option::Option>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: query depth increased by 65 when computing layout of `core::option::Option>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` error: aborting due to 1 previous error diff --git a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr index 95eddbde9e672..2f66e17ff6854 100644 --- a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr +++ b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr @@ -39,6 +39,9 @@ LL | let e = [String::new(), 10]; | ^^- help: try using a conversion method: `.to_string()` | | | expected `String`, found integer + | + = note: expected struct `String` + found type `{integer}` error[E0308]: mismatched types --> $DIR/typo-in-repeat-expr-issue-80173.rs:36:19 @@ -63,6 +66,8 @@ error[E0308]: mismatched types LL | let g = vec![String::new(), 10]; | ^^ expected `String`, found integer | + = note: expected struct `String` + found type `{integer}` help: replace the comma with a semicolon to create a vector | LL | let g = vec![String::new(); 10]; diff --git a/tests/ui/resolve/issue-22692.rs b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs similarity index 72% rename from tests/ui/resolve/issue-22692.rs rename to tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs index 31a76261408ef..7436b301ca24d 100644 --- a/tests/ui/resolve/issue-22692.rs +++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs @@ -1,15 +1,35 @@ +// see also https://github.com/rust-lang/rust/issues/22692 + +type Alias = Vec; + +mod foo { + fn bar() {} +} + fn main() { let _ = String.new(); - //~^ ERROR expected value, found struct `String` + //~^ ERROR expected value, found type alias `String` //~| HELP use the path separator let _ = String.default; - //~^ ERROR expected value, found struct `String` + //~^ ERROR expected value, found type alias `String` //~| HELP use the path separator let _ = Vec::<()>.with_capacity(1); //~^ ERROR expected value, found struct `Vec` //~| HELP use the path separator + + let _ = Alias.new(); + //~^ ERROR expected value, found type alias `Alias` + //~| HELP use the path separator + + let _ = Alias.default; + //~^ ERROR expected value, found type alias `Alias` + //~| HELP use the path separator + + let _ = foo.bar; + //~^ ERROR expected value, found module `foo` + //~| HELP use the path separator } macro_rules! Type { diff --git a/tests/ui/resolve/issue-22692.stderr b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr similarity index 65% rename from tests/ui/resolve/issue-22692.stderr rename to tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr index be0634ebffc96..4e165af29c7d3 100644 --- a/tests/ui/resolve/issue-22692.stderr +++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr @@ -1,5 +1,5 @@ -error[E0423]: expected value, found struct `String` - --> $DIR/issue-22692.rs:2:13 +error[E0423]: expected value, found type alias `String` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:10:13 | LL | let _ = String.new(); | ^^^^^^ @@ -9,8 +9,8 @@ help: use the path separator to refer to an item LL | let _ = String::new(); | ~~ -error[E0423]: expected value, found struct `String` - --> $DIR/issue-22692.rs:6:13 +error[E0423]: expected value, found type alias `String` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:14:13 | LL | let _ = String.default; | ^^^^^^ @@ -21,7 +21,7 @@ LL | let _ = String::default; | ~~ error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-22692.rs:10:13 + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:18:13 | LL | let _ = Vec::<()>.with_capacity(1); | ^^^^^^^^^ @@ -31,8 +31,41 @@ help: use the path separator to refer to an item LL | let _ = Vec::<()>::with_capacity(1); | ~~ +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:22:13 + | +LL | let _ = Alias.new(); + | ^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = Alias::new(); + | ~~ + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:26:13 + | +LL | let _ = Alias.default; + | ^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = Alias::default; + | ~~ + +error[E0423]: expected value, found module `foo` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:30:13 + | +LL | let _ = foo.bar; + | ^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = foo::bar; + | ~~ + error[E0423]: expected value, found struct `std::cell::Cell` - --> $DIR/issue-22692.rs:17:9 + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9 | LL | ::std::cell::Cell | ^^^^^^^^^^^^^^^^^ @@ -47,7 +80,7 @@ LL | ::get(); | ~~~~~~~~~~~ error[E0423]: expected value, found struct `std::cell::Cell` - --> $DIR/issue-22692.rs:17:9 + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9 | LL | ::std::cell::Cell | ^^^^^^^^^^^^^^^^^ @@ -62,7 +95,7 @@ LL | ::get; | ~~~~~~~~~~~~ error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-22692.rs:26:9 + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:46:9 | LL | Vec.new() | ^^^ @@ -77,7 +110,7 @@ LL | Vec::new() | ~~ error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-22692.rs:31:9 + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:51:9 | LL | Vec.new | ^^^ @@ -92,7 +125,7 @@ LL | Vec::new | ~~ error[E0423]: expected value, found struct `std::cell::Cell` - --> $DIR/issue-22692.rs:17:9 + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9 | LL | ::std::cell::Cell | ^^^^^^^^^^^^^^^^^ @@ -106,6 +139,6 @@ help: use the path separator to refer to an item LL | ::new(0) | ~~~~~~~~~~~ -error: aborting due to 8 previous errors +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/unresolved-segments-visibility.rs b/tests/ui/resolve/unresolved-segments-visibility.rs index c26171f75d2ca..d2c2b0d011b7c 100644 --- a/tests/ui/resolve/unresolved-segments-visibility.rs +++ b/tests/ui/resolve/unresolved-segments-visibility.rs @@ -6,6 +6,6 @@ extern crate alloc as b; mod foo { mod bar { pub(in b::string::String::newy) extern crate alloc as e; - //~^ ERROR failed to resolve: `String` is a struct, not a module [E0433] + //~^ ERROR failed to resolve: `String` is a type alias, not a module [E0433] } } diff --git a/tests/ui/resolve/unresolved-segments-visibility.stderr b/tests/ui/resolve/unresolved-segments-visibility.stderr index 09f3c50258d93..800d3adfb6960 100644 --- a/tests/ui/resolve/unresolved-segments-visibility.stderr +++ b/tests/ui/resolve/unresolved-segments-visibility.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: `String` is a struct, not a module +error[E0433]: failed to resolve: `String` is a type alias, not a module --> $DIR/unresolved-segments-visibility.rs:8:27 | LL | pub(in b::string::String::newy) extern crate alloc as e; - | ^^^^^^ `String` is a struct, not a module + | ^^^^^^ `String` is a type alias, not a module error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr index ee1a336ea98f6..007d1e1b6d890 100644 --- a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr +++ b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr @@ -4,7 +4,7 @@ error[E0422]: cannot find struct, variant or union type `Drain` in this scope LL | let _d = Drain {}; | ^^^^^ not found in this scope | -help: consider importing one of these structs +help: consider importing one of these items | LL + use crate::plumbing::Drain; | @@ -14,7 +14,7 @@ LL + use std::collections::hash_map::Drain; | LL + use std::collections::hash_set::Drain; | - and 3 other candidates + and 4 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/span/coerce-suggestions.stderr b/tests/ui/span/coerce-suggestions.stderr index 77b01ee08b791..23746a9c733a5 100644 --- a/tests/ui/span/coerce-suggestions.stderr +++ b/tests/ui/span/coerce-suggestions.stderr @@ -5,6 +5,9 @@ LL | let x: usize = String::new(); | ----- ^^^^^^^^^^^^^ expected `usize`, found `String` | | | expected due to this + | + = note: expected type `usize` + found struct `String` error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:9:19 @@ -14,6 +17,8 @@ LL | let x: &str = String::new(); | | | expected due to this | + = note: expected reference `&str` + found struct `String` help: consider borrowing here | LL | let x: &str = &String::new(); @@ -57,6 +62,8 @@ error[E0308]: mismatched types LL | s = format!("foo"); | ^^^^^^^^^^^^^^ expected `&mut String`, found `String` | + = note: expected mutable reference `&mut String` + found struct `String` = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 5 previous errors diff --git a/tests/ui/span/issue-33884.stderr b/tests/ui/span/issue-33884.stderr index 29490d86fffe7..ca86db813703d 100644 --- a/tests/ui/span/issue-33884.stderr +++ b/tests/ui/span/issue-33884.stderr @@ -4,6 +4,8 @@ error[E0308]: mismatched types LL | stream.write_fmt(format!("message received")) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Arguments<'_>`, found `String` | + = note: expected struct `Arguments<'_>` + found struct `String` = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/span/issue-39018.stderr b/tests/ui/span/issue-39018.stderr index c8c4a5139880d..aa7bc19ceada4 100644 --- a/tests/ui/span/issue-39018.stderr +++ b/tests/ui/span/issue-39018.stderr @@ -80,6 +80,8 @@ error[E0308]: mismatched types LL | let _ = a + b; | ^ expected `&str`, found `String` | + = note: expected reference `&str` + found struct `String` help: consider borrowing here | LL | let _ = a + &b; diff --git a/tests/ui/specialization/default-associated-type-bound-1.stderr b/tests/ui/specialization/default-associated-type-bound-1.stderr index 516df555a0d5f..38e3b29b0c851 100644 --- a/tests/ui/specialization/default-associated-type-bound-1.stderr +++ b/tests/ui/specialization/default-associated-type-bound-1.stderr @@ -14,7 +14,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | default type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X::U` --> $DIR/default-associated-type-bound-1.rs:8:13 | diff --git a/tests/ui/static/bad-const-type.stderr b/tests/ui/static/bad-const-type.stderr index 807cd2f7a25a7..46394f74e7298 100644 --- a/tests/ui/static/bad-const-type.stderr +++ b/tests/ui/static/bad-const-type.stderr @@ -5,6 +5,9 @@ LL | static i: String = 10; | ^^- help: try using a conversion method: `.to_string()` | | | expected `String`, found integer + | + = note: expected struct `String` + found type `{integer}` error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr index 2dd6fb6a3bf6d..291f4ebda9f93 100644 --- a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr +++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr @@ -37,6 +37,8 @@ LL | fn foo(mut s: String) -> String { LL | s.push_str("asdf") | ^^^^^^^^^^^^^^^^^^ expected `String`, found `()` | + = note: expected struct `String` + found unit type `()` note: method `push_str` modifies its receiver in-place --> $DIR/chain-method-call-mutation-in-place.rs:7:7 | diff --git a/tests/ui/suggestions/const-in-struct-pat.stderr b/tests/ui/suggestions/const-in-struct-pat.stderr index d4056e09cc364..1f7f09670f893 100644 --- a/tests/ui/suggestions/const-in-struct-pat.stderr +++ b/tests/ui/suggestions/const-in-struct-pat.stderr @@ -10,6 +10,8 @@ LL | let Thing { foo } = t; | expected `String`, found `foo` | `foo` is interpreted as a unit struct, not a new binding | + = note: expected struct `String` + found struct `foo` help: bind the struct field to a different name instead | LL | let Thing { foo: other_foo } = t; diff --git a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr index 46613e8e1b487..df425ae090614 100644 --- a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr +++ b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr @@ -6,6 +6,8 @@ LL | | "abc" LL | | }; | |_____^ expected `&str`, found `String` | + = note: expected reference `&str` + found struct `String` = note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/format-borrow.stderr b/tests/ui/suggestions/format-borrow.stderr index 3ea0d208cbb7f..de9eca087043e 100644 --- a/tests/ui/suggestions/format-borrow.stderr +++ b/tests/ui/suggestions/format-borrow.stderr @@ -6,6 +6,8 @@ LL | let a: String = &String::from("a"); | | | expected due to this | + = note: expected struct `String` + found reference `&String` help: consider removing the borrow | LL - let a: String = &String::from("a"); @@ -24,6 +26,8 @@ LL | let b: String = &format!("b"); | | | expected due to this | + = note: expected struct `String` + found reference `&String` help: consider removing the borrow | LL - let b: String = &format!("b"); @@ -42,6 +46,8 @@ LL | let c: String = &mut format!("c"); | | | expected due to this | + = note: expected struct `String` + found mutable reference `&mut String` help: consider removing the borrow | LL - let c: String = &mut format!("c"); @@ -60,6 +66,8 @@ LL | let d: String = &mut (format!("d")); | | | expected due to this | + = note: expected struct `String` + found mutable reference `&mut String` help: consider removing the borrow | LL - let d: String = &mut (format!("d")); diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr index d02d318608297..e5f5bf68eafac 100644 --- a/tests/ui/suggestions/into-str.stderr +++ b/tests/ui/suggestions/into-str.stderr @@ -11,9 +11,9 @@ LL | foo(String::new()); `String` implements `From<&String>` `String` implements `From<&mut str>` `String` implements `From<&str>` - `String` implements `From>` `String` implements `From>` `String` implements `From` + `String` implements `From>` = note: required for `String` to implement `Into<&str>` note: required by a bound in `foo` --> $DIR/into-str.rs:1:31 diff --git a/tests/ui/suggestions/issue-105494.stderr b/tests/ui/suggestions/issue-105494.stderr index 4cb4a399a7245..c6281cbd84732 100644 --- a/tests/ui/suggestions/issue-105494.stderr +++ b/tests/ui/suggestions/issue-105494.stderr @@ -6,6 +6,8 @@ LL | let _v: i32 = (1 as i32).to_string(); | | | expected due to this | + = note: expected type `i32` + found struct `String` help: try removing the method call | LL - let _v: i32 = (1 as i32).to_string(); @@ -19,6 +21,9 @@ LL | let _v: i32 = (1 as i128).to_string(); | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String` | | | expected due to this + | + = note: expected type `i32` + found struct `String` error[E0308]: mismatched types --> $DIR/issue-105494.rs:7:20 @@ -28,6 +33,8 @@ LL | let _v: &str = "foo".to_string(); | | | expected due to this | + = note: expected reference `&str` + found struct `String` help: try removing the method call | LL - let _v: &str = "foo".to_string(); @@ -43,6 +50,8 @@ LL | let mut path: String = "/usr".to_string(); LL | path = format!("{}/{}", path, folder).as_str(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `&str` | + = note: expected struct `String` + found reference `&str` help: try removing the method call | LL - path = format!("{}/{}", path, folder).as_str(); diff --git a/tests/ui/suggestions/issue-109854.stderr b/tests/ui/suggestions/issue-109854.stderr index d9cbbe37d4612..dce56c3e2e79c 100644 --- a/tests/ui/suggestions/issue-109854.stderr +++ b/tests/ui/suggestions/issue-109854.stderr @@ -19,7 +19,7 @@ LL | generate_setter, = note: expected type `usize` found fn item `fn() {generate_setter}` note: associated function defined here - --> $SRC_DIR/alloc/src/string.rs:LL:COL + --> $SRC_DIR/alloc/src/string/string.rs:LL:COL help: remove the extra arguments | LL - generate_setter, diff --git a/tests/ui/suggestions/issue-109991.stderr b/tests/ui/suggestions/issue-109991.stderr index bd21e4de648cb..69650267a49f4 100644 --- a/tests/ui/suggestions/issue-109991.stderr +++ b/tests/ui/suggestions/issue-109991.stderr @@ -29,6 +29,9 @@ LL | let x: String; | ------ expected due to this type LL | (x,) = (1,); | ^ expected `String`, found integer + | + = note: expected struct `String` + found type `{integer}` error[E0308]: mismatched types --> $DIR/issue-109991.rs:18:6 diff --git a/tests/ui/suggestions/issue-52820.stderr b/tests/ui/suggestions/issue-52820.stderr index a67d75014171f..ebe6e086103df 100644 --- a/tests/ui/suggestions/issue-52820.stderr +++ b/tests/ui/suggestions/issue-52820.stderr @@ -4,6 +4,8 @@ error[E0308]: mismatched types LL | guts, | ^^^^ expected `String`, found `&str` | + = note: expected struct `String` + found reference `&str` help: try using a conversion method | LL | guts: guts.to_string(), @@ -17,6 +19,9 @@ LL | brains: guts.clone(), | | | | | help: try using a conversion method: `to_string` | expected `String`, found `&str` + | + = note: expected struct `String` + found reference `&str` error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-53692.stderr b/tests/ui/suggestions/issue-53692.stderr index 469a538411fb1..4dcca1bb83b21 100644 --- a/tests/ui/suggestions/issue-53692.stderr +++ b/tests/ui/suggestions/issue-53692.stderr @@ -20,6 +20,9 @@ LL | let string: String = s.clone(); | | | help: try using a conversion method: `to_string` | | expected `String`, found `&str` | expected due to this + | + = note: expected struct `String` + found reference `&str` error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-59819.stderr b/tests/ui/suggestions/issue-59819.stderr index 43acf9549c29a..c9a9fe12f995e 100644 --- a/tests/ui/suggestions/issue-59819.stderr +++ b/tests/ui/suggestions/issue-59819.stderr @@ -32,6 +32,9 @@ LL | let g: String = f; | | | | | expected `String`, found `Bar` | expected due to this + | + = note: expected struct `String` + found struct `Bar` error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/issue-83943.stderr b/tests/ui/suggestions/issue-83943.stderr index 1a085368485cf..853af5a27c8a4 100644 --- a/tests/ui/suggestions/issue-83943.stderr +++ b/tests/ui/suggestions/issue-83943.stderr @@ -11,6 +11,9 @@ LL | | "B" | | expected `String`, found `&str` LL | | }; | |_____- `if` and `else` have incompatible types + | + = note: expected struct `String` + found reference `&str` error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr index c721ceb11463f..b798b4a70aa0d 100644 --- a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr +++ b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr @@ -8,6 +8,9 @@ LL | your_name.trim() | ^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()` | | | expected `String`, found `&str` + | + = note: expected struct `String` + found reference `&str` error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/return-bindings.stderr b/tests/ui/suggestions/return-bindings.stderr index 6f906c27ba943..75dd54498bfe4 100644 --- a/tests/ui/suggestions/return-bindings.stderr +++ b/tests/ui/suggestions/return-bindings.stderr @@ -20,6 +20,8 @@ LL | | LL | | } else { | |_____^ expected `String`, found `()` | + = note: expected struct `String` + found unit type `()` help: consider returning the local binding `s` | LL ~ let s: String = if let Some(s) = opt_str { @@ -52,6 +54,8 @@ LL | | LL | | } else { | |_____^ expected `String`, found `()` | + = note: expected struct `String` + found unit type `()` help: consider returning the local binding `s` | LL ~ let s: String = if let Some(s) = opt_str { @@ -69,6 +73,8 @@ LL | | } else { LL | String::new() | ^^^^^^^^^^^^^ expected `()`, found `String` | + = note: expected unit type `()` + found struct `String` help: consider returning the local binding `s` | LL ~ let s = if let Some(s) = opt_str { @@ -82,6 +88,8 @@ error[E0308]: mismatched types LL | Some(s) => {} | ^^ expected `String`, found `()` | + = note: expected struct `String` + found unit type `()` help: consider returning the local binding `s` | LL | Some(s) => { s } @@ -100,6 +108,8 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | + = note: expected unit type `()` + found struct `String` help: consider returning the local binding `s` | LL | Some(s) => { s } diff --git a/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr index 4b83bfff86333..b3d9876c50d34 100644 --- a/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr +++ b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr @@ -10,6 +10,9 @@ LL | | }; | |_____- this block is missing a tail expression LL | list | ^^^^ expected `String`, found `()` + | + = note: expected struct `String` + found unit type `()` error[E0277]: a value of type `String` cannot be built from an iterator over elements of type `()` --> $DIR/semi-suggestion-when-stmt-and-expr-span-equal.rs:23:20 diff --git a/tests/ui/suggestions/suggest-remove-deref.stderr b/tests/ui/suggestions/suggest-remove-deref.stderr index 4253838eb5265..e0efcce15a9f5 100644 --- a/tests/ui/suggestions/suggest-remove-deref.stderr +++ b/tests/ui/suggestions/suggest-remove-deref.stderr @@ -27,6 +27,8 @@ LL | bar(*s); | | | arguments to this function are incorrect | + = note: expected reference `&String` + found struct `String` note: function defined here --> $DIR/suggest-remove-deref.rs:17:4 | diff --git a/tests/ui/switched-expectations.stderr b/tests/ui/switched-expectations.stderr index cc57674740020..17b6df7d5d0c6 100644 --- a/tests/ui/switched-expectations.stderr +++ b/tests/ui/switched-expectations.stderr @@ -5,6 +5,9 @@ LL | let ref string: String = var; | ^^^- help: try using a conversion method: `.to_string()` | | | expected `String`, found `i32` + | + = note: expected struct `String` + found type `i32` error: aborting due to 1 previous error diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs index 8e43b7249f7c0..ca206bdcb98e0 100644 --- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs @@ -2,6 +2,8 @@ trait Bar { type Baz; } +struct String; + struct Foo where T: Bar, ::Baz: String { //~ ERROR expected trait, found struct t: T, } diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr index 0020f9e416df2..6c4d535f97cd3 100644 --- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr @@ -1,5 +1,5 @@ error[E0404]: expected trait, found struct `String` - --> $DIR/assoc_type_bound_with_struct.rs:5:46 + --> $DIR/assoc_type_bound_with_struct.rs:7:46 | LL | struct Foo where T: Bar, ::Baz: String { | ^^^^^^ not a trait @@ -17,7 +17,7 @@ LL | struct Foo where T: Bar, ::Baz: ToString { | ~~~~~~~~ error[E0404]: expected trait, found struct `String` - --> $DIR/assoc_type_bound_with_struct.rs:9:54 + --> $DIR/assoc_type_bound_with_struct.rs:11:54 | LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { | ^^^^^^ not a trait @@ -35,7 +35,7 @@ LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: ToString { | ~~~~~~~~ error[E0404]: expected trait, found struct `String` - --> $DIR/assoc_type_bound_with_struct.rs:13:45 + --> $DIR/assoc_type_bound_with_struct.rs:15:45 | LL | fn foo(_: T) where ::Baz: String { | ^^^^^^ not a trait @@ -53,7 +53,7 @@ LL | fn foo(_: T) where ::Baz: ToString { | ~~~~~~~~ error[E0404]: expected trait, found struct `String` - --> $DIR/assoc_type_bound_with_struct.rs:16:57 + --> $DIR/assoc_type_bound_with_struct.rs:18:57 | LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { | ^^^^^^ not a trait @@ -71,13 +71,13 @@ LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString { | ~~~~~~~~ error[E0405]: cannot find trait `Unresolved` in this scope - --> $DIR/assoc_type_bound_with_struct.rs:19:31 + --> $DIR/assoc_type_bound_with_struct.rs:21:31 | LL | fn issue_95327() where ::Assoc: String {} | ^^^^^^^^^^ not found in this scope error[E0404]: expected trait, found struct `String` - --> $DIR/assoc_type_bound_with_struct.rs:19:51 + --> $DIR/assoc_type_bound_with_struct.rs:21:51 | LL | fn issue_95327() where ::Assoc: String {} | ^^^^^^ help: a trait with a similar name exists: `ToString` diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr index e7e55d0beeeb4..479a55c176a61 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | f::>(); | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `f` --> $DIR/check-trait-object-bounds-1.rs:7:9 | diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr index 5cc38e4371d1c..b75f2671586c4 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | f::>(); | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the trait `Clone` is implemented for `String` + = help: the trait `Clone` is implemented for `String` note: required by a bound in `f` --> $DIR/check-trait-object-bounds-4.rs:10:9 | diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr index 1cd62d2cbdbaa..239ed45a1b628 100644 --- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -7,7 +7,7 @@ LL | s.strip_suffix(b'\n').unwrap_or(s) | required by a bound introduced by this call | = help: the following other types implement trait `Pattern`: - &'b String + &'b String &'b [char; N] &'b [char] &'b str diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr index 2b26a1b7ab15a..e20a36d833ada 100644 --- a/tests/ui/traits/issue-77982.stderr +++ b/tests/ui/traits/issue-77982.stderr @@ -7,7 +7,8 @@ LL | opts.get(opt.as_ref()); | cannot infer type of the type parameter `Q` declared on the method `get` | = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: - - impl Borrow for String; + - impl Borrow for String + where A: Allocator; - impl Borrow for T where T: ?Sized; note: required by a bound in `HashMap::::get` @@ -26,10 +27,14 @@ LL | opts.get(opt.as_ref()); | cannot infer type of the type parameter `Q` declared on the method `get` | = note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`: - - impl AsRef for String; - - impl AsRef for String; - - impl AsRef<[u8]> for String; - - impl AsRef for String; + - impl AsRef for String + where A: Allocator; + - impl AsRef for String + where A: Allocator; + - impl AsRef<[u8]> for String + where A: Allocator; + - impl AsRef for String + where A: Allocator; help: consider specifying the generic argument | LL | opts.get::(opt.as_ref()); diff --git a/tests/ui/traits/negative-impls/ambiguity-cause.negative_coherence.stderr b/tests/ui/traits/negative-impls/ambiguity-cause.negative_coherence.stderr index 4ec3414a57bcc..f33cf5db96fd2 100644 --- a/tests/ui/traits/negative-impls/ambiguity-cause.negative_coherence.stderr +++ b/tests/ui/traits/negative-impls/ambiguity-cause.negative_coherence.stderr @@ -7,7 +7,7 @@ LL | LL | impl MyTrait for String { } | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `String` | - = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::string::String` in future versions + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::string::string::String` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/traits/negative-impls/ambiguity-cause.simple.stderr b/tests/ui/traits/negative-impls/ambiguity-cause.simple.stderr index 4ec3414a57bcc..f33cf5db96fd2 100644 --- a/tests/ui/traits/negative-impls/ambiguity-cause.simple.stderr +++ b/tests/ui/traits/negative-impls/ambiguity-cause.simple.stderr @@ -7,7 +7,7 @@ LL | LL | impl MyTrait for String { } | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `String` | - = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::string::String` in future versions + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::string::string::String` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr index bad325a672042..d82daef5b88d2 100644 --- a/tests/ui/traits/question-mark-result-err-mismatch.stderr +++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr @@ -34,7 +34,6 @@ LL | .map_err(|_| ())?; `String` implements `From<&String>` `String` implements `From<&mut str>` `String` implements `From<&str>` - `String` implements `From>` `String` implements `From>` `String` implements `From` = note: required for `Result<(), String>` to implement `FromResidual>` diff --git a/tests/ui/typeck/conversion-methods.stderr b/tests/ui/typeck/conversion-methods.stderr index a9b5078ccdde3..f6c7f228962e0 100644 --- a/tests/ui/typeck/conversion-methods.stderr +++ b/tests/ui/typeck/conversion-methods.stderr @@ -6,6 +6,9 @@ LL | let _tis_an_instants_play: String = "'Tis a fond Ambush—"; | | | | | expected `String`, found `&str` | expected due to this + | + = note: expected struct `String` + found reference `&'static str` error[E0308]: mismatched types --> $DIR/conversion-methods.rs:6:40 @@ -24,6 +27,9 @@ LL | let _but_should_the_play: String = 2; // Perhaps surprisingly, we sugge | | | | | expected `String`, found integer | expected due to this + | + = note: expected struct `String` + found type `{integer}` error[E0308]: mismatched types --> $DIR/conversion-methods.rs:12:47 diff --git a/tests/ui/typeck/issue-67971.stderr b/tests/ui/typeck/issue-67971.stderr index d50ed9cf13bb4..4792338ed08cc 100644 --- a/tests/ui/typeck/issue-67971.stderr +++ b/tests/ui/typeck/issue-67971.stderr @@ -11,6 +11,9 @@ LL | fn foo(ctx: &mut S) -> String { | --- ^^^^^^ expected `String`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `String` + found unit type `()` error: aborting due to 2 previous errors