-
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
lint against unexpectedly late drop for temporaries in match scrutinee expressions #93883
Comments
This is a duplicate of #37612 - but I am not inclined to immediately close, since the ideas here might cause more progress. But I do want to stress that this is an ancient issue. rust-lang/rfcs#210 describes not just the problem (surprising semantics around releasing lock guards - though the culrpit in that RFC is different from what's implemented today), but offers a solution ( The sad thing is that there really hasn't been much (any?) progress around that kind of categorization, even if it could've come in handy in more than one way (e.g. a semantic (A quick search finds some newer mentions of |
Related clippy issue: rust-lang/rust-clippy#1904 |
I'm relatively new to rust, but after reading the fasterthanlime blog post about this and the related issues, I'd be interested in taking a swing at it, assuming no one else has already claimed it. Would that be okay? |
Yes! So we've set up some procedure for this to make sure other ppl will know you are working on it. Just write On the implementation side there are a few ways to go about it, but you'll likely have the best experience by implementing it in clippy first (going from editing your lint to seeing it in action on a test is quicker in the clippy repo). Generic instructions to get you started are in https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md I do recommend using https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md#author-lint to get a picture of how some tests that you come up with look like (tho I am biased, as I initiated the author lint xD). In any case, you'll want to stay simple, so I recommend ignoring the actual match arms for now and only concentrating on the situation where the match scrutinee type has no lifetimes other than |
Thank you for the detailed suggestions! It’s very helpful! |
@rustbot claim |
Cool! I'd love to see this get fixed. I would say that -- implementation wise at least -- we should do it with an attribute placed on the type, analogous to |
@nikomatsakis Do you mean that mutexes would need the attribute to trigger the lint or as a solution outside the lint? |
We already have a similar attribute (at least in theory) for the RFC 2229 work, right? That's obviously perma-unstable under that name, but we could consider a stable version of it. |
@PrestonFrom I mean that the lint would not hard-code particular types, but we would annotate the "guard" types with the attribute. And yes, @Mark-Simulacrum is right that |
@nikomatsakis Thank you -- to make sure I am correctly following your suggestion:
I think this makes sense -- I wish there were a way to write the lint so that it wouldn't require an "opt-in", but this seems like a good approach to avoid false positives. |
Hmm, I'm unclear on why the lifetime of the scrutinee is significant. I was expecting to just look for cases where a drop is executing and the type being dropped has this flag. (We probably do want to discuss whether to "traverse" the type, e.g., to detect things like a Really this problem is larger than |
@nikomatsakis This might be confusion on my part. I thought we'd want to look at the lifetime because it would indicate that the object's lifetime was being extended (and thank you for mentioning the Maybe instead of checking the lifetime, it should check that the object is not a ref? |
The reason I mentioned that we should only lint if If we want to target just lock guards and similar, the plan with an extra attribute (or simply an auto trait?) sgtm. It won't immediately work for lock guard types outside of libstd, but that's ok, we can figure out how to allow crates to register themselves for the lint later. If we want to look into things like
that's the thing, there is no extension happening that is based on types or such, this also happens when the scrutinee type is |
@oli-obk Thank you so much for the clarification! I think I understand this better now. An auto trait sounds like it might be a good way to go -- I will look at that vs an attribute |
Create clippy lint against unexpectedly late drop for temporaries in match scrutinee expressions A new clippy lint for issue 93883 (rust-lang#93883). Relies on a new trait in `marker` (called `SignificantDrop` to enable linting), which is why this PR is for the rust-lang repo and not the clippy repo. changelog: new lint [`significant_drop_in_scrutinee`]
That's because you're exploring new territory for which we don't have procedures yet. A clippy PR against the rustc repo is just one of them. We'll need to debrief with @flip1995 to figure out whether we need to change/improve some things there. Then we can write some docs so other people will have some guidance in the future. About moving the lint to rustc: Here's a PR where we did this previousy: #75671 Reading through it, a few things come to mind:
you can do 4. in the clippy repo first if you'd like, then the uplifting PR itself will only be about the uplift. |
Usually lints that are uplifted from Clippy to rustc were in Clippy for a long time and therefore got tested on real world code. Also they were mostly deny-by-default IIRC or at the very least warn-by-default in Clippy. This lint is currently in
I suggest that all modifications and bug fixes to the lint are now done in the Clippy repo. You can If you manage to submit the PR moving this lint to the As for the uplifting process:
We now mark uplifted lints as "register_renamed", so that the new rustc lint name gets suggested when the old Clippy lint name is found in the code.
In general it doesn't have to be warn-by-default, it could also be allow-by-default. This should probably be decided in the MCP. For this lint warn-by-default sounds right though. (On the other hand does uplifting a lint to an allow-by-default rustc lint even make sense?) |
nope :) I meant more like, even if clippy has it in deny-by-default, we should move it to warn-by-default in rustc |
Thank you both for the overview of next steps! I'll try to get step 4 done this week in the Clippy repo! |
Create clippy lint against unexpectedly late drop for temporaries in match scrutinee expressions A new clippy lint for issue 93883 (rust-lang/rust#93883). Relies on a new trait in `marker` (called `SignificantDrop` to enable linting), which is why this PR is for the rust-lang repo and not the clippy repo. changelog: new lint [`significant_drop_in_scrutinee`]
* Fix significant drop in match scrutinee rust-lang/rust#93883 * Fix deref immutable value * Fix explicit 0 index when first() would do Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
* Fix significant drop in match scrutinee rust-lang/rust#93883 * Fix deref immutable value * Fix explicit 0 index when first() would do Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
@oli-obk The PR adding more context (rust-lang/rust-clippy#8981) was merged into clippy last week. Is this what you were looking for in terms of adding context or would you like more added? |
This looks really great now! Thank you |
@oli-obk Great! Is the next step moving uplifting or is this a good time to pause and wait for feedback from the community on how useful/confusing the lint is? |
I'd suggest to wait for a release cycle to get feedback on the lint. |
That makes sense! To make sure I don’t forget to come back to this, Would that mean waiting until 1.63 or 1.64? Or am I misunderstanding what a release cycle is? |
The current nightly is 1.64, see https://forge.rust-lang.org/#current-release-versions This would mean to wait until the current nightly is 1.65, which on 2022-08-11 |
However you can start with the uplifting work a bit earlier, so that the uplifted lint will get into 1.65 right away. |
Thank you for the explanation! |
Create clippy lint against unexpectedly late drop for temporaries in match scrutinee expressions A new clippy lint for issue 93883 (rust-lang/rust#93883). Relies on a new trait in `marker` (called `SignificantDrop` to enable linting), which is why this PR is for the rust-lang repo and not the clippy repo. changelog: new lint [`significant_drop_in_scrutinee`]
This lint saved my hide and helped me identify and correct a longstanding issue. Thank you for this lint. I feel like this lint should be elevated or even be made into a compiler warning/error. Unexpected deadlocks arguably undermine rust's claims of safety and fearless concurrency, especially for something so seemingly innocuous as a |
Agreed with @leontoeides. I just ran into this footgun, and I was surprised that rustc and clippy didn't seem to have anything for it. For other folks like me finding this thread late, the lint that @PrestonFrom added is https://rust-lang.github.io/rust-clippy/master/index.html#/significant_drop_in_scrutinee, and it's currently disabled by default. You can try it with something like this:
In my specific case I'm retaking the same lock behind a function call, and I'm especially happy that the lint still fires for me. (For reference here's my corrected code, with comments about how |
Hi, Sorry, this is on me. Having a second kid really sucked up free time. I'm not sure what needs to be done to get it enabled by default but I'll look into it and get it moving again. |
Wow that was a lightning fast response :-D If you'd rather someone else take the ball, please let me know! I've been meaning to learn more about how Clippy works anyway :) |
I'd like to finish it since I started it, and I'm getting some free time, but if it looks doubtful, I'll ping you here! I appreciate the offer very much though. |
A good starting point to see what needs to be addressed is the PR moving the lint to Running |
@oconnor663 I thought I would have more time to work on this but I haven't yet. If you wanted to take over, I would be happy to step aside. Otherwise, I'm hoping to have more time in a few months. |
This came up recently on twitter: https://twitter.com/fasterthanlime/status/1491803585385877519
Where @fasterthanlime ran into an unexpected difference in behavior that caused a deadlock.
The following code works fine:
But when the mutex locking expression is inlined into the match scrutinee expression it causes deadlock:
Link to playgrounds
This deadlock occurs because temporaries created in a match scrutinee automatically have their lifetime extended for the duration of the match expression. This is done to allow match arms to borrow from the scrutinee expressions, but this surprised many of the users in the above twitter thread because
foo
returns a bool, so there is no borrow taken by any of the match arms. My understanding is that the current behavior was chosen because otherwise drop timing of match temporaries would depend on whether or not you create any borrows.This issue has generated some discussion around the possibility of changing drop rules in an edition to more aggressively drop temporaries. In this issue I would like to avoid a discussion of that size and instead propose that we introduce a lint that warns when one could encounter potentially surprising drop behaviour. @oli-obk has volunteered to mentor this issue. He suggested that we produce a warning when a temporary with a Drop impl which isn't borrowed by any match arms has its lifetime extended.
The text was updated successfully, but these errors were encountered: