On 14/11/13 16:00, Tommi wrote:
On 2013-11-14, at 6:20, Tommi <[email protected]> wrote:

On 2013-11-14, at 5:54, Huon Wilson <[email protected]> wrote:

On 14/11/13 14:50, Tommi wrote:
let mut n = 11;
let p: &int = &123;

p + n; // OK
n + p; // error: mismatched types: expected `int` but found `&int`

Shouldn't this error be considered a compiler-bug? The Add trait says '&' for 
rhs after all:
fn add(&self, rhs: &RHS) -> Result;

-Tommi

_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev
This is https://github.com/mozilla/rust/issues/8895 . I believe it is caused by the 
implementation details of the overloaded-operator desugaring (a + b is equivalent to 
`a.add(&b)`, so auto-deref allows for `a: &T` with `b: T`), I personally think 
the more sensible resolution would be for `p + n` to be disallowed as well as `n + p`.

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

Thanks, I tried to search for a bug report for this but didn't manage to find that one. To me 
it makes perfect sense that p + n would work because if a + b is specified to be 
"just" syntactic sugar for a.add(b), then a + b should behave exactly like 
a.add(b), with implicit pointer dereferencing and all that good stuff. But, I don't 
understand why is it a.add(&b) like you said, though.

By the way, I would hate all of this behavior if Rust had pointer arithmetic, 
but luckily it doesn't seem to have it.

-Tommi

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

You're right in that it's not a bug in built-in types, but affects user-defined 
types also. But n.add(p) works just fine, while n.add(&p) doesn't:

struct Num { n: int }

impl Add<Num, Num> for Num {
     fn add(&self, other: &Num) -> Num { Num { n: self.n + other.n } }
}

fn main() {
     let n = 11i;
     let p = &22i;

     p + n; // OK
     n + p; // error: mismatched types: expected `int` but found `&int`
     n.add(p); // OK
     n.add(&p); // error: mismatched types: expected `&int` but found `&&int`

     let n = Num { n: 11 };
     let p = &Num { n: 22 };

     p + n; // OK
     n + p; // error: mismatched types: expected `Num` but found `&Num`
     n.add(p); // OK
     n.add(&p); // error: mismatched types: expected `&Num` but found `&&Num`
}

-Tommi

p has type &Num, which matches the type signature of add for Num, so it is expected that it compiles. And, &p has type & &Num, which doesn't match the signature of add for Num and so correspondingly doesn't compile. Similarly, for the + sugar, `n + p` and `n.add(&p)` (with the extra &) are the same (despite the error messages having one fewer layers of &).


The operator traits all take references because they (in the common case) don't want ownership of their arguments. If they didn't take references (i.e. `fn add(self, other: Num) -> Num`) then something like

  bigint_1.add(&bigint_2) // bigint_1 + bigint_2

would likely require

bigint_1.clone().add(bigint_2.clone()) // bigint_1.clone() + bigint_2.clone()

if one wanted to reuse the values in bigint_1 and bigint_2 later.


The current definitions of the traits means that the operator desugaring needs to implicitly add the references (that is a + b -> a.add(&b), rather than a.add(b)`) to match the type signature, or else we'd be forced to write `x + &1` everywhere.

(Just to be clear the auto-deref only happens on the "self" value, i.e. the value on which you are calling the method, not any arguments.)


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

Reply via email to