Currently, methods declared as self cannot be invoked on object types. The reason for this is that, without knowing the type of the receiver, we can't know whether self is to be passed with indirection or as an immediate value.
For example:
trait Consume { fn take(self) { ... } }
impl Consume for int {
fn take(self) { ... /* self should be passed as an immediate here */ ... }
}
impl Consume for MyBigStruct {
fn take(self) { ... /* self not passed as an immediate here */ ... }
}
So now if I have a ~int casted to ~Consume, and I were to invoke take(), I would want to load from the ~int, pass the loaded value, and then free the ~int after the call returns (or maybe in a different order; I don't want to think too hard about weird failure cases since that's not really the point of this issue). If I have a ~MyBigStruct, I would want to pass the pointer itself to take (since take expects a MyBigStruct*, essentially). After the call returns, take() will have freed the MyBigStruct but not the ~ pointer itself, so I can shallow free the pointer. But of course all I know at codegen time is that I have a ~Consume and thus I can't distinguish these two cases.
This is however rather inconvenient, as the above example shows. It is particularly inconvenient since using a ~self method isn't really a good alternative, particularly if you try to implement the trait for the object type:
trait Message { fn send(~self) { ... } }
impl Message for ~Message { fn send(~self) { /* self: ~~Message */ } }
Now I need a ~~Message! Silly. This would work fine if send() were a self method, though.
The thing is, if we were a bit more clever, we could permit by-value calls on object types. We can just say that for virtual calls self is always passed indirectly, and then generate a shim function to use in the vtable that does a load for immediate receivers.
Nominating although I think this is something that can possibly wait till post 1.0, since it's not a backwards compat question. I'd still call it high priority (presuming others agree with my reasoning).
Currently, methods declared as
selfcannot be invoked on object types. The reason for this is that, without knowing the type of the receiver, we can't know whetherselfis to be passed with indirection or as an immediate value.For example:
So now if I have a
~intcasted to~Consume, and I were to invoketake(), I would want to load from the~int, pass the loaded value, and then free the~intafter the call returns (or maybe in a different order; I don't want to think too hard about weird failure cases since that's not really the point of this issue). If I have a~MyBigStruct, I would want to pass the pointer itself totake(sincetakeexpects aMyBigStruct*, essentially). After the call returns,take()will have freed theMyBigStructbut not the~pointer itself, so I can shallow free the pointer. But of course all I know at codegen time is that I have a~Consumeand thus I can't distinguish these two cases.This is however rather inconvenient, as the above example shows. It is particularly inconvenient since using a
~selfmethod isn't really a good alternative, particularly if you try to implement the trait for the object type:Now I need a
~~Message! Silly. This would work fine ifsend()were aselfmethod, though.The thing is, if we were a bit more clever, we could permit by-value calls on object types. We can just say that for virtual calls
selfis always passed indirectly, and then generate a shim function to use in the vtable that does a load for immediate receivers.Nominating although I think this is something that can possibly wait till post 1.0, since it's not a backwards compat question. I'd still call it high priority (presuming others agree with my reasoning).