[rust-dev] Fwd: &self/&mut self in traits considered harmful(?)

Sebastian Gesemann s.gesemann at gmail.com
Thu Jun 19 09:13:07 PDT 2014

On Thu, Jun 19, 2014 at 1:59 PM, SiegeLord wrote:
> [...]
> I don't think merely changing the type of self/arg to be by move is the only
> solution, or the best solution. It does seem to be the case that different
> operators benefit from reusing temporaries differently, but it's clear that
> *some* operators definitely do (e.g. thing/scalar operators,
> addition/subtraction, element-wise matrix-operators)

Sure. I'm not denying this.

> and the current
> operator overloading traits prevent that optimization without the use of
> RefCell or lazy evaluation. Both of those have non-trivial semantic costs.
> In the case of operators that do benefit from reusing temporaries, doing so
> via moving seems very natural and relatively clean.

Here's another idea: Introduce a new uniform parameter type that
supports both: acting like an immutable reference to lvalues (to keep
them as they are) OR doing a move for rvalues (because almost nobody
would care):

   trait Mul<RHS,RES> {
      fn mul<'a,'b>(self: Arg<'a,Self>, rhs: Arg<'b,RHS>) ->RES;

where Arg is something like this:

    pub enum Arg<'b,T> {
        keep(&'b T),

and the compiler coerses Lvalues into keep(&mylvalue) and and Rvalues
into move(myrvalue) automatically if the user was not explicit. This
way one can still benefit from move semantics (sometimes with an
explicit move) and it does not require clone()-calls in the user code.

See here for an example on how Arg could be used: http://is.gd/etvAu7
(in this example, I used the keep/move variant constructors explicitly
but the idea is to let the compiler automatically pick the right, see
previous paragraph).

It's like C++ overload resolution deferred to runtime matching. Maybe
this could be optimized in some clever way. For example, if the
function is inlined, only one match arm remains ("static matching").
And maybe it would even benefit from some core language sugar. I hear
@ is not used anymore ;) Some sugar would remove the need to specify
lifetimes (in almost all cases) and make self work again without
explicit types:

   trait Mul<RHS,RES> {
      fn mul(@self, rhs: @RHS) ->RES;

We have something similar already (MaybeOwned) but the "constructor
magic" (inferring the right variant based on the value category)
hasn't been done yet as far as I know.


More information about the Rust-dev mailing list