-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Allow implicit coercions for cross-borrows. #226
Conversation
Wherever a type implements `Deref<T>`, allow an implicit coercion to `&T`. Removes the need for most occurrences of `&*`.
I've been a big fan of this idea in the past. I'm not as much of a fan today, primarily because it makes it slightly harder to figure out whether a given expression is a move/copy or a cross-borrow, but I think I still fall in the 👍 camp. I'm also in favor of implementing For what it's worth, we already have some inconsistency in moves vs borrows with macros. I can say let s: String = foo();
println!("{}", s); // note: bare `s`
consume_string(s); But I can't say let s: String = foo();
io::println(s); // bare `s` again, this time it's moved
consume_string(s); This RFC coupled with a |
This also seems related to rust-lang/rust#13910, which needs an RFC (extending support for |
FWIW, UFCS provides an argument in favor of more drastic auto-borrowing, because if any type That said, I think it's still appropriate to stick with just cross-borrowing. Full auto-borrowing just seems potentially too problematic. |
&e | &e | ||
&*e | e | ||
&**e | *e | ||
&&**e | &*e |
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 don't understand how this can work?
It seems let x = &&**e;
is equivalent to the following today:
let tmp = e.deref().deref();
let x = &tmp;
while the latter seems like it should just be e.deref()
(as &*e
is now)? Or is there some deep coercions going on here, if so, that doesn't seem like it's backwards compatible, particularly, since &*e
could mean two different things.
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 might be wrong actually. I was imagining *e
would happen first, then we would implicitly coerce to &**e
and finally the explicit &
would give &&**e
. If we allow coercions at &e
but not at *e
, then I think there is no ambiguity. This distinction does seem a bit ad-hoc though (it follows where we have an expected type in the type checker at the moment). I have another RFC which goes in to depth on sites for coercions, for this RFC I'm just kind of assuming that is nailed down elsewhere.
Sounds good, my only reservation is that being able to write Maybe deep cross-borrowing wouldn't be so bad? |
6357402
to
e0acdf4
Compare
I've posted an alternative design that achieves similar goals but is somewhat more conservative: it only allows coercions on already-borrowed data, and thereby does not introduce new borrows implicitly. The RFC gives detail about the downsided of implicit borrowing. |
Change the address-of operator (`&`) to a borrow operator. This is an alternative to rust-lang#241 and rust-lang#226 (cross-borrowing coercions). The borrow operator would perform as many dereferences as possible and then take the address of the result. The result of `&expr` would always have type `&T` where `T` does not implement `Deref`.
Some data and a little discussion: https://gist.github.com/nick29581/809614adb2bbb38232b7 |
Closed in favour of #241 or something like that (that idea is superior because it better respects the borrowing/ownership principles of Rust and substitutability). |
Named Blocks
Wherever a type implements
Deref<T>
, allow an implicit coercion to&T
. Removes the need for most occurrences of&*
.