[WIP] Add support for custom allocator for String#101551
[WIP] Add support for custom allocator for String#101551zachs18 wants to merge 24 commits intorust-lang:mainfrom
String#101551Conversation
|
(rust-highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
6faca17 to
a2b102a
Compare
There was a problem hiding this comment.
This PR changed a lot of the UI tests/diagnostics to have duplicated-ish note messages. I don't know enough about the diagnostics system to really understand why. Are these changes acceptable?
(Several similar changes, e.g. expected struct String, found type str in src/test/ui/issues/issue-53348.stderr, expected struct String, found unit type () in src/test/ui/block-result/consider-removing-last-semi.stderr)
There was a problem hiding this comment.
I also don't know the cause here, but it feels like it might be a larger bug -- maybe worth trying to reproduce on stable/nightly outside of the String type (e.g., have a struct and add a generic parameter to it) and see if that causes similar behavior on regular rustc compilers? If so, then you could file an issue for that.
If this is something specific to String that's probably worth poking at too.
There was a problem hiding this comment.
It does not appear to be specific to String; I have opened #101992 about it.
This comment has been minimized.
This comment has been minimized.
a2b102a to
7ab2548
Compare
This comment has been minimized.
This comment has been minimized.
Things that are the same as 79500:The following were made allocator-aware (or added) in the same way as in 79500:
DIfferences from 79500 :
Additions from 79500:
|
|
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
|
It passes the checks now, so I'm marking this as ready for review. Feedback is appreciated! (especially on the unresolved questions in the Todos). (CC'ing people from 79500) |
|
(I think this is right?) |
library/alloc/src/string.rs
Outdated
There was a problem hiding this comment.
I sort of feel like we shouldn't provide these APIs and instead encourage String::from(Vec::with_capacity_in(....)), since they do add noise to documentation and most users aren't using them. But that can be handled at stabilization time, I suppose, and is a broader question about everything being allocator-generic.
library/alloc/src/string.rs
Outdated
There was a problem hiding this comment.
I don't think we should add this comment; there's many APIs which could do this (even on Vec) and it doesn't seem worth leaving comments strewn around std for that future possibility.
There was a problem hiding this comment.
Yeah, I had intended to remove or implement most of the FIXMEs based on feedback before the PR gets merged. I'll just remove the ones that don't currently exist for Vec for this PR.
|
A few notes:
I think this is not observable on stable, though I'm not entirely confident. The primary area where it matters that I know of is pattern matching with a const value, but that requires StructuralPartialEq too.
In order to check whether this is a breaking change we need to know whether any const context on stable can get the value -- I think the answer may be no, but I'm not confident. Also left some comments inline, going to @rustbot author for now but please mark it as ready for review if the ACP goes through and you have addressed comments (or posted back with questions). |
0445581 to
311f4a5
Compare
This comment has been minimized.
This comment has been minimized.
311f4a5 to
c75bd1f
Compare
…str, A> to A = Global.
…o the new path. Also reverts some UI test changes that were due to on_unimplemented path being wrong.
When `Foo.field` or `Foo.method()` exprs are encountered, suggest `Foo::field` or `Foo::method()` when Foo is a type alias, not just a struct, trait, or module. Also rename test for this suggestion from issue-22692.rs to something more meaningful.
…ng type alias diagnostic item.
|
The job Click to see the possible cause of the failure (guessed by this bot) |
|
☔ The latest upstream changes (presumably #136507) made this pull request unmergeable. Please resolve the merge conflicts. |
|
I won't have time to work on this in the near future, if someone wants to take over. It might make sense to split this into multiple PRs (e.g. one moving |
|
As someone who's been waiting for this for years (it would allow me to delete hundreds of lines of workaround code), I am really tempted to say I want to push this through. Realistically, I can imagine reserving a couple of weeks around the end of September. Will check back in then to see if someone else didn't already. |
|
I started on this in another branch, I'll try to get something PR'd within the next week. So I guess, I'd be happy to claim this for a week, but if there's no heartbeat update from me within that time, someone else can grab it. |
|
Closing this in favour of #149328 |
Add `String<A>` type with custom allocator parameter This change is part of the `allocator_api` feature set [rust-lang#32838](rust-lang#32838) (also see [wg-allocators roadmap] or [libs-team ACP]). The previous attempts at adding an allocator parameter to string are at [rust-lang#101551], and [rust-lang#79500] (I think those authors should get much of the credit here, I am re-writing what they worked out in those threads). ## workaround There is a type inference ambiguity introduced when adding a generic parameter to a type which previously had none, even when that parameter has a default value (more details in [rust-lang#98931]). I've done the same [workaround] as [rust-lang#101551], which is to make `alloc::string::String` a type alias to `String<Global>`, but I've arranged the modules a bit differently to make rebase/merges a bit easier. This workaround unfortunately changes the type name of the `String` language item, and that would be user-facing in error or diagnostic output. I understand from [this comment](rust-lang#101551 (comment)) that this change is acceptable. ## changes to existing API Most of the methods on the original `String` have been implemented for the generic version instead. I don't foresee anything more moving from `String<Global>` to `String<A>`, as the remaining methods are all constructors which implicitly use the `Global` allocator. There are three general types of changes: 1. methods which don't allocate: here we just change `impl Foo for String` to `impl<A: Allocator> Foo for String<A>` 2. converting to/from other allocator generic types like `Vec<u8, A>` and `Box<str, A>`: here we can use the existing allocator from those types. 3. methods which clone from some other type with an allocator: here it's ambiguous whether the end result should be `String<A>`, `String<Global>`, or `String<impl Allocator + Default>`, etc; in general I try to leave these out of this change, but where some analogous change was made to `Vec<T, A>` I follow that. ## new methods Some methods have been added to `String<A>` which are not strictly necessary to land this change, but are considered helpful enough to users, and close enough to existing precedent in `Vec<T, A>`. Specifically, 4 new constructors (`new_in`, `with_capacity_in`, `try_with_capacity_in`, `from_raw_parts_in`), 1 destructor (`into_raw_parts_with_alloc`), and 1 getter (`allocator`). Technically, the updated `from_utf8_unchecked` should be sufficient for constructing, but we can add some safe constructors so users don't have to sully themselves. ## not implemented Variants of `from_utf{8,16}*` which internally allocate or use `Cow` have been punted on this PR, maybe a followup would make sense to either rewrite them, or add some `*_in` variant. [wg-allocators roadmap]: rust-lang/wg-allocators#7 [libs-team ACP]: rust-lang/libs-team#101 [workaround]: rust-lang#79499 (comment) [rust-lang#101551]: rust-lang#101551 [rust-lang#79500]: rust-lang#79500 [rust-lang#98931]: rust-lang#98931
Add `String<A>` type with custom allocator parameter This change is part of the `allocator_api` feature set [rust-lang#32838](rust-lang#32838) (also see [wg-allocators roadmap] or [libs-team ACP]). The previous attempts at adding an allocator parameter to string are at [rust-lang#101551], and [rust-lang#79500] (I think those authors should get much of the credit here, I am re-writing what they worked out in those threads). ## workaround There is a type inference ambiguity introduced when adding a generic parameter to a type which previously had none, even when that parameter has a default value (more details in [rust-lang#98931]). I've done the same [workaround] as [rust-lang#101551], which is to make `alloc::string::String` a type alias to `String<Global>`, but I've arranged the modules a bit differently to make rebase/merges a bit easier. This workaround unfortunately changes the type name of the `String` language item, and that would be user-facing in error or diagnostic output. I understand from [this comment](rust-lang#101551 (comment)) that this change is acceptable. ## changes to existing API Most of the methods on the original `String` have been implemented for the generic version instead. I don't foresee anything more moving from `String<Global>` to `String<A>`, as the remaining methods are all constructors which implicitly use the `Global` allocator. There are three general types of changes: 1. methods which don't allocate: here we just change `impl Foo for String` to `impl<A: Allocator> Foo for String<A>` 2. converting to/from other allocator generic types like `Vec<u8, A>` and `Box<str, A>`: here we can use the existing allocator from those types. 3. methods which clone from some other type with an allocator: here it's ambiguous whether the end result should be `String<A>`, `String<Global>`, or `String<impl Allocator + Default>`, etc; in general I try to leave these out of this change, but where some analogous change was made to `Vec<T, A>` I follow that. ## new methods Some methods have been added to `String<A>` which are not strictly necessary to land this change, but are considered helpful enough to users, and close enough to existing precedent in `Vec<T, A>`. Specifically, 4 new constructors (`new_in`, `with_capacity_in`, `try_with_capacity_in`, `from_raw_parts_in`), 1 destructor (`into_raw_parts_with_alloc`), and 1 getter (`allocator`). Technically, the updated `from_utf8_unchecked` should be sufficient for constructing, but we can add some safe constructors so users don't have to sully themselves. ## not implemented Variants of `from_utf{8,16}*` which internally allocate or use `Cow` have been punted on this PR, maybe a followup would make sense to either rewrite them, or add some `*_in` variant. [wg-allocators roadmap]: rust-lang/wg-allocators#7 [libs-team ACP]: rust-lang/libs-team#101 [workaround]: rust-lang#79499 (comment) [rust-lang#101551]: rust-lang#101551 [rust-lang#79500]: rust-lang#79500 [rust-lang#98931]: rust-lang#98931
Add `String<A>` type with custom allocator parameter This change is part of the `allocator_api` feature set [rust-lang#32838](rust-lang#32838) (also see [wg-allocators roadmap] or [libs-team ACP]). The previous attempts at adding an allocator parameter to string are at [rust-lang#101551], and [rust-lang#79500] (I think those authors should get much of the credit here, I am re-writing what they worked out in those threads). ## workaround There is a type inference ambiguity introduced when adding a generic parameter to a type which previously had none, even when that parameter has a default value (more details in [rust-lang#98931]). I've done the same [workaround] as [rust-lang#101551], which is to make `alloc::string::String` a type alias to `String<Global>`, but I've arranged the modules a bit differently to make rebase/merges a bit easier. This workaround unfortunately changes the type name of the `String` language item, and that would be user-facing in error or diagnostic output. I understand from [this comment](rust-lang#101551 (comment)) that this change is acceptable. ## changes to existing API Most of the methods on the original `String` have been implemented for the generic version instead. I don't foresee anything more moving from `String<Global>` to `String<A>`, as the remaining methods are all constructors which implicitly use the `Global` allocator. There are three general types of changes: 1. methods which don't allocate: here we just change `impl Foo for String` to `impl<A: Allocator> Foo for String<A>` 2. converting to/from other allocator generic types like `Vec<u8, A>` and `Box<str, A>`: here we can use the existing allocator from those types. 3. methods which clone from some other type with an allocator: here it's ambiguous whether the end result should be `String<A>`, `String<Global>`, or `String<impl Allocator + Default>`, etc; in general I try to leave these out of this change, but where some analogous change was made to `Vec<T, A>` I follow that. ## new methods Some methods have been added to `String<A>` which are not strictly necessary to land this change, but are considered helpful enough to users, and close enough to existing precedent in `Vec<T, A>`. Specifically, 4 new constructors (`new_in`, `with_capacity_in`, `try_with_capacity_in`, `from_raw_parts_in`), 1 destructor (`into_raw_parts_with_alloc`), and 1 getter (`allocator`). Technically, the updated `from_utf8_unchecked` should be sufficient for constructing, but we can add some safe constructors so users don't have to sully themselves. ## not implemented Variants of `from_utf{8,16}*` which internally allocate or use `Cow` have been punted on this PR, maybe a followup would make sense to either rewrite them, or add some `*_in` variant. [wg-allocators roadmap]: rust-lang/wg-allocators#7 [libs-team ACP]: rust-lang/libs-team#101 [workaround]: rust-lang#79499 (comment) [rust-lang#101551]: rust-lang#101551 [rust-lang#79500]: rust-lang#79500 [rust-lang#98931]: rust-lang#98931
Roadmap for allocator support.
API Change Proposal: rust-lang/libs-team#101 [ Accepted ]
A subset/bring-to-current of #79500 utilizing a workaround(?) to the issue (#79499) that was blocking it.
(Note: I previously tried rebasing that (2 year old) PR onto current master, which was not my best idea).
Blocked on:
Stringlibs-team#101Todo/Unresolved Questions:
Fix UI tests.Done?(see my question below)(see Apparent duplicated diagnostic note for type mismatch involving type with defaulted type parameter. #101992)String<A>.ShouldremovedFrom<String<A>> for Rc<str>/Arcbe removed from this PR? (Corresponding impl does not exist forVec/Rc<[T]>, and also it may preclude a futureFrom<String<A>> for Rc<str, A>)impl StructuralEq for String<_>be re-added? This PR removes it (because it no longerderive(Eq)), but it may not be observable becauseString: !StructuralPartialEqFromUtf8Error<_>, but that derived bothPartialEqandEqso it had bothStructuralPartialEqandStructuralEq.CString, which derivesPartialEqandEq.)impl<A: Allocator> From<String<A>> to Box<str, A>breaks orphan rules? (becauseBoxandstrare fundamental?)String<A>?fn String<A>::from_str_in(s: &str, alloc: A) -> String<A>?fn str::to_string_in(alloc: A) -> String<A>(parallelsslice::to_vec_in)to_string_intoToString? (Probably a non-starter, since that would make ToString not object-safe, unless we put awhere Self: Sized, which would precludestr)[ ] Other(removed FIXME comments, APIs moved to future work)FIXMEs (implement or remove comments)Possible Future work
from_utf8_lossy, which returns a non-allocator-awareCow<str>?from_utf16(_lossy), which returnStringandResult<String, _>?String<A> where A: Defaultfrom_utf16(_lossy)_in, (Add support for custom allocator for(C)String#79500 only addedfrom_utf16_in, not the lossy version)From<Cow<str>> for String<A> where A: Defaultcould be implemented asfrom_str_in(&*cow, A::default()), and specialized forA = Globalto the current implementationcow.into_owned().From<&String<A>> for String<A> where A: CloneorFrom<&String<A>> for String<B> where B: Default(I don't think both can exist).FromIterator<_> for String,FromStr for String, andFrom<&str-like> for Stringcould befor String<A> where A: Default.impl const Default for Stringcould beimpl<A: _ + ~const Default> Default for String<A>, except thatGlobaldoesn't implementconst Defaultcurrently (but I don't see any reason it couldn't).