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 upRFC: deref coercions #241
Conversation
This comment has been minimized.
This comment has been minimized.
|
cc @nick29581 @nikomatsakis |
aturon
referenced this pull request
Sep 16, 2014
Closed
Allow implicit coercions for cross-borrows. #226
sfackler
reviewed
Sep 16, 2014
| Of course, method dispatch can implicitly execute code via `Deref`. But `Deref` | ||
| is a pretty specialized tool: | ||
|
|
||
| * Each type `T` can only deref to *one* other type. |
This comment has been minimized.
This comment has been minimized.
sfackler
Sep 16, 2014
Member
Is this a formal restriction or an informal one? AFAIK it's currently possible to do something like
trait Foo { ... }
impl Foo for int { ... }
impl Foo for uint { ... }
struct Bar;
impl<T> Deref<T> for Bar where T: Foo { ... }
This comment has been minimized.
This comment has been minimized.
aturon
Sep 16, 2014
Author
Member
Once associated types land, we'd make T an associated type, which would force it to be uniquely determined by the Self type.
That restriction is necessary for the coercion algorithm being proposed to work.
This comment has been minimized.
This comment has been minimized.
pnkfelix
reviewed
Sep 16, 2014
| This is a key difference from the | ||
| [cross-borrowing RFC](https://github.com/rust-lang/rfcs/pull/226). | ||
|
|
||
| ### Limit implicitly execution of arbitrary code |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Did any of the examples show an instance of the second bullet's coercion, namely: "From &mut T to &U when T: Deref" ? I ask because that is a case where something that looks like an ownership transfer (of the It could be that the trade off here is in the RFC's favor. I just want to make sure we show an example justifying the second bullet in particular. |
nrc
reviewed
Sep 16, 2014
| ```rust | ||
| let v = vec![0u8, 1, 2]; | ||
| foo(v); // is v moved here? | ||
| bar(v); // is v still available? |
This comment has been minimized.
This comment has been minimized.
nrc
Sep 16, 2014
Member
My basic counter-argument to this is that the compiler tells you exactly this - if this is working code, then you know for sure that v is available in the call to bar so, you don't benefit from having to write &.
This comment has been minimized.
This comment has been minimized.
reem
Oct 29, 2014
I think this is a fair assumption for experienced Rust developers, but this is a large disadvantage for people new to Rust, who will just be extremely confused when two function calls that look like they use v in exactly the same way actually use it completely differently.
nrc
reviewed
Sep 16, 2014
| proposes a more aggressive form of deref coercion: it would allow converting | ||
| e.g. `Box<T>` to `&T` and `Vec<T>` to `&[T]` directly. The advantage is even | ||
| greater convenience: in many cases, even `&` is not necessary. The disadvantage | ||
| is the change to local reasoning about ownership: |
This comment has been minimized.
This comment has been minimized.
nrc
Sep 16, 2014
Member
The primary advantage as I see it is that we continue to respect the level of indirection, we would never implicitly change it, whereas with this proposal we do.
nrc
reviewed
Sep 16, 2014
| fn use_nested(t: Rc<Box<T>>) { | ||
| use_ref(&**t); // what you have to write today | ||
| use_ref(&t); // what you'd be able to write (note: recursive deref) |
This comment has been minimized.
This comment has been minimized.
nrc
Sep 16, 2014
Member
This strikes me as a bit scary - you have to know which types implement Deref to know what type you're going to get.
This comment has been minimized.
This comment has been minimized.
pnkfelix
Sep 16, 2014
Member
Are we expecting things besides smart pointer types to implement Deref? I thought that was the thrust of the argument regarding implicit calls to user defined code.
This comment has been minimized.
This comment has been minimized.
nrc
Sep 16, 2014
Member
I realise that should generally just be 'smart pointers' but looking at what does already, that is not the case, there are also 'smart pointer helpers'. If we add it for Vec/String too, then it will be 'smart pointers' and 'smart pointer-ish things' and 'some collections', which is maybe matches the intuition, but seems a little vague.
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Sep 16, 2014
Contributor
How is this any different from any other cross-borrowing proposal based on Deref? Ah, I suppose because it's willing to do multiple levels of deref?
This comment has been minimized.
This comment has been minimized.
Actually I just remembered: of course there are other cases where passing a Still, adding the requested example would benefit the RFC presentation. |
nrc
reviewed
Sep 16, 2014
| The design satisfies both of the principles laid out in the Motivation: | ||
|
|
||
| * It does not introduce implicit borrows of owned data, since it only applies to | ||
| already-borrowed data. |
This comment has been minimized.
This comment has been minimized.
nrc
reviewed
Sep 16, 2014
| for implicitly running unknown code; together with the expectation that | ||
| programmers are generally aware when they are using `Deref` types, this should | ||
| retain the kind of local reasoning Rust programmers can do about | ||
| function/method invocations today. |
This comment has been minimized.
This comment has been minimized.
nrc
reviewed
Sep 16, 2014
| surrounding `&`, and in particular somewhat muddies the idea that it creates a | ||
| pointer. This change could make Rust more difficult to learn (though note that | ||
| it puts *more* attention on ownership), though it would make it more convenient | ||
| to use in the long run. |
This comment has been minimized.
This comment has been minimized.
nrc
Sep 16, 2014
Member
I'm still not sold on this idea, you are suggesting that the ownership intuition in Rust trumps being explicit about indirection. While I agree that ownership is a very important principal, I feel it comes second to indirection. In a language with explicit memory management (which I think Rust is, even if you don't explicitly call 'free' yourself) I think programmers (beginner or otherwise) have to be extremely concious of indirection and that this is primary to ownership. I fear losing that explicitness in Rust.
I believe it will make programs more convenient to write in the long run, but harder to read, and easier to introduce bugs.
I really like that this proposal doesn't introduce implicit borrows (cf 226). I think that would pay for the extra &s (which I'm otherwise not a fan of). But losing the explicitness around indirection would make me sad.
This comment has been minimized.
This comment has been minimized.
|
@pnkfelix actually, coercing |
This comment has been minimized.
This comment has been minimized.
|
@nick29581 it seems like the key question is whether, indeed, programmers need to be very aware of the levels of indirection. I contend that they do not. In terms of capabilities, there is virtually no difference between a Speaking personally, I find accounting for the precise amount of indirection to be tedious and I don't think it adds much information. It's not a big deal, but converting from However, when we used to have cross-borrowing, I did find that confusing. I remember distinctly being surprised to see vectors that looked like they were being moved, but were in fact being (implicitly) borrowed, and also being surprised that a |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis yes, totally agree it boils down to whether programmers need to be concerned about the level of indirection. I could be persuaded. My experience is mostly from C++ where it is deadly important to know. I agree that at first blush I ignore the I want to believe that we can not worry about pointers and only about ownership, it seems a much more attractive model. But my experience in the past has always been that if I don't know precisely what is going on, there is confusion, and that makes debugging harder. I guess I think of borrowing, deep down, as just a pointer to something, so trying to not think of pointers is difficult for me. I'll try and think only of ownership and borrowing for a while and see if I can warm to the idea of reasoning without pointers :-) |
This comment has been minimized.
This comment has been minimized.
|
On Tue, Sep 16, 2014 at 04:31:35AM -0700, Nick Cameron wrote:
That's interesting. I don't think I've ever had a bug in Rust code The closest example I can come up with is that I have seen errors |
alexcrichton
referenced this pull request
Sep 16, 2014
Closed
Feature request: Automatically convert String to &str when required. #17300
This comment has been minimized.
This comment has been minimized.
|
I am still not decided on whether this is the best approach, but a couple of thoughts if it is:
and so forth. I think this gives similar results to this RFC, but also works for I believe the borrow operator has the following advantages over a cross-borrow-deref coercion:
Does this sound like a sensible alternative or is it silly? If it is the former I can write up an RFC so we have a place to discuss, rather than doing so here. |
aturon
force-pushed the
aturon:deref-coercions
branch
from
aba44ab
to
896e453
Sep 16, 2014
This comment has been minimized.
This comment has been minimized.
I tend to agree; we could drop
Yes, though it depends on what implements
(details elided)
It's an intriguing idea, but seems problematic. Consider cases like the following: fn wants_vec_ref(v: &mut Vec<u8>) { ... }
fn has_vec(v: Vec<u8>) {
wants_vec_ref(&mut v)
}If (Just wanted to jot that down for now -- more later.) |
nrc
assigned
aturon
Sep 16, 2014
aturon
force-pushed the
rust-lang:master
branch
from
4c0bebf
to
b1d1bfd
Sep 16, 2014
This comment has been minimized.
This comment has been minimized.
|
@aturon @nick29581, another alternative would be making coercions explicit, but not too explicit. Some ideas here: Semi-explicit coercion control with |
This comment has been minimized.
This comment has been minimized.
|
On Tue, Sep 16, 2014 at 01:43:23PM -0700, Nick Cameron wrote:
Why does the current RFC not work for Regarding the slice notation, I agree that |
This comment has been minimized.
This comment has been minimized.
Thiez
commented
Jan 12, 2015
|
@Valloric since I oppose this RFC because I don't think having to type |
This comment has been minimized.
This comment has been minimized.
|
I was +0 when I first read this, but since then I’ve repeatedly written code that would have been nicer with it. Big +1. |
This comment has been minimized.
This comment has been minimized.
Valloric
commented
Jan 13, 2015
|
@Thiez Syntax like |
This comment has been minimized.
This comment has been minimized.
Thiez
commented
Jan 14, 2015
|
@Valloric And syntax like If you're going to learn a new language, you have to learn the syntax. That is not a bad thing. And while the syntax certainly shouldn't be made more complex that it needs to be, I don't think making the semantics of |
alexcrichton
referenced this pull request
Jan 14, 2015
Merged
Improve quality of String#to_slice() deprecation message #21157
This comment has been minimized.
This comment has been minimized.
|
+1
|
eddyb
added a commit
to eddyb/rust
that referenced
this pull request
Jan 18, 2015
eddyb
added a commit
to eddyb/rust
that referenced
this pull request
Jan 18, 2015
This comment has been minimized.
This comment has been minimized.
|
+1 |
This comment has been minimized.
This comment has been minimized.
|
There is an implementation now, and there seems to be a lot of positive sentiment for this change, should we push forward with it? @aturon are there any open questions you're aware of? (I haven't re-read the whole conversation here, but I will if we are going to move on to this. But I'm mostly checking you don't have any new concerns which aren't already here). I'm still a little uneasy about the 'searching' aspect of the coercion, but I think it is worth it for the ergonomic benefit. |
This comment has been minimized.
This comment has been minimized.
The |
This comment has been minimized.
This comment has been minimized.
|
Note that this is one reason why the slice syntax |
This comment has been minimized.
This comment has been minimized.
|
Yes, we're ready to move forward with this; this way we can gain some experience before the beta. |
nikomatsakis
merged commit 434552d
into
rust-lang:master
Jan 20, 2015
nikomatsakis
referenced this pull request
Jan 20, 2015
Closed
Tracking issue for deref coercions RFC #21432
This comment has been minimized.
This comment has been minimized.
|
Note: this RFC has now been merged, after some significant digestion on all our parts :-) I won't recap the motivation/arguments here, which are well-represented in the RFC and thread. However, I will note that an implementation is nearly ready to land, and so we should have time to gain some experience here before shipping beta. |
aturon commentedSep 16, 2014
Add the following coercions:
&Tto&UwhenT: Deref<U>.&mut Tto&UwhenT: Deref<U>.&mut Tto&mut UwhenT: DerefMut<U>These coercions eliminate the need for "cross-borrowing" (things like
&**v) and calls toas_slice.Rendered