-
Notifications
You must be signed in to change notification settings - Fork 1.6k
RFC: Add DerefMove #178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Add DerefMove #178
Conversation
|
👍 |
active/0000-deref-move.md
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like I am missing something in this second bullet: Whether we choose to move or copy a value is based on the static type of that value's expression. If I implement Deref<C> on Foo (for some C:Copy), then *foo will copy rather than move, right? Therefore, this specification seems circular, e.g. if I also implement DerefMove<Box<()>> on Foo as well, then I need to know the type of an expression like *foo to know whether its return value is being copied or being moved, but in order to know what the type of *foo is, I need to know whether I am supposed to be invoking deref or deref_move.
But perhaps I have misunderstood your intention, and there is some other property that you are trying to describe here that is unrelated to the type-based move/copy distinction. And if that is the case, perhaps there is another phrasing that would be clearer here. (I'm just guessing now, but would "if the dereference is in an rvalue context" work?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I mention a ‘move’ in the RFC, I generally mean a ‘move or copy’. So deref_move is called (if is implemented) whenever a value is moved or copied out of a dereference. This means that if I had a struct, Foo, that implemented Deref<int>, *foo (where foo: Foo) would call deref (because Foo doesn’t implement DerefMove). However, if I implemented DerefMove<uint> on Foo as well, even a copy like *foo would call deref_move, not deref any more.
In other words, deref_move is called if it looks like a move or copy. On types that also implement DerefMove, deref and deref_mut are only called when an expression along the lines of &*p or &mut *p is encountered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That won't work. uint is Copy but Foo probably isn't. It would need to call Deref<int> on Foo and copy out of the resulting &int instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s a good point. Maybe the rules could be revised to this:
- If the type implements
DerefMovebut notDereforDerefMut, all dereferences are done usingderef_move. - If a reference is being taken to a dereference (e.g.
&*ptr), calldereforderef_mut, depending on the mutability of the reference. - If a value is being dereferenced and implements
DerefMoveandDerefand/orDerefMut:- If the type is
Copy, callderef_move. - Otherwise:
- If the type implements
Deref<T>whereT: Copy, call*derefor*deref_mut. - Otherwise, call
deref_move.
- If the type implements
- If the type is
- If a value is being dereferenced and does not implement
DerefMovebut does implementDerefand/orDerefMut, usedereforderef_mut.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems reasonable to me. Presumably if the type implements both Deref and DerefMut, it will choose to use deref instead of deref_mut in 3.ii.a and 4.
|
Thanks for the RFC. I believe the plan is to implement This has the downside that |
6357402 to
e0acdf4
Compare
active/0000-deref-move.md
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear to me what is actually mean here - is this supposed to be *x.deref()?
|
I'm concerned about making DerefMove inherit from Deref. Servo needs DerefMove to allow us to create JSRef values on demand that borrow the Root that is being dereferenced. We're hacking around the currently lack of DerefMove by returning a JSRef value that isn't actually valid in all cases; there's no value we could return for Deref that would make sense in a world with DerefMove. |
|
I guess the best way (from a user perspective) of resolving the issue with // A hypothetical syntax for the above
pub trait DerefMove<T>: for<U> !Deref<U> where T != U {
// ...
}(Pretend the type parameters are associated types, like they should be.) I’m not sure if this would have any other repercussions relating to coherence. |
|
(meta-comment: could you update the Rendered View link in the top comment?) |
|
This is an important topic, but not one we are prepared to address now in the runup to 1.0. I hope we can come back to it shortly thereafter. Postponing for now under issue #997. |
|
Oh, and in case it wasn't clear, thanks very much for the RFC! |
Annotate `CpuFuture` with `#[must_use]`.
|
Should this issue be reopened now that the original rationale for closing it seems to no longer apply? I think there is quite a bit of interest. |
|
If you look slightly above your comment, that is tracked in #997. |
Rendered view