-
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
Provide a more explicit way to "clone" a standard reference counted pointer. #1954
Conversation
I’ve sometimes used |
Isn't there a case for putting
|
text/0000-rc-newref-clone.md
Outdated
|
||
This RFC does not involve any compiler change (only minor additions to alloc/rc.rs and alloc/arc.rs). | ||
|
||
The following steps apply to ```Rc<T>```, ```Arc<T>```, ```rc::Weal<T>```, ```arc::Weak<T>```. |
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.
Weal ↦ Weak.
text/0000-rc-newref-clone.md
Outdated
|
||
The following steps apply to ```Rc<T>```, ```Arc<T>```, ```rc::Weal<T>```, ```arc::Weak<T>```. | ||
|
||
A method ```fn new_ref(&self) -> Self``` is added to the pointer type, into which the code of the ```Clone::clone``` implementation is moved. |
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.
Better define it as
fn new_ref(this: &Self) -> Self;
to let user call it as
let p1 = Rc::new(vec![0u8; 1000]);
let p2 = Rc::new_ref(&p1); // <-- instead of p1.new_ref()
as explained in the doc of Rc:
The inherent methods of
Rc
are all associated functions, which means that you have to call them as e.g.Rc::get_mut(&value)
instead ofvalue.get_mut()
. This avoids conflicts with methods of the inner typeT
.
(The .clone()
method on Rc is precisely causing such a conflict.)
Thanks a lot for the feedback so far. I had not though about it before, but the concern about new_ref conflicting with the pointee type potentially having a new_ref method of its own is pretty serious and quite obvious in retrospect. I added it to the RFC under Drawbacks and Alternative, although depending on how the discussion goes it might become a reformulation of the main proposal. It would be great, though, if we could find a solution that is at least almost as convenient as clone, otherwise I fear that what will/may come out of this RFC won't be used in practice, which would defeat part of the purpose. |
I’m balanced. I think the distinction is important. I saw the example in some impl<T: _> Clone for Buffer<T> { _ } What do we expect a On the other side, I think that It’s all about confusion. In a perfect world, I’d rather prefer not having an |
I'm 100% behind the motivation for this RFC, but as @SimonSapin stated, we already have an explicit version ( If we don't add such a lint, the The "how do we teach this" section is insufficient imo, since the change of adding |
Very good point about the lint. Is this something that should go into the compiler, or is clippy the place for this type of thing? |
Well... in clippy we can insert this without an RFC. For the compiler, this RFC would need to continue. Deprecation is not breaking the code. Deprecation means you start getting warnings when you use it. So basically the same as adding a lint. |
Would this also deprecate deriving Clone for any type containing a reference counted pointer? |
We're not deprecating the |
Is the derived impl going to suppress that deprecation warning then? |
@sfackler Those use |
This sounds like a good idea. Maybe add |
Without weighing in on the specific solution, I just want to voice support for this being a problem that needs solving. I've always hated calling Minor noncommittal bike shed: |
Typo: repsective -> respective |
Ugh, sorry, mobile UI has no confirmation on acidental press. |
I think "use Arc::clone" (from @SimonSapin) deserves to be explicitly noted as an alternative in the RFC text. All the clarity and linting points could be done immediately with that, no need for a stabilization period. And at least the two I think whether Bikeshed: I'm not a fan of "new" in the name, since that has a somewhat different connotation in its usual use. What about just Also, if the name is going to include Is this always going to be on something where clone is shallow anyway? Clone being shallow for Overall, that could turn the proposal to something like this:
Another alternative: Put these methods (and possibly trait) in a crate, since there are no coherence issues. See how broadly the crate is used before putting into On the lint: warning on Arc::clone feels quite aggressive for rustc. I think it should live in clippy. |
I added the suggestion made by @SimonSapin to the alternatives section as well as something equivalent to the CloneRef trait suggested by @scottmcm. |
The libs team discussed this RFC a bit in triage yesterday, and the general consensus was that the |
I take it that the decision is made to go for So, taking this approach, what is the way forward from here? Is there a separate RFC process for clippy? Should I re-write this RFC to formalize that I'm about to go offline for two weeks but I'll be happy to help with these when I come back. I don't think that this approach will solve the problem (as in, the vast majority of code will still be written |
@nical You just need to file an issue to https://github.com/Manishearth/rust-clippy/issues. Typical reports seem to be pretty short (e.g. https://github.com/Manishearth/rust-clippy/issues/1594). |
Thanks, I filed a clippy issue. It would be good to clarify what the official position is with respect to the idiomatic way to clone a reference counted pointer before we close this pull request. |
What is considered as idiomatic way of cloning inner value then? Is it just |
Technically you could do |
Or |
I have always used the |
Favor the function over the method syntax when cloning a reference counted pointer. ```data.clone()``` reads like performance hazard, due to the vague definition of Clone, which can be either very expensive if data is an uniquely owned large resource or very cheap if it is a reference counted pointer to such a resource. This has already confused people reading the code and even code reviews several times in webrender, so I would like to work around this unfortunate ambiguity. I first tried to address this at the [standard library level](rust-lang/rfcs#1954) but the decision of the rust team appears to be that we should use the function syntax instead of the method syntax to address the problem. See also the [clippy issue](https://github.com/Manishearth/rust-clippy/issues/1645) about providing a lint for this. I decided to take a systematic approach and use the function call syntax for all of the outstanding reference counted pointer clones that I came across (I would not be surprised that I missed some of them). Rather than try to separate the obvious from the ambiguous ones. I would rather make this a default policy than have to debate about where the line is in each code review. The three commits are independent and can be reviewed separately (although they are small and simple enough to look at as one diff if you prefer). <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1037) <!-- Reviewable:end -->
Yep, @nical, do you want to close? |
Alright! I'll look into updating the docs as a follow up soon-ish. |
It was decided in the RFC discussion rust-lang/rfcs#1954 to make the function call syntax Rc::clone(&foo) the idiomatic way to clone a reference counted pointer (over the method call syntax foo.clone(). This change updates the documentation of Rc, Arc and their respoective Weak pointers to reflect it and bring more exposure to the existence of the function call syntax.
Update to Rc and Arc documentation to favor the Rc::clone(&ptr) syntax. This is a followup of the discussion in rust-lang/rfcs#1954. The solution chosen by the core team to address the problem tackled by the [the RFC](rust-lang/rfcs#1954) was to make the function call syntax Rc::clone(&foo) the idiomatic way to clone a reference counted pointer (over the method call syntax foo.clone()). This change updates the documentation of Rc, Arc and their respective Weak pointers to reflect this decision and bring more exposure to the existence of the function call syntax.
Update to Rc and Arc documentation to favor the Rc::clone(&ptr) syntax. This is a followup of the discussion in rust-lang/rfcs#1954. The solution chosen by the core team to address the problem tackled by the [the RFC](rust-lang/rfcs#1954) was to make the function call syntax Rc::clone(&foo) the idiomatic way to clone a reference counted pointer (over the method call syntax foo.clone()). This change updates the documentation of Rc, Arc and their respective Weak pointers to reflect this decision and bring more exposure to the existence of the function call syntax.
Update to Rc and Arc documentation to favor the Rc::clone(&ptr) syntax. This is a followup of the discussion in rust-lang/rfcs#1954. The solution chosen by the core team to address the problem tackled by the [the RFC](rust-lang/rfcs#1954) was to make the function call syntax Rc::clone(&foo) the idiomatic way to clone a reference counted pointer (over the method call syntax foo.clone()). This change updates the documentation of Rc, Arc and their respective Weak pointers to reflect this decision and bring more exposure to the existence of the function call syntax.
Remove recommendation about idiomatic syntax for Arc::clone I believe we should not make this recommendation. I don't want to argue that `Arc::clone` is less idiomatic than `arc.clone`, but that the choice is not clear cut and that we should not be making this kind of call in the docs. The `.clone()` form has advantages too: it is more succinct, it is more likely to be understood by beginners, and it is more uniform with other `clone` calls, indeed with most other method calls. Whichever approach is better, I think that this discussion belongs in a style guide or textbook, rather than the library docs. We don't talk much about idiomatic code in the docs, this place is pretty exceptional. The recommendation is also not followed in this repo. It is hard to figure out how many calls there are of the `.clone()` form, but there are 1550 uses of `Arc` and only 65 uses of `Arc::clone`. The recommendation has existed for over two years. The recommendation was added in rust-lang#42137, as a result of rust-lang/rfcs#1954. However, note that that RFC was closed because it was not necessary to change the docs (the original RFC proposed a new function instead). So I don't think an RFC is necessary here (and I'm not trying to re-litigate the discussion on that RFC (which favoured `Arc::clone` as idiomatic) in any case). cc @nical (who added the docs in the first place; sorry :-) ) r? @alexcrichton (or someone else on @rust-lang/libs )
This is my first RFC.
This RFC proposes a very small addition to the standard reference counted pointer types, that aims solving a recurrent paper-cut-type of annoyance related the lack of clarity of code calling
clone()
.Rendered.