-
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
Warn when a local is "mut" but clearly not mutated #3083
Comments
+1. i'm all for compiler warnings that make folks tighten down their code. |
Would it work similarly to the unused variable detection, where it warns unless you stick an underscore on the front of the identifier? |
I would like to work on this issue but I don't know where to start. Can anyone provide me with some tips? |
The |
I'm not sure how familiar you are with a traditional liveness analysis, but the basic idea is that it tracks when variables may be used again (in which case they are live). Ours is a bit different in that it also tracks when variables may be reassigned in the future. Therefore, it should be possible to check, at the point where a variable is declared, whether it will ever be reassigned. The easiest thing would be to issue a warning for mutable variables which have initializers but are never reassigned (such as the example given in this bug). Such a warning would be issued in check_local(). There is currently a check that says "if there is an initializer and the variable is immutable, ensure it is never assigned again". You could repurpose this to something like "if there is an initializer, and the variable is never reassigned again, warn if it is not immutable" (but of course it should still report the error it does today) You might conceivably also try to issue warnings for variables that are assigned only once in the flow of execution:
as such variables also do not require a mut label. But this is trickier, I'm not sure if we have enough information available to distinguish that case from one like;
That is, each assignment can determine whether there are ever any later assignments and whether the variable is ever used later. But here it seems like we would also need to know whether there have been any prior assignments. So I'd say just warn if there is an initializer and ignore this second case. |
Note: Be sure to add a "compile-fail" test case as described here: https://github.com/mozilla/rust/wiki/Note-testsuite This one is a bit tricky as you'll be detecting a warning, and the test suite likes for such tests to fail, so you'll probably have to add a secondary error. You can check out the test |
It's unfortunately not as easy as just adding another check to check_local(). Variables might need to be mutable not only for re-assignment:
These both result in |
I have little idea of the infrastructure (I had a look at middle/liveness.rs, which didn't help me much), but how difficult would it be to add an e.g. let mut a;
a = 1;
// used_mutably_count(a) == Known(1)
let mut b = 2;
b = 1;
// used_mutably_count(b) == Known(2)
let mut c = ~[];
for vec::each(args) |arg| {
c.push(copy *args);
}
// used_mutably_count(c) == Unknown Then if It could be computed with rules like umc(var, if cond { blk1 } else { blk2 }) = max(umc(var, blk1), umc(var, blk2))
umc(var, { stmt1; stmt2; ... }) = umc(var, stmt1) + umc(var, stmt2) + ...
umc(var, while expr { body }) = if umc(var, body) > Known(0) || umc(var, expr) > Known(0) { Unknown } else { Known(0) }
umc(var, let var = ...;) = Known(1)
umc(var, let var;) = Known(0) where (I guess the count could even be compressed to |
non-critical for 0.6, de-milestoning |
Handle itemized blocks in comments
GC the Stacked Borrows allocation history This handles the biggest contributor to rust-lang/miri#3080 The benchmark that this adds demonstrates the memory improvement here, but our benchmark setup doesn't record memory usage, and `hyperfine` doesn't support emitting memory usage stats. I ran this benchmark manually with `/usr/bin/time -v cargo +miri miri run` 🤷
Instead of turning on the address sanitizer to ensure storage markers (`StorageLive` and `StorageDead`) are kept in MIR, directly disable the MIR pass that removes them from MIR (https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/.E2.9C.94.20Keeping.20MIR's.20storage.20markers). This is to ensure we don't get additional instrumentation that is not relevant for Kani, and may unnecessarily increase the code size and compilation time. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
I think this should warn:
The text was updated successfully, but these errors were encountered: