-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Duplicating mut Copy variables doesn't warn or error #73467
Comments
Looks like this is already a warning in 1.45.0-beta2 (and nightly ofc)
|
Closing as fixed |
I actually think this should be reopened. Here's a slight variation that gives no warning on nightly: fn main() {
let mut x = 0;
let closure = move || {
let mut closure2 = move || {
x += 1;
x
};
closure2();
println!("{}", x);
};
closure();
} Since |
Two years passed and this issue is still without any attention. rustc 1.67.0 (fc594f1 2023-01-24) let mut a = 1;
for _ in 0..10 {
tokio::spawn(async move {
a += 1;
if a > 3 {
// this will never reached
}
})
.await
.unwrap();
} UPD: Edited to more realistic example |
I've also myself managed to hit this issue while trying to hurriedly set up a closure producing diagnostic output ("how many times did this event happen" or similar) in addition to its existing behavior. |
@kpreid Yeah, I found the real bug today too. It had to be an archiver which slices zips to 512 Mb each, but it didn't. And it took some time to realize that count the zip size in mut usize which increments in spawn_blocking was not the best idea. |
A simpler example from my recent code: let mut i = 0;
let mut f = move || {
i += 1;
i
};
println!("{}", f());
println!("{}", i); Which formerly was #[tokio::main(flavor = "current_thread")]
async fn main() {
let mut i = 0;
let n = 5;
let futures = (0..n).map(|_| async move {
// some dozens of lines of code here
i += 1;
println!("Done {} out of {}", i, n);
});
for f in futures {
f.await;
}
} The thing is that counter didn't exist in the fist place - it was just bunch of futures with their own work. So I added a counter - and while it stroke me a little bit "why does it compile? Don't I need some kind of synchronization" I immediately thought "well I'm running on a current-thread executor, so it figured out I don't need synchronization and regular reference is enough, since compiler is happy then it most definitely should be valid". And it's easy to imagine I was very wrong about that. I agree that I was tired and probably should have looked better, but in the end I really think that compiler should warn about such issues, C# compiler does just this in a very similar situation. I think this is the best approach and doesn't harm anyone - rust always has been about explicitness so I think this is a great place to apply it. |
This came up on URLO again. I think what the compiler should do is warn when, for some binding
Note that these rules don’t mention |
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=6dee1348129e0c1938c67eb66a8f62b0
The inner closure essentially forks the mutable variable
x
into two variables. I would expect rustc to give a warning or error, but there is no warning or error. I understand the logic behind allowing this but I think it can lead to surprising results. rust-analyzer warns that assignment tox
inclosure2
is never read. This led me to a real bug in our code.Seems to me that duplicating a
mut
Copy
variable like this deserves some kind of warning at least.The text was updated successfully, but these errors were encountered: