Change:
prints "5". I am under the impression that should have been moved. complains that has been moved as expected
cc 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 let = x;let = (, ) = ...) Here is an example to explain why I think we want to mean "don't bind this value": Nominating and adding to meeting agenda.
Updated title.
Decided that always run at end of scope. Need implementation.
P-backcompat-lang. (Pretty sure we discussed in a recent mtg.)
We settled on the semantics of meaning "ignore". I think implementing this mostly means removing the special case code in trans to perform a drop.
are you actively working on this? I want to take it.
So this means we want to call the destructor at the end of scope, right? That's what I'd like, but I'm not entirely clear on what the decision was from what's written here.
actually no, in that case represents a temporary, and hence the decision about when it would be freed depends on . The current rules there that I am working are "end of statement". The main change is that if you do (where is an lvalue) then is not freed immediately.
Would there be a drawback to making always behave the same as if you gave it a name?
yes. I described them here:
Ah, I was hoping that was just going to act like without the need to name it.
I am trying to determine from the dialogue here whether the -suggested semantics of having act like represents a third potential semantics, distinct from the two choices you outlined in After considering the example you provided earlier, and rewriting it replacing occurrences of x means "drop this value". (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 let = ...) So if the above is correct, then I take it that if one wants to write with explicit names everywhere, eschewing `` (hypothetical company policy), then you would need to write the above like so: is this consistent with your mental model? (Note that I'm not asserting that ref arg; see aside below.) An aside: The code transformation shown here did make me wonder if one could explain the new ref freshvarref freshvarmap to implicit references. (But then again, it might be closer to what was expecting.)
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.
creating a ref binding is not equivalent to ``, because it creates a new loan which implies restrictions on the value being matched (for example, it could not be moved). it would indeed be convenient for that case, though inconvenient for others. When would drop the temporary actually depends on how we define the lifetimes of temporaries. I could imagine saying that "temporaries that appear inside of initializer expressions are dropped at the end of the block", but it seems potentially rather surprising and is not what I was planning on doing.
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 ``: Drop it Don't bind it Bind it This is what pattern makes it go out of scope and get dropped. This means and are both more-or-less equivalent to: This 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 . This means as a top-level pattern is basically pointless, but in nested patterns it lets you do things you otherwise possibly couldn't do, such as where you bind a reference to the inside of while leaving itself intact. This is what I believe was suggesting, and what I was trying to inquire about as well. Here matching something with is the same as matching it with a name, except that it doesn't actually get a name. This means and are both effectively equivalent to This is pretty nice for RAII, as noted. In this case is not a temporary, and the rules for temporaries are free to behave however they like, they won't apply to it. Personally, I think 3. is the most intuitive behaviour, but 2. might have more practical benefit. In particular, while you can easily use instead of for RAII if 2. is in force, I don't know if there's a way to emulate the behaviour of 2. with nested patterns if 3. is in force. Now that I have a clearer understanding of the tradeoffs, I'm not sure which is better. (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 'most' intuitive, rather it will depend on the context. In any case, there is no equivalent of ("don't bind it") otherwise, and it is an important capability.
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 turn into? What is being bound by here? Does the second component of the pair get moved into the binding and then dropped at the end of the scope? This problem is what made me drop my attempt to present something analogous to your semantics 3. (It could be that would be illegal and one would be forced to write , but, Yuck.) (It could also be that under semantics 3, the ref freshvarbinds by-move or by-ref is context dependent.) I don't know what other options are available under semantics 3.
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 and `` is whether the compiler might give you an unused variable warning). I guess the remaining question is whether people might write expecting it to work, and whether it's a problem.
maybe we'd end up making a lint to flag code like , since under the new semantics for foo(); and should probably be written as such.
that sounds like a good solution. (In case it's not what you already meant, I'd warn on anything, because it doesn't make any more sense for non-temporaries than it does for temporaries.) Edit: If we wanted to be more comprehensive, we could flag any or that doesn't have an effect (so, I suppose, ones which contain no bindings at all): so , , and so forth would also generate warnings.
(recorded as )
and are related
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 trans::base::fn initlocal` I found this: but according to ... 's from over a year ago! So what's up with this?
ping with the landing of , can this be closed?
Not sure, let me check, I forget if I removed the code. Note to -- given the temporary lifetime semantics I ended up with, will run the destructor immediately, but will not, so that could be a handy RAII idiom.
So, the code identified by 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 is removed, we will still_ run the destructor after the statement, just through a different (and more consistent) path in the code.
Just out of curiosity: is the behavior of assigning to/matching against documented anywhere authoritatively? I looked around for a while, but couldn't find anywhere that says what the drop rules are.
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 ) – my findings on stuff: The updated URL for the ^ above ^ (first edition) link is A very nice . I've the line so the code can be : (I decided against including the output here so readers get a chance to think about what the output should be.) From the and
Relevant sections from the current Book of Rust: (also in and ) (also in and ) (also in and ) (also in and )
I got here after realizing and behave differently. Idiomatic Rust guards tend to hand out access from their lock function to ensure locks are held at the type level, and avoid this problem entirely. Here are two ways to do that and make your code safer: your RAII guard to own the data being locked and return it as a smart pointer in : it return a ZST marker that indicates the guard is held, and pass that into any function that needs it. That just means removing the / and having be:

Discussion:
pub fn init_local<'a>(bcx: &'a Block<'a>, local: &ast::Local) -> &'a Block<'a> { <del> debug!("init_local(bcx={}, local.id={:?})", bcx.to_str(), local.id); </del> <ins> debug!("init_local(bcx={}, local.id={:?})", bcx.to_str(), local.id); </ins> let _indenter = indenter(); let _icx = push_ctxt("init_local"); <del> if ignore_lhs(bcx, local) { // Handle let _ = e; just like e; match local.init { Some(ref init) => { return controlflow::trans_stmt_semi(bcx, &**init) } None => { return bcx; } } } </del> _match::store_local(bcx, local) }