new lint that detects blocking operations in async#11578
new lint that detects blocking operations in async#11578J-ZhengLi wants to merge 3 commits intorust-lang:masterfrom
Conversation
|
r? @Jarcho (rustbot has picked a reviewer for you, use r? to override) |
1ccb7d4 to
285d0d7
Compare
|
☔ The latest upstream changes (presumably #11527) made this pull request unmergeable. Please resolve the merge conflicts. |
Jarcho
left a comment
There was a problem hiding this comment.
You can avoid the extra HIR traversals by keeping a stack of bodies and whether that body is async. check_body and check_body_post would maintain the stack and check_expr would be used to detect the calls.
You'll also need to make a distinction between async and maybe async contexts. Closures and nested functions inside an async context might run in an async context, but they may also not.
| impl<'tcx> LateLintPass<'tcx> for UnnecessaryBlockingOps { | ||
| fn check_crate(&mut self, cx: &LateContext<'tcx>) { | ||
| // Avoids processing and storing a long list of paths if this lint was allowed entirely | ||
| if is_lint_allowed(cx, UNNECESSARY_BLOCKING_OPS, CRATE_HIR_ID) { |
There was a problem hiding this comment.
Lints levels can change anywhere.
There was a problem hiding this comment.
@Jarcho Sorry for late response, I was a bit busy dealing with other stuffs.
I'm not sure if I fully understand this phrase:
Closures and nested functions inside an async context might run in an async context, but they may also not.
So, if there's an async function like this
async fn foo() {
fn bar() {
// hehe, sleep!
std::time::sleep(INF)
}
}Then it shouldn't trigger any warning unless the function bar was called in foo later, correct?
There was a problem hiding this comment.
That is correct. Unless the call occurs directly within foo there's no way to know if the function is called in an async context. Something like thread::spawn(|| sleep(10)) or thread::spawn(bar) would be fine since the sleep call doesn't block the current thread.
There was a problem hiding this comment.
That is correct. Unless the call occurs directly within
foothere's no way to know if the function is called in an async context. Something likethread::spawn(|| sleep(10))orthread::spawn(bar)would be fine since thesleepcall doesn't block the current thread.
Ok, I think my code logic already prevent linting on such case, but I'm not sure, I'll add a few test cases tomorrow just in case
Edit: Actually, calling nested function in async function would have FN, so in the above example code, even if the bar gets called in foo, there wouldn't be any warnings... To lint those I'm afraid I have to loop through each body's parent, take note of the function id if there is one, then keep looping the parent to find an upper block and search every expr inside that block until a call to the noted function id is found? And ofc ignore the calls inside thread::spawn, but I got a feeling this whole thing could take a lot of time 🤔
|
☔ The latest upstream changes (presumably #11685) made this pull request unmergeable. Please resolve the merge conflicts. |
95ff7c8 to
0bf6239
Compare
|
☔ The latest upstream changes (presumably #11791) made this pull request unmergeable. Please resolve the merge conflicts. |
976b2a2 to
f26775c
Compare
3c822ed to
24f6dcd
Compare
|
☔ The latest upstream changes (presumably #10283) made this pull request unmergeable. Please resolve the merge conflicts. |
399780b to
6ac03a4
Compare
| "std::io::copy", | ||
| "std::io::read_to_string", |
There was a problem hiding this comment.
These are only blocking if the underlying reader or writer are blocking. For example, copying between Vecs or reading from a Vec into a string isn't blocking in practice.
There was a problem hiding this comment.
...only blocking if the underlying reader or writer are blocking.
That's interesting, can you further explain this?
Initially, I list those methods purely base on the observation from the tokio crate, since there are AsyncRead and AsyncWrite in the crate, I assume the Read and Write traits from std::io are blocking 😄 , but now that you mention it, I wonder if copying between slices would actually affect anything.
|
☔ The latest upstream changes (presumably #12144) made this pull request unmergeable. Please resolve the merge conflicts. |
|
Hey @Jarcho, this is a ping from triage. Can you give this PR a review? It's totally fine if you don't have the time right now, you can reassign the PR to a random team member using @J-ZhengLi could you rebase on master again? Since only @rustbot ready |
b1914c3 to
3194a51
Compare
yeah sure, I forgot about this one, still feel very unconfident about this one, running |
f90251e to
607ab6b
Compare
|
I believe none of the lints in lintcheck use async extensively, but I could be wrong. |
|
☔ The latest upstream changes (presumably #12635) made this pull request unmergeable. Please resolve the merge conflicts. |
|
Hey, this is a ping from triage. @Jarcho can you give this PR a review? It's totally fine if you don't have the time right now, you can reassign the PR to a random team member using @J-ZhengLi Sorry for the wait, could you rebase this PR? @rustbot ready |
|
Looking at current implementation, combining with the other issue #4377, I kinda want to close this and maybe re-work on it later 🤔 |
fixes: #10794
changelog: new lint [
unnecessary_blocking_ops]Ok, this is a rough one, I have no confident in many things (the name ofc), and there are certain things I wanna address before I put too much effort in it.