Open TimDiekmann opened 5 years ago
I've started in https://github.com/rust-lang/rust/pull/60703 .
@obsidianminor has asked about the Clone
trait needing to also be modified:
(38183) Allocator aware std traits - rust-lang - Zulip
There's a number of traits that implicitly allocate to the global allocator like
str
ToOwned
making aString<Global>
andClone
String<Global>
always making anotherString<Global>
which would make it slightly more difficult to move data across allocators.let a: String<Global> = format!("hello world!"); let b: String<System> = a.clone(); // nope, that's a String<Global> let b: String<System> = { // we could do it manually let mut z: String<System> = String::new(); z.push_str(a.as_str()); z }; let b: String<System> = a.clone_in(System); // or use a trait let s: &'static str = "hello world!"; let t: String<Global> = s.to_owned(); let u: String<System> = s.to_owned(); // nope, it's Global again let v: String<System> = s.to\_owned\_in(System);
Is there an issue yet talking about traits like this?
Any reason this issue couldn't also accomodate Clone
and any other traits/method we think of along the way? :)
Thoughts on CloneIn: Clone
trait instead of adding an additional clone_in
method to `Clone?
@lachlansneff: What would your motivation be for splitting into another trait?
@ErichDonGubler
Adding it to Clone
would be a breaking change. I can't think of a valid default implementation for Clone::clone_in
and many types would have nothing to do with an allocator.
I think this should be added to the list in #15.
When implementing Box
and RawVec
I had to limit those traits to allocators, which implements Default
which is rather limiting.
However, as @SimonSapin noticed in https://github.com/rust-lang/wg-allocators/issues/15#issuecomment-489595249, it's probably fine to add them at a later point. Additionally, if you really need those traits, I think a third party trait should be possible here until landed.
Okay. I'm guessing it'd look something like this?
pub trait CloneIn {
type Alloc: Alloc;
fn clone_in(&self, allocator: Self::Alloc) -> T;
}
Adding it to Clone would be a breaking change. I can't think of a valid default implementation for Clone::clone_in and many types would have nothing to do with an allocator.
Wouldn't just calling regular clone
and ignoring the allocator be a valid default implementation?
@Amanieu, how could it produce a SomeType<A>
when Clone::clone
would just create a SomeType<System>
?
@ErichDonGubler, I don't think it'd need a Alloc
associated type, but it would need a generic self type I think.
pub trait CloneIn {
type This<A: Alloc>;
fn clone_in<A: Alloc>(&self, allocator: A) -> Self::This<A>;
}
This won't be possible until generic associated types, maybe there's another way of doing it?
I was thinking something like
pub trait CloneIn<A: Alloc> {
type Cloned;
fn clone_in(&self, allocator: A) -> Self::Cloned;
}
Then you can implement it like
impl<S, A: Alloc> CloneIn<A> for String<S> {
type Cloned = String<A>;
fn clone_in(&self, allocator: A) -> Self::Cloned {
String { vec: self.vec.clone_in(allocator) }
}
}
I had this in mind:
pub trait CloneIn<B: BuildAllocRef>: Sized
where
B::Ref: AllocRef,
{
fn clone_in(&self, a: B::Ref) -> Self
where
B::Ref: AllocRef<Error = crate::Never>;
fn try_clone_in(&self, a: B::Ref) -> Result<Self, <B::Ref as AllocRef>::Error>;
}
But this has to be enhanced by an associative Self type.
I think this should be discussed in #15 or in a new Issue.
@Amanieu
Wouldn't just calling regular clone and ignoring the allocator be a valid default implementation?
How would you add this method to Clone
? (*)
IIUC what you are proposing, what would something like this do
let x: Vec<T, A>;
let y: Vec<T, U> = x.clone_in();
if Clone::clone_in
is implemented on top of clone
?
(*) I can imagine that we either have Clone<A> for T
which would be a breaking change, or Clone::clone_in<Other>(&self) -> Other where Self: Sized
or something like that, but I'm probably missing some more obvious extension.
can't we make the clone
method generic:
fn clone<A = Global>(&self) -> Self where A: Alloc;
@95th You would need to return a different type than Self
to be able to clone a Box<T, A>
into one that has a different type because it has a different allocator, e.g., Box<T, B>
.
@gnzlbg you're right sorry.. A type based on generic param..
Edit: I realize the problem with this
Do we also need to associate an allocator for owned strings types from std::ffi
module? That will include CString
and OSString
...
On Sonntag, 10. November 2019 23:23:43 CET Qifan Lu wrote:
Do we also need to associate an allocator for owned strings types from
std::ffi
module? That will includeCString
andOSString
...
Adding an associated allocator to CString
should be pretty straightforward,
as it's basically a Box<[u8]>
. OSString
depends on the Os, but this
shouldn't be a problem as well. Based on this, also PathBuf
may should get
an allocator, too. All three have a low priority at time of writing though.
Currently, there is a PR upstream for Box
and BTreeMap
. After Box
is merged, I'll adjust Vec
and String
.
I updated the OP to reflect this.
cc @exrook
When can we put Vec<T, A>
into std? I keep track of vec more than the rest, maybe I can help out with vec?
I just answered the question right above. And my fat fingers clicked the wrong button :D
rust-lang/rust#77187 just got merged. I'll add an allocator parameter to Vec
next.
https://github.com/rust-lang/hashbrown/pull/133 got merged a few days ago, adding custom allocator support to hashbrown.
Would this working group be willing to accept a PR for the std HashMap
and HashSet
too, or is it too early?
Forwarding to hashbrown
should be pretty straightforward. Currently, Vec
is queued for a crater run and this will take a while. I can take a look at HashMap
(+ HashSet
, which is basically the same) afterwards. Thanks for the heads up!
@TimDiekmann It seems like efforts to add allocator to CString
has stalled due to issues with generic parameter stability attributes... Would it be a good idea to turn to other data structures first, such as HashMap
and HashSet
suggested by @hansihe, while waiting for someone to fix the issue?
There is an open proposal #79 which would replace the allocator backend with a storage backend, which is more flexible and intuitive. This is looking very promising and I'd prefer that in favor of adding allocators to every data structure. Since recently it is in a state with which it seems worth experimenting within std.
Is there interest in accepting contributions implementing Allocators for the various remaining containers? I'd like to try and help knock some of those out.
Yes, very much! Since I am currently relocating, I currently have only limited time.
Awesome! Alright, I've got the rust repo cloned and will be making an rc-alloc
branch.
Anything I should know/adhere to going forward?
https://rustc-dev-guide.rust-lang.org/contributing.html#contributing-to-rust should be a good start
After reading into that, use ./x.py setup
to configure it for libs so you don't have to rebuild the whole compiler and for it to automatically download it online, that will make the development process much faster. I think the docs mention it somewhere but you need to find it, maybe you can just run that. After that you can start iterating on the libs. You might want to pick something simpler such as Rc
first. Usually you only want ./x.py check
or it might take a long time if you do ./x.py test
or ./x.py build
, at the end you might want to write some tests and do ./x.py test --bless
to automatically fix the tests for you, you might also want to do test filtering.
https://rustc-dev-guide.rust-lang.org/getting-started.html?highlight=setup#configuring-the-compiler may also be useful. The rustc-dev-guide is kind of geared towards the compiler itself, but a lot of the advice also applies to the standard library.
@TimDiekmann I have just sent a PR for VecDeque
, could you add it to the top-level list ?
@TimDiekmann I made a PR for Rc
in rust-lang/rust#89132, could you add that to the list?
I might have a usecase for BinaryHeap
with custom allocators. Looking at the source, BinaryHeap
is just a wrapper around Vec
, which is already allocatorized, so extending it to support allocator api should be relatively straightforward.. I hope.
I notice there is no linked issue. If I want to add this, should I create an issue in rust-lang/rust
and go from there?
I think you can just go ahead and write a pull request for it. All the allocators are under the #32838 tracking issue.
@TimDiekmann I have a PR for LinkedList
here: https://github.com/rust-lang/rust/pull/103093
Thanks, updated!
Oh, I didn't realize I had to post back here, but I made a PR for BinaryHeap
some time ago, but it looks like it got buried https://github.com/rust-lang/rust/pull/99339
There are a few changes to the list in the issue - @TimDiekmann would you want to update these items?
Thank you, I updated the comment.
Rc and Arc just landed! https://github.com/rust-lang/rust/pull/89132#event-9843774823
This WG wants to associate an allocator for all suitable structs. This issue tracks those structs, which are covered so far (non-exhaustive list):
Box<T, A>
: rust-lang/rust#77187Rc<T, A>
: rust-lang/rust#89132Arc<T, A>
: rust-lang/rust#89132String<A>
: https://github.com/rust-lang/rust/pull/101551CString<A>
: rust-lang/rust#79500Vec<T, A>
: rust-lang/rust#78461VecDeque<T, A>
: rust-lang/rust#86595LinkedList<T, A>
: rust-lang/rust#103093HashMap<K, V, S, A>
: rust-lang/hashbrown#133BTreeMap<K, V, A>
: rust-lang/rust#98103HashSet<T, S, A>
BTreeSet<T, A>
: https://github.com/rust-lang/rust/pull/98103BinaryHeap<T, A>
: https://github.com/rust-lang/rust/pull/99339OsString<A>
)PathBuf<A>
)