Description
Proposal
Add an unstable, defaulted generic parameter to alloc::string::String
to allow use with custom allocators under #![feature(allocator_api)]
, and generalize most implementations on String
to be generic over the allocator.
(There's a tracking issue rust-lang/wg-allocators#7 on wg-allocators, so I wasn't sure if this needed an ACP. I made one just to be safe.)
Problem statement
Currently, Vec
and Box
have a second, unstable, defaulted generic parameter A: Allocator = Global
, allowing them to support custom allocators. String
does not currently have this, so it does not yet support custom allocators.
Motivation, use-cases
Part of the effort to expand allocator_api
to support more collection types. It could be useful to allow using common container types with different allocators that are better suited to different allocation patterns.
Solution sketches
Add an #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global
generic to alloc::string::String
, alloc::string::FromUtf8Error
, and alloc::string::Drain
, and make most inherent functions and trait implementations generic over this parameter.
Also make some corresponding non-allocator-generic functions and implementations on Box<str>
allocator-generic.
- removed unstable trait implementations.
StructuralEq for String
:String
previously usedderive(Eq)
, but manually implementedPartialEq
. To prevent anA: Eq
bound, I removed thederive
and replaced it with a manualimpl Eq
without that bound. It should not be observable on stable, becauseString
does not implementStructuralPartialEq
, which is also required for structural matching.- Manual
impl<A: Allocator> StructuralEq for String<A> {}
, etc. can be added if necessary.
- Manual
StructuralEq
/StructralPartialEq for FromUtf8Error
:FromUtf8Error
previously usedderive(PartialEq, Eq)
. However, it is not possible to get a value of typeFromUtf8Error
in constant evaluation on stable, so there is no way to construct anything that could even be used as a structural match pattern, so I don't think these removals are observable.
- Added allocator-generic inherent
String
functions (that already exist forVec
)new_in
/with_capacity_in
from_raw_parts_in
/into_raw_parts_with_alloc
allocator
- Inherent functions which are not (currently) made allocator-generic
new
/with_capacity
/from_utf16
/from_utf16_lossy
: These could useA: (~const) Default
, but seemed out of scope. Also, correspondingVec
functions are not allocator-generic.from_utf8_lossy
: This returns aCow<str>
, which is not allocator-generic.from_raw_parts
/into_raw_parts
: These are tied to the global allocator.
- Added trait implementations that already are allocator-generic for
Vec
/[T]
-like.Clone for Box<str, A> where A: Clone
- Added trait implementations that are not yet allocator-generic for
Vec
/[T]
-likeBorrow/BorrowMut<str> for String<A>
edit: These have been removed from the linked PR to make room for futureFrom<String<A>> for Rc<str>
/Arc<str>
From<String<A>> for Rc<str, A>
-like impls.
- Trait implementations which are not (currently) made allocator-generic:
Default where A: Default
: this would require makingGlobal
implementconst Default
, which is probably fine, but seemed out-of-scope. Also, the correspondingVec
implementation is not allocator-generic.- Likewise for
impl const Default for Box<str>
(andBox<[T]>
).
- Likewise for
From<&String> for String
: Unclear if it should beFrom<&String<A>> for String<A> where A: Clone
orFrom<&String<A2>> for String<A1> where A1: Default
FromStr
,From<&str-like>
,From<char>
,FromIterator<_>
: Could befor String<A> where A: Default
but seemed out-of-scope. Also, correspondingVec
implementations are not allocator-generic.- Likewise for
From<&str> for Box<str>
andFrom<&[T]> for Box<T> where T: Clone
- Likewise for
- Other APIs which are not (currently) made allocator-generic
- APIs involving
CString
, e.g.CString::into_string
- APIs outside the
alloc
crate, e.g.std::io::Read::read_to_string
,AsRef<OsStr> for String
,ToSocketAddrs for String
- APIs involving
All unmentioned inherent functions and trait implementations on String
, FromUtf8Error
, and Drain
are made allocator-generic (with appropriate bounds, e.g. A: Allocator + Clone
for String::split_off
).
Several implementations involving Box<str>
are also made allocator-generic
From<Box<str, A>> for Box<[u8], A>
From<Box<str, A>> for String<A>
From<String<A>> for Box<str, A>
is not added currently because of trait coherence rules (help?).
Links and related work
- [WIP] Add support for custom allocator for
String
rust#101551 - Add support for custom allocator for
(C)String
rust#79500 (closed in favor of 101551 above) - Tracking Issue for structs which needs an allocator wg-allocators#7
- Add support for custom allocators in
Vec
rust#78461 - Future work to do similar for
CString
and other containers.
What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.