<div dir="ltr">Regarding the white-listing, I also find it weird, but should the user experience be worse just because Rc and Arc are implemented in Rust and so we should do nothing in the name of orthogonality? A user won't care if Arc and Rc are built-in or not.<div>
<br></div><div>I may have passed the message that its only ugliness involved, and being lazy to type .clone(). But the point is uniformity and coherence of the pointers API, clarity, and ease of refactoring code. I am thinking of writing an RFC about cleaning up pointers. As of now there are some, in my opinion, needless non-uniformities in the use of pointers. I would like to have some properties:</div>
<div><br></div><div>1) Two programs that use pointers, identical except for pointer types and that both compile should produce semantically equivalent result (i.e., only differ in performance).</div><div><br></div><div>The idea is that different pointer types would be chosen according to capabilities (is move enough or do I want to mutate something I own, pick Box; do I want to share intra-task, pick Rc or Gc; inter-task, pick Arc). If a program fragment is written using,  say Gc, and later I decide to switch to Rc, I should need only change the declaration site(s) and not have to go all-over and add .clone().</div>
<div><br></div><div>(There are other things than Copy that need to be improved, like uniformity of auto-dereferencing and auto-borrowing. Fortunately I hope those to be not as controverse.)</div><div><br></div><div>2) Pointers should be transparent, and avoid confusion between methods of the pointer and methods of the referent.</div>
<div><br></div><div>In particular, having non Box pointers Copy and avoiding pointer cloning, all .clone() in code would mean cloning the referent, being uniform with what happens with Box pointers. A clone should be something more rare and conscious. As of now, having mechanical .clone() in many places makes the "real" refent clones less obvious. An unintended referent clone may go more easily unnoticed.</div>
<div><br></div><div>(Other aspects involve switching to UFCS style for pointer methods.)</div><div><br></div><div>3) Last use move optimisation should be applied for pointer types.</div><div><br></div><div>This is not as essential, but as now, the compiler will know the last use place of a variable and use move instead of copy. All white-listed for Copy pointer-types must allow this optimisation. As we are talking about a controlled, to be approved set of types (i.e. Rc and Arc), and not general user-defined types, we can be sure that for all white-listed types this is so. Last use move optimisation would result in the same performance of code as now. Again, this is coherent with Box types, where the first use (by value) must be also the last use.</div>
<div><br></div><div>Anyway, I would like to stress that much fewer pointer copies will exist in Rust given (auto-)borrowing. It is important to educate programers to always start by considering &T in function arguments, if they only need to use the T, and add more capabilities if needed. Something like &Rc<T> if the function needs to use the T and occasionally copy the pointer, and only Rc<T> if the normal case is copying the pointer.</div>
<div><br></div><div>This is why I even argue that Arc should be Copy even considering the much more expensive copy. The important thing is programers knowing the cost, which will happen for the very few white-listed types, as opposed to allowing general user-defined copies for which the cost is not clear for the reader. A program using Arc should not Use Arc all-over, but only in a few places; after spawning, the proc will typically pass not the Arc<T> but only &T to functions performing the work; this is unless those functions need to spawn further tasks but in this case, the Arc copies are need and in those places we would use .clone() anyway, resulting in the same performance.</div>
<div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On 21 June 2014 10:10, Nick Cameron <span dir="ltr"><<a href="mailto:lists@ncameron.org" target="_blank">lists@ncameron.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>I guess I forgot that C++ ref counted pointers (pre-11) generally have a move version of the type. Thanks for pointing that out.<br>
<br></div>I agree it would be odd to copy that design (Rc/RcTemp) in a language which has move semantics by default. I wonder if we could come up with _some_ design that would be better than the current one. My reasoning is that copy-with-increment is the (overwhelmingly) common case for ref-counted pointers and so should be easier/prettier than the less common case (moving). One could argue that the more efficient case (moving) should be prettier and I think that is valid. I'm not sure how to square the two arguments. I do think this deserves more thought than just accepting the current (`.clone()`) situation - I think it is very un-ergonimic. Having two types rather than two copying mechanisms seems more preferable to me, but I hope there is a better solution.<br>

</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Jun 21, 2014 at 6:21 PM, Cameron Zwarich <span dir="ltr"><<a href="mailto:zwarich@mozilla.com" target="_blank">zwarich@mozilla.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>On Jun 20, 2014, at 11:06 PM, Nick Cameron <<a href="mailto:lists@ncameron.org" target="_blank">lists@ncameron.org</a>> wrote:<br>


<br>
> zwarich: I haven't thought this through to a great extent, and I don't think here is the right place to plan the API. But, you ought to still have control over whether an Rc pointer is copied or referenced. If you have an Rc<T> object and pass it to a function which takes an Rc<T>, it is copied, if it takes a &Rc<T> or a &T then it references (in the latter case with an autoderef-ref). If the function is parametric over U and takes a &U, then we instantiate U with either Rc<T> or T (in either case it would be passed by ref without an increment, deciding which is not changed by having a copy constructor). If the function takes a U literal, then U must be instantiated with Rc<T>. So, you still get to control whether you reference with an increment or not.<br>


><br>
> I think if Rc is copy, then it is always copied. I would not expect it to ever move. I don't think that is untenable, performance wise, after all it is what everyone is currently doing in C++. I agree the second option seems unpredictable and thus less pleasant.<br>


<br>
</div>Copying on every single transfer of a ref-counted smart pointer is definitely *not* what everyone is doing in C++. In C++11, move constructors were added, partially to enable smart pointers to behave sanely and eliminate extra copies in this fashion (albeit in some cases requiring explicit moves rather than implicit ones like in Rust).<br>


<br>
Before that, it was possible to encode this idiom using a separate smart pointer for the expiring value. WebKit relies on (or relied on, before C++11) a scheme like this for adequate performance:<br>
<br>
<a href="https://www.webkit.org/coding/RefPtr.html" target="_blank">https://www.webkit.org/coding/RefPtr.html</a><br>
<br>
In theory, you could encode such a scheme into this “always copy on clone" version of Rust, where Rc would always copy, and RcTemp wouldn’t even implement clone, and would only be moveable and convertible back to an Rc. However, it seems strange to go out of your way to encode a bad version of move semantics back into a language that has native move semantics.<br>


<span><font color="#888888"><br>
Cameron</font></span></blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
Rust-dev mailing list<br>
<a href="mailto:Rust-dev@mozilla.org">Rust-dev@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/rust-dev" target="_blank">https://mail.mozilla.org/listinfo/rust-dev</a><br>
<br></blockquote></div><br></div>