Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upPermit `fn(self)` methods to be invoked on object types #10672
Comments
This comment has been minimized.
This comment has been minimized.
|
I am of two minds on this issue. One part of me likes simple rules of thumb like: "eschew fn foo(~self); do foo(self) instead." (as noted on niko's Thoughts on DST part I). So that part of me would like such methods to actually be supported on object types. Another part of me likes to have a simplified compilation model in my mind, with as little magic as possible (or at least the potential for ALMAP ... I am after all still a GC guy...). And that part of me figures we should keep things the way that they are; if you want a method to be invokable on the objects of a trait, then the type for the self pointer needs to be reflected in the method's type, including which kind of pointer it is. Having said that, I haven't thought of a concrete reason to disallow the generalization suggested here, beyond mental complexity when trying to understand the control flow from the invocation point to the entry to the method itself. For which pointer-variants would we generate these shim functions? Will it only work for Or is this something that we can infer on a impl by impl basis, choosing the most general option that is sound? |
This comment has been minimized.
This comment has been minimized.
|
On Mon, Dec 02, 2013 at 08:43:47AM -0800, Felix S Klock II wrote:
In general I agree, but, if we don't wind up with a DST-based system,
As magic goes, what I proposed is pretty minimal. Basically a variant
That said, this interacts with the smart pointers. I outlined some |
alexcrichton
referenced this issue
Dec 2, 2013
Closed
By-value self methods on trait objects have bad error messages #9893
This comment has been minimized.
This comment has been minimized.
|
I have closed #9893 in favor of this bug, but if this bug is rejected then that bug should be re-opened (because the error message today isn't exactly ideal). |
This comment has been minimized.
This comment has been minimized.
|
As part of another discussion, I realized that this is a special case of a more general sort of pointer. For want of a better name, I'll call it a "my" pointer: So the "adapter" methods I described for |
This comment has been minimized.
This comment has been minimized.
|
Is this the same mythical pointer type that's needed to make once stack closures as DSTs work? (Maybe that's what the I think it makes sense to view this as a natural progression on I think it also makes sense to think about the converse: a pointer to potentially-unitialized memory which you have the obligation to initialize, corresponding to C#'s concept of an |
This comment has been minimized.
This comment has been minimized.
|
Yes, i've spent some time thinking about "obliation to initialize" -- that is much harder. In particular, that would have to be a linear value -- meaning it could not be 'dropped' (except possibly by failure -- but even there we have to be careful). Currently, though, we assume all values can be dropped, and hence permit generic functions like the following:
and I invoke with a The natural implication is that either (1) dropping a type parameter must become an explicit operation:
(Incidentally this only works if |
This comment has been minimized.
This comment has been minimized.
|
I guess that the natural pointer type for |
This comment has been minimized.
This comment has been minimized.
|
You're right, I was sloppy in my thinking about the out-pointer. I was thinking it would error if you reached the end of the function without initializing through it, but that obviously didn't take generic functions into account. I wonder how many generic functions would actually wind up needing a |
This comment has been minimized.
This comment has been minimized.
|
Not a backcompat risk; so accepting at P-low. (If one finds more evidence to up its priority, then renominate.) |
This comment has been minimized.
This comment has been minimized.
|
I couldn't fall asleep last night because I was thinking about pointer types; how's that for fun? As you alluded to, the problem of (I also don't see any reason why making As before, after assigning through an
I think this is fine, because if someone lends you an
These two effectively reify the cycling of data between initialized and uninitialized states as a first class abstraction for the programmer. Using the above we can implement
I suspect this means that arbitrary permutations could also be expressed using only safe code.
where it allocates an element and returns the obligation to initialize it. Smart pointers:
where it initializes the pointer, allocates the box, and returns the obligation to initialize its contents. (I also suspect it could be used to tie the knot, though I haven't figured out a way to do it without Anyway, I used to think |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis I'm starting to have second thoughts, not about
I suppose, if it stays part of the language, we could hardcode this for |
This comment has been minimized.
This comment has been minimized.
I envisioned a distinct method being called for shallow drop, in this case. Clearly the pointer type would have to opt-in. It's actually already an issue of sorts, in that we would like to be able to move out of smart pointer types. |
sfackler
referenced this issue
Mar 8, 2014
Closed
Trait objects cannot call methods that take self by-value #12761
This comment has been minimized.
This comment has been minimized.
|
cc @pcwalton |
This comment has been minimized.
This comment has been minimized.
|
Nominating, P-backcompat-lang—needed for unboxed closures to replace |
pcwalton
added
the
P-backcompat-lang
label
Jun 11, 2014
pcwalton
added
the
I-nominated
label
Jun 11, 2014
This comment has been minimized.
This comment has been minimized.
|
Already marked P-backcompat-lang; adding to the 1.0 milestone. |
nikomatsakis commentedNov 26, 2013
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).