-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add a RFC for TryClone trait #2189
Conversation
text/0000-try-clone-trait.md
Outdated
fail. In case we do not need this, implementing the RFC will produce extra maintenance | ||
overhead. | ||
|
||
[1] https://github.com/search?l=Rust&q=TryClone&type=Code&utf8=%E2%9C%93 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Prefer inline links instead of footnotes.
text/0000-try-clone-trait.md
Outdated
``` | ||
pub trait TryClone<T> { | ||
type Error, | ||
fn try_clone() -> Result<Self, Self::Error> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should:
fn try_clone_from(&mut self, source: &Self) -> Result<(), Self::Error> { ... }
be added to mirror Clone
?
text/0000-try-clone-trait.md
Outdated
# Motivation | ||
A number of crates have defined `TryClone` as a trait and implemented it on standard | ||
types [1]. Including this in the standard library will reduce some clutter in the code | ||
of those crates. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What code? Can you give an example of real-world code that would be improved here?
To me, it does not look like If anything, their naming says more to be about the ancestry of these types than anything else.
What I see in that link are:
|
You meant
Note that those are also candidates for an All in all, I do like the proposal. I probably won't need it any time soon, but I like having it around, just in case. One more thing, though: Besides quite some typos, you forgot about pub trait TryClone: Sized {
type Error;
fn try_clone(&self) -> Result<Self, Self::Error>;
#[inline]
fn try_clone_from(&mut self, src: &Self) -> Result<(), Self::Error> {
*self = src.try_clone()?
}
} |
text/0000-try-clone-trait.md
Outdated
This trait should be added in `std` and should be called `TryClone`. It should look similar | ||
to `TryFrom` | ||
|
||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
```rust
For syntax highlighting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, someone has already requestes this.
Thanks, everyone. Pushed a new version with all comments addresses. |
|
||
One example is [Clone](https://doc.rust-lang.org/src/alloc/arc.rs.html#710) for `std::alloc::arc`. This is better represented | ||
by returning a `Result<Arc>`. Doing that will also make the unsafe block unnecessary. Also, this will enable | ||
the caller to handle these errors idiomatically instead of aborting the process. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error is only encountered if your process leaks at a minimum 2 billion copies of the Arc, after which you can never clone it again. How is that situation supposed to be "idiomatically handled"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talking about 2 billion copies... An Arc
takes 4 bytes on 32-bit architectures plus the data behind that 4 bytes pointer. If, in theory, you could use every single byte of your program to allocate a copy of an Arc
, then you would have a maximum reference count of 0x40000000_u32
, which is < u32::max_value()
. And now reduce that number further, because you also have to fit the actual data, your whole program, and the OS kernel into your 4GiB address space.
As a result, it is absolutely impossible to overflow the reference counters of Arc
and Rc
, ever, on any CPU architecture. So, in a way, you could optimise alloc
instead by not doing overflow checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let foo = Arc::new(0);
loop {
mem::forget(foo.clone());
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, that is just evil. ;)
I see it as useful for wrapping C libraries. Most have functions for copying/duplicating their objects, but they're allowed to fail ( |
Do we need a |
Just fyi,
|
One important thing was not clear to me from the RFC and the discussion so far -- the text seems to frame TryClone as an improvement over ad hoc |
Thanks for pursuing this design and for the insightful discussion! I am going to close because I think we will be all right continuing to use individual |
Rendered