-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Drop partially bound function parameters in the expected order #56044
Drop partially bound function parameters in the expected order #56044
Conversation
r? @cramertj (rust_highfive has picked a reviewer for you, use r? to override) |
Given |
Things bound to |
I would have expected |
@bors r+ |
📌 Commit 7dc0dd2 has been approved by |
…mertj Drop partially bound function parameters in the expected order Given the function ```rust fn foo((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {} ``` Prior to 1.12.0 we dropped both `_x` and `_y` before the rest of their respective parameters, since then we dropped `_x` and `_y` after. The original order appears to be the correct order, as the value created later is dropped first, so we revert to that order and add a test for it. While this is technically a breaking change, I can't work out how anyone could be relying on this without making their code very brittle. If this is considered to be too likely to break real world code then I can revert the change and change the test to check for the current order.
💔 Test failed - status-travis |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
…rder, r=cramertj Drop partially bound function parameters in the expected order Given the function ```rust fn foo((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {} ``` Prior to 1.12.0 we dropped both `_x` and `_y` before the rest of their respective parameters, since then we dropped `_x` and `_y` after. The original order appears to be the correct order, as the value created later is dropped first, so we revert to that order and add a test for it. While this is technically a breaking change, I can't work out how anyone could be relying on this without making their code very brittle. If this is considered to be too likely to break real world code then I can revert the change and change the test to check for the current order.
I find the uses of the word "immediately" confusing in the comments above by @Mark-Simulacrum and @RalfJung Can we clarify if that is supposed to mean "immediately" at the end of the execution of |
@pnkfelix I stated my expected semantics as an equivalence with fn foo(PAT: T) { ... }
fn foo(_tmp: T) { let PAT = _tmp; ... } I think this means they should be dropped at the beginning of |
I would expect this: fn foo((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {
// for naming:
// fn foo((a, b): (LogDrop, LogDrop), (c, d): (LogDrop, LogDrop)) {
// variables dropped "immediately," before function runs;
// technically I think c should drop first to preserve "reverse of declaration order"
// c dropped
// b dropped
// function runs
// variables dropped in reverse of declaration order:
// d dropped
// a dropped
} |
These currently have different drop order: playground. This PR makes them have the same drop order. |
} | ||
} | ||
|
||
fn foo((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {} |
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.
Could this test also have the let
version, to explicitly demonstrate that they do the same thing?
Like
fn foo2(_temp1: (LogDrop, LogDrop), _temp2: (LogDrop, LogDrop)) {
let (_x, _) = _temp1;
let (_, _y) = _temp2;
}
Consensus in the lang team meeting was that patterns in the function arguments should work exactly like the equivalent let bindings at the top of the function, in terms of drop order. So, fn foo(a: (LogDrop, LogDrop), b: (LogDrop, LogDrop)) {
let (_x, _) = a;
let (_, _y) = b;
// ...
} |
This comment has been minimized.
This comment has been minimized.
Given the function fn foo((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {} Prior to 1.12 we dropped both `_x` and `_y` before the rest of their respective parameters, since then we dropped `_x` and `_y` after. The original order appears to be the correct order, as the value created later is dropped first, so we revert to that order and add a test for it.
5459338
to
914515f
Compare
ping from triage @cramertj waiting for your review on this |
Sorry for the delayed response-- can you explain how this is different from your current test? fn bindings_with_let(a: (LogDrop, LogDrop), b: (LogDrop, LogDrop)) {
// Drop order in foo is the same as the following bindings.
// _temp2 is declared after _x to avoid a difference between `_: T` and
// `x: T` in function parameters.
let _temp1 = a;
let (_x, _) = _temp1;
let _temp2 = b;
let (_, _y) = _temp2;
} The difference I see is the introduction of |
The difference is that fn foo(a: (LogDrop, LogDrop), b: (LogDrop, LogDrop)) {
let (_x, ) = a;
let (, _y) = b; would be let _temp1 = a;
// _temp2 created before `_x`, so it's dropped after
let _temp2 = b;
let (_x, ) = a;
let (, _y) = b; |
@matthewjasper Thanks for clarifying! I think I was getting confused because in this particular example (where we're destructuring both and the tuple types don't implement The change is whether or not destructuring happens paired with temporary assignment for each argument one-at-a-time, or whether temporary assignment happens first for all arguments, followed by destructuring for all. I think it makes sense to do a full argument-at-a-time so long as this is documented clearly. Thanks for explaining! @bors r+ |
📌 Commit 914515f has been approved by |
⌛ Testing commit 914515f with merge 768ccc6972a8c875e519b95311f5e86c675c45c6... |
💔 Test failed - checks-travis |
Your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem. Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@bors retry |
…rder, r=cramertj Drop partially bound function parameters in the expected order Given the function ```rust fn foo((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {} ``` Prior to 1.12.0 we dropped both `_x` and `_y` before the rest of their respective parameters, since then we dropped `_x` and `_y` after. The original order appears to be the correct order, as the value created later is dropped first, so we revert to that order and add a test for it. While this is technically a breaking change, I can't work out how anyone could be relying on this without making their code very brittle. If this is considered to be too likely to break real world code then I can revert the change and change the test to check for the current order.
Rollup of 8 pull requests Successful merges: - #56044 (Drop partially bound function parameters in the expected order) - #57352 (forbid manually impl'ing one of an object type's marker traits) - #57456 (RawVec doesn't always abort on allocation errors) - #57467 (Implement `check_attribute` to forbid `#[allow_internal_unsafe]`) - #57579 (Add core::iter::once_with()) - #57587 (Add 'rustc-env:RUST_BACKTRACE=0' to const-pat-ice test) - #57608 (Simplify 'product' factorial example) - #57614 ([rustdoc] Fix crates filtering box not being filled) Failed merges: r? @ghost
Given the function
Prior to 1.12.0 we dropped both
_x
and_y
before the rest of theirrespective parameters, since then we dropped
_x
and_y
after. Theoriginal order appears to be the correct order, as the value created
later is dropped first, so we revert to that order and add a test for
it.
While this is technically a breaking change, I can't work out how
anyone could be relying on this without making their code very
brittle. If this is considered to be too likely to break real world code
then I can revert the change and change the test to check for the
current order.