Here's one use case your proposal doesn't cover:
Subtracting two points returns a vector, which either has the same internal 
representation as a point or uses point as its internal representation, and 
thus, despite the return type of the subtraction operation being different from 
`Self`, it's still eligible for the implicit move-optimization.

For example, assuming a `Sub` definition that moves `self`:

struct Point {
    coordinates: Vec<int>
}

struct Vector {
    end_point: Point
}

impl Sub<Point, Vector> for Point {
    fn sub(self, rhs: &Point) -> Vector {
        for (left, right) in 
self.coordinates.mut_iter().zip(rhs.coordinates.iter()) {
            *left -= *right;
        }
        Vector { end_point: self }
    }
}

On 2014-06-17, at 11:04, Jan Klesnil <[email protected]> wrote:

> Hi,
> 
> Maybe we should look at the problem from other perspective? Currently the x 
> += y expression is sugar for x = x + y. Can we flip it over and make x = x + 
> y expression sugar for x = { let tmp = x; tmp += y }? What to do for non-Copy 
> types then?
> 
> It can be fixed by having traits for both + and += operators with default 
> implementation of Add for Copy types.
> 
> trait Add<RHS> {
>  fn add(&mut self, &rhs : RHS);
> }
> 
> trait BinaryAdd<RHS, RES> {
>  fn add(&self, &rhs : RHS) -> RES;
> }
> 
> impl<RHS, T : Copy + Add<RHS>> BinaryAdd<RHS, T> for T {
>  fn add(&self, &rhs : RHS) -> T {
>    let mut tmp = self;
>    tmp += rhs;
>    tmp
>  }
> }
> 
> For any addable type you either implement Add and Copy, or Add and BinaryAdd 
> if the type is too expensive to be implicitly copyable, or just the BinaryAdd 
> if the result's type is different from Self.
> 
> Then the rustc may be allowed to use Add instead of BinaryAdd for temporary 
> values and for += expressions:
> let a = a + b;  => a += b;
> let c = get_new_foo() + b;  => let c=get_new_foo(); c+=b;
> c += a;
> 
> It will be user's responsibility to provide compatible implementations for 
> Add and BinaryAdd (results, side-effects, etc.).
> 
> JK
> 
> On 16.6.2014 16:32, Sebastian Gesemann wrote:
>> The following message got sent to Patrick instead to the list by mistake.
>> Sorry, Patrick!
>> 
>> ---------- Forwarded message ----------
>> From: [email protected]
>> Date: Mon, Jun 16, 2014 at 4:29 PM
>> Subject: Re: [rust-dev] &self/&mut self in traits considered harmful(?)
>> To: Patrick Walton <[email protected]>
>> 
>> 
>> On Sat, Jun 14, 2014 at 2:46 AM, Patrick Walton wrote:
>>> I have filed RFC #118 for this:
>>> https://github.com/rust-lang/rfcs/pull/118
>>> 
>>> Patrick
>> Bold move. But I'm not convinced that this is a good idea. I may be
>> missing something, but forcing a move as opposed to forcing an
>> immutable reference seems just as bad as an approach. Also, I'm not
>> sure why you mention C++ rvalue references there. References in C++
>> are not objects/values like C++ Pointers or References in Rust. They
>> are auto-borrowing and auto-deref'ing non-values, so to speak. These
>> different kinds of L- and Rvalue references combined with overloading
>> is what makes C++ enable move semantics.
>> 
>> I think one aspect of the issue is Rust's Trait system itself. It
>> tries to kill two birds with one stone: (1) Having "Interfaces" with
>> runtime dispatching where Traits are used as dynamically-sized types
>> and (2) as type bound for generics. Initially, I found this to be a
>> very cool Rust feature. But now, I'm not so sure about that anymore.
>> Back in 2009 when "concepts" were considered for C++ standardization,
>> I spent much time on understanding the intricacies of that C++ topic.
>> This initial "concepts" design also tried to define some type
>> requirements in terms of function signatures. But this actually
>> interacted somewhat badly with rvalue references (among other things)
>> and I think this is one of the reasons why "concepts lite" (a new and
>> simplified incarnation of the concepts design, expected to augment
>> C++1y standard in form of a technical report) replaced the function
>> signatures with "usage patterns". As a user of some well-behaved type,
>> I don't really care about what kind of optimizations it offers for +
>> or * and how they work. I'm just glad that I can "use" the "pattern"
>> x*y where x and y refer to instances of some type. Whether the
>> implementer of that type distinguishes between lvalues and rvalues via
>> overloading or not is kind of an implementation detail that does not
>> affect how the type is being used syntactically. So, I expect "C++
>> concepts lite" to be able to specify type requirements in terms of
>> "usage patters" in a way that it allows "models" of these "concepts"
>> to satisfy the requirements in a number of ways (with move
>> optimizations being optional but possible).
>> 
>> Another thing I'm not 100% comfortable with (yet?) is the funky way
>> references are used in Rust in combination with auto-borrowing (for
>> operators and self at least) and auto-deref'ing while at the same
>> time, they are used as "values" (like C++ pointers as opposed to C++
>> references). I've trouble putting this into words. But it feels to me
>> like the lines are blurred which could cause some trouble or bad
>> surprizes.
>> 
>> Assuming this RFC is accepted: How would I have to implement Add for a
>> custom type T where moving doesn't make much sense and I'd rather use
>> immutable references to bind the operands? I could write
>> 
>>    impl Add<&T,T> for &T {...}
>> 
>> but it seems to me that this requires explicit borrowing in the user code à 
>> la
>> 
>>    let x: T = ...;
>>    let y: T = ...;
>>    let c = &x + &y;
>> 
>> Or is this also handled via implicit borrowing for operators (making
>> operators a special case)?
>> 
>> Still, I find it very weird to impl Add for &T instead of T and have
>> this asymmetry between &T and T for operands and return value.
>> 
>> Can you shed some more light on your RFC? Maybe including examples? A
>> discussion about the implications? How it would affect Trait-lookup,
>> implicit borrowing etc? What did you mean by "The AutorefArgs stuff in
>> typeck will be removed; all overloaded operators will typecheck as
>> though they were DontAutorefArgs."? Many thanks in advance!
>> 
>> Cheers
>> sg
>> _______________________________________________
>> Rust-dev mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/rust-dev
> 
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev

_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to