-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Fix semantics of let _ = ...
not to drop
#10488
Comments
cc @nikomatsakis, this is surprising! |
that seems broken indeed. cc me. |
Actually, thinking harder on this, I'm not sure it's broken. It depends on what we want the semantics of Here is an example to explain why I think we want
Nominating and adding to meeting agenda. |
Updated title. |
Decided that |
P-backcompat-lang. (Pretty sure we discussed in a recent mtg.) |
We settled on the semantics of |
@nikomatsakis are you actively working on this? I want to take it. |
@nikomatsakis: So this means we want |
@thestinger actually no, in that case |
Would there be a drawback to making |
@glehel yes. I described them here: #10488 (comment) |
@nikomatsakis: Ah, I was hoping that |
@nikomatsakis: I am trying to determine from the dialogue here whether the @thestinger -suggested semantics of having After considering the example you provided earlier, and rewriting it replacing occurrences of fn some_func(pair: (~Foo, ~Bar)) {
{
let (ref x, _arg) = pair; // It sounds like this moves ~Bar into _arg ...
...
// ... which means we drop ~Bar here ...
}
{
let (_, ref y) = pair; // ... and thus makes this illegal
}
} (Update: after I wrote this I remembered that you cannot have a by-move and by-ref binding in the same pattern, so the above code couldn't work anyway. It seems like our current semantics must be inferring whether to treat So if the above is correct, then I take it that if one wants to write with explicit names everywhere, eschewing fn some_func(pair: (~Foo, ~Bar)) {
{
let (ref x, ref _arg) = pair; // do not move ~Bar ...
...
}
{
let (ref _ign, ref y) = pair; // ... and thus this is fine.
}
} @nikomatsakis is this consistent with your mental model? (Note that I'm not asserting that An aside: The code transformation shown here did make me wonder if one could explain the new |
I think what I expected it to do is probably not a great idea, but is useful in a world of RAII locks and such. |
@pnkfelix creating a ref binding is not equivalent to @thestinger it would indeed be convenient for that case, though inconvenient for others. When |
I think I now understand the situation here better, and want to summarize it in case it's helpful (and so people can correct me if I'm wrong). There are actually *3* options for the meaning of
1. Drop itThis is what
and
are both more-or-less equivalent to:
2. Don't bind itThis is the new meaning. It means: leave the RHS alone, do nothing at all with it. In this case,
is equivalent to
so indeed, its lifetime is governed by the rules for temporaries, while
is equivalent to just
in other words, it leaves the RHS alone and does not move out of 3. Bind itThis is what I believe @thestinger was suggesting, and what I was trying to inquire about as well. Here matching something with
and
are both effectively equivalent to
This is pretty nice for RAII, as noted. In this case ConclusionPersonally, I think 3. is the most intuitive behaviour, but 2. might have more practical benefit. In particular, while you can easily use (jsyk: global online-identity renaming, used to be glehel) |
On Wed, Dec 18, 2013 at 12:55:19PM -0800, Gábor Lehel wrote:
This sounds like an accurate summary. I don't think any option is the |
@glaebhoerl my comment above originally started out as an analysis like yours; the spot where I got stuck was when I tried to translate niko's example, but using your third semantics ("Bind it"). Namely, in your semantics 3., what does
I don't know what other options are available under semantics 3. |
@pnkfelix Ah, I understand now. I guess that yes,
would be the logical consequence of 3. That does make 2. look even moreso like the most practical option, even if it doesn't have the meaning that I would naively expect (but maybe that's because I'm coming from Haskell, where the only difference between I guess the remaining question is whether people might write |
@glaebhoerl maybe we'd end up making a lint to flag code like |
@pnkfelix that sounds like a good solution. (In case it's not what you already meant, I'd warn on Edit: If we wanted to be more comprehensive, we could flag any |
(recorded as #11088) |
…lly do anything (irrefutable, no bindings). Will be useful once the semantics of _ in patterns changes to "ignore" instead of "drop" (rust-lang#10488). Closes rust-lang#11088.
Is this done already? I was looking into doing it, but didn't find what would need to be changed. Then I tried a few tests, and everything's behaving as if
but according to
...that's from over a year ago! So what's up with this? |
ping @nikomatsakis, with the landing of #11585, can this be closed? |
Not sure, let me check, I forget if I removed the code. Note to @thestinger -- given the temporary lifetime semantics I ended up with, |
So, the code identified by @glaebhoerl is still there and should be removed, but I think the code actually behaves the right way nonetheless. i.e., once the special case for |
This code didn't do anything, but was a vestige of the old semantics for `let _ = ...`. Closes rust-lang#10488. (As near as I can tell anyhow.)
This code didn't do anything, but was a vestige of the old semantics for `let _ = ...`. Closes #10488. (As near as I can tell anyhow.) r? @nikomatsakis
Just out of curiosity: is the behavior of assigning to/matching against |
I think this is a very good quote, so I'll repeat it here and below:
For others like me who found their way here using G**gles (in my case via rust let underscore) – my findings on Book linkThe updated URL for the ^ above ^ (first edition) link is https://doc.rust-lang.org/stable/book/first-edition/patterns.html#ignoring-bindings. ExampleA very nice example can be found on users.rust-lang.org. I've added the struct D(i32);
impl Drop for D {
fn drop(&mut self) { println!("dropped {}", self.0); }
}
fn main() {
#![allow(path_statements, unused_variables)]
{
D(0);
let x = D(1);
let _ = D(2);
D(3);
let y = D(4);
let _ = D(5);
}
{
let var = D(0);
let _ = var;
var;
D(1);
}
} (I decided against including the output here so readers get a chance to think about what the output should be.) QuotesFrom the book and #40096 (comment):
// Here, the String created will be dropped immediately, as it’s not bound:
let _ = String::from(" hello ").trim();
|
Relevant sections from the current Book of Rust:
|
I got here after realizing
pub struct FooGuard(Foo);
impl FooGuard {
fn lock(&self) -> HeldFooLock { // do lock code }
}
pub struct HeldFooLock<'a>(&'a mut Foo);
impl Deref for HeldFooLock<'_> {
type Target = Foo;
fn deref(&self) -> &Foo { &self.0 }
}
impl DerefMut for HeldFooLock<'_> {
fn deref_mut(&mut self) -> &mut Foo { &mut self.0 }
}
impl Drop for HeldFooLock<'_> {
fn drop(&mut self) { // do unlock code }
}
// This struct can only be directly constructed in this module because of the private `()` field
pub struct HeldFooLock(());
impl Drop for HeldFooLock { ... }
impl FooGuard {
fn lock(&self) -> HeldFooLock {
// Do lock code;
HeldFooLock(())
}
}
pub fn do_operation_that_requires_guard(guard: &HeldFooLock) {} |
…t_type, r=Manishearth `collection_is_never_read`: Handle unit type changelog: [`collection_is_never_read`]: Fix false negative fixes: rust-lang#10488
prints "5". I am under the impression that
x
should have been moved.complains that
x
has been moved as expectedThe text was updated successfully, but these errors were encountered: