Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add support for custom allocator for String #101551

Draft
wants to merge 24 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8faf58c
Initial work to make `String` usable with `feature(allocator_api)`.
zachs18 Jul 26, 2024
39f4355
Move String<A> to a submodule, and make alloc::string::String a type …
zachs18 Feb 3, 2025
5e85ae9
Fix doc links.
zachs18 Jul 26, 2024
9e79eb1
Remove duplicate ParseError definition.
zachs18 Jan 19, 2024
efde431
Fix debuginfo tests(?).
zachs18 Jul 26, 2024
20442e0
Fix doctests.
zachs18 Jan 19, 2024
b7ce9fd
Under cfg(test), restrict impl<A: Allocator> From<String<A>> for Box<…
zachs18 Jul 28, 2024
6823cb4
Update stdlib on_unimplemented attributes and doctests using String t…
zachs18 Jul 28, 2024
70dd8a3
Fix doclinks
zachs18 Jul 28, 2024
60baaa1
Fix stuff from rebase
zachs18 Jan 22, 2025
e1a335a
fmt
zachs18 Jan 22, 2025
4508a61
Update debuginfo tests
zachs18 Jan 22, 2025
ad85d70
Update rustc_on_unimplementeds
zachs18 Jan 22, 2025
cdb67f3
Update UI tests. Audit these before marking ready and/or merging.
zachs18 Jan 22, 2025
bb97e15
Suggest using :: instead of . in more cases.
zachs18 Jan 30, 2025
9788ed5
Update mir-opt tests
zachs18 Jan 31, 2025
b59f581
Update rustdoc tests
zachs18 Feb 1, 2025
95708da
Update String's new path in clippy tests
zachs18 Feb 1, 2025
5810dde
Update cliipy arithmetic_side_effects lint for new String path
zachs18 Feb 1, 2025
af2716b
Update useless_conversion and box_collection clippy lints to use Stri…
zachs18 Feb 1, 2025
098ebac
Update redundant_type_annotations doc and tests to remove String
zachs18 Feb 1, 2025
fb69c03
Update rc_buffer clippy lint to use String type alias diagnostic item.
zachs18 Feb 1, 2025
845e0ea
Update explicit-html-path doc links to String in docs, books, etc
zachs18 Feb 1, 2025
bdceb2e
Exempt some html links to std::string::String methods from linkchecker
zachs18 Feb 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -1735,7 +1735,7 @@ Stabilized APIs

- [`impl<T: Send> Sync for mpsc::Sender<T>`](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:

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
16 changes: 7 additions & 9 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
};

Expand Down Expand Up @@ -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 {
Expand Down
20 changes: 16 additions & 4 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1848,11 +1848,23 @@ impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl Clone for Box<str> {
impl<A: Allocator + Clone> Clone for Box<str, A> {
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();
}
}
}

Expand Down
18 changes: 10 additions & 8 deletions library/alloc/src/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<str>` is not meaningful here.
Expand Down Expand Up @@ -186,15 +187,15 @@ where
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<str> for String {
impl<A: Allocator> Borrow<str> for String<A> {
#[inline]
fn borrow(&self) -> &str {
&self[..]
}
}

#[stable(feature = "string_borrow_mut", since = "1.36.0")]
impl BorrowMut<str> for String {
impl<A: Allocator> BorrowMut<str> for String<A> {
#[inline]
fn borrow_mut(&mut self) -> &mut str {
&mut self[..]
Expand Down Expand Up @@ -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<str>) -> Box<[u8]> {
pub fn into_boxed_bytes<A: Allocator>(self: Box<str, A>) -> Box<[u8], A> {
self.into()
}

Expand Down Expand Up @@ -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<str>) -> String {
let slice = Box::<[u8]>::from(self);
pub fn into_string<A: Allocator>(self: Box<str, A>) -> String<A> {
let slice = Box::<[u8], A>::from(self);
unsafe { String::from_utf8_unchecked(slice.into_vec()) }
}

Expand Down Expand Up @@ -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<str> {
unsafe { Box::from_raw(Box::into_raw(v) as *mut str) }
pub unsafe fn from_boxed_utf8_unchecked<A: Allocator>(v: Box<[u8], A>) -> Box<str, A> {
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.
Expand Down
Loading
Loading