Skip to content

Permit fn(self) methods to be invoked on object types #10672

Closed
@nikomatsakis

Description

@nikomatsakis

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generation

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions