-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
New lint const_is_empty
#12310
New lint const_is_empty
#12310
Conversation
☔ The latest upstream changes (presumably #12306) made this pull request unmergeable. Please resolve the merge conflicts. |
59ee46c
to
f108599
Compare
Updated to account for the |
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.
The implementation looks good to me. I would like to see a few more tests. Once they are added, we can merge this :D
f108599
to
c94ef81
Compare
Done. I've also added a third commit which uses constant folding to identify more cases, including those involving |
8c03ee1
to
afaf883
Compare
A lintcheck run on the top 500 packages from crates.io reveals one hit in the fn which(tool: &Path, path_entries: Option<OsString>) -> Option<PathBuf> {
fn check_exe(exe: &mut PathBuf) -> bool {
let exe_ext = std::env::consts::EXE_EXTENSION;
exe.exists() || (!exe_ext.is_empty() && exe.set_extension(exe_ext) && exe.exists())
}
[…]
} A |
afaf883
to
1ccb1d5
Compare
☔ The latest upstream changes (presumably #12346) made this pull request unmergeable. Please resolve the merge conflicts. |
1ccb1d5
to
02efec7
Compare
Rebased on |
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.
Thank you for the update and also running this on 500 crates :)
self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| { | ||
let result = mir_to_const(this.lcx, result)?; |
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.
I have the feeling using miri to check if the value is constant can cause annoying false positives. Though, you ran it in 500 crates, and it only generated a single warning, which indicates that this fear might be overly cautions.
I would suggest adding a restriction at this position, to only evaluate the path, if it's a local path, meaning it comes from the same crate. Constant values of dependencies are not always in the control of the user and should therefore be seen as a black box IMO. (Maybe this should be configurable)
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.
I've run lintcheck on the 1000 most popular crates: no new hit compared to the 1 on 500 crates. But you're right, we might want to err on the side of caution, I've added such a check in an additional commit so that you can have a look at it separately. Tell me if it requires stashing, even though the changes are logically separated.
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.
I would guess that the likelihood of a crate using external constants highly depends on the type of crate. Crates.io mainly hosts libraries, they would probably provide such constant values but use them rarly
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.
Yes, except constants such as the path separator, but this is now taken care of, so we get no hit in popular libraries.
@@ -788,6 +834,40 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> | |||
} | |||
} | |||
|
|||
fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<bool> { |
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.
It looks like most is_empty
functions in rustc's std are already static. Could we maybe make our lives easier and throw the whole <recv>.is_empty()
expression into the constant evaluation? That seems easier than this entire thing.
(I haven't worked with const too much, so excuse me, if this suggestion is invalid)
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.
Yes, probably, if those methods were const
they would not trigger a warning but the use of their result might.
Those methods are const
already, it is surprising that the use of their result does not trigger a warning. But as far as I can see, no warning is triggered on this code even for the if true
:
fn main() {
if true {
println!("True");
}
if [0u8; 0].is_empty() {
println!("Is empty");
}
}
02efec7
to
1159e2c
Compare
1c0617b
to
898ed88
Compare
r? @matthiaskrgr |
LGTM, thank you for addressing my comments. The last few weeks have been a bit busy (And I also genuinely needed a break), sorry for delaying the review. Either way, let's get this merged :D @bors r+ |
I can relate, no problem, that's why I requested another reviewer instead of bothering you. |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
This lint detects calls to
.is_empty()
on an entity initialized from a string literal and flag them as suspicious. To avoid triggering on macros called from generated code, it checks that the.is_empty()
receiver, the call itself and the initialization come from the same context.Fixes #12307
changelog: [
const_is_empty
]: new lint