> A user won't care if Arc and Rc are built-in or not. They will definitely care, once they attempt to write their own pointer types and find that they're second-class citizens compared to the types that have been blessed by the compiler. There's little point in having a powerful and extensible language if even simple types need hardcoded compiler magic to function.
On Sat, Jun 21, 2014 at 7:42 AM, Paulo Sérgio Almeida <pssalme...@gmail.com> wrote: > 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. > > 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: > > 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). > > 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(). > > (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.) > > 2) Pointers should be transparent, and avoid confusion between methods of > the pointer and methods of the referent. > > 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. > > (Other aspects involve switching to UFCS style for pointer methods.) > > 3) Last use move optimisation should be applied for pointer types. > > 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. > > 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. > > 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. > > > > On 21 June 2014 10:10, Nick Cameron <li...@ncameron.org> wrote: > >> I guess I forgot that C++ ref counted pointers (pre-11) generally have a >> move version of the type. Thanks for pointing that out. >> >> 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. >> >> >> On Sat, Jun 21, 2014 at 6:21 PM, Cameron Zwarich <zwar...@mozilla.com> >> wrote: >> >>> On Jun 20, 2014, at 11:06 PM, Nick Cameron <li...@ncameron.org> wrote: >>> >>> > 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. >>> > >>> > 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. >>> >>> 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). >>> >>> 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: >>> >>> https://www.webkit.org/coding/RefPtr.html >>> >>> 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. >>> >>> Cameron >> >> >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev@mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> >> > > _______________________________________________ > Rust-dev mailing list > Rust-dev@mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > >
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev