Fix 2021: why I need `let _ = &obj;`

I run cargo fix --edition to migrate from edition 2018 to 2021,
and got "fix" bellow. Why I need it?
Code compiled perfectly fine without it.

     fn test_foo_send() {
         let foo = Foo::create_empty();
         std::thread::spawn(move || {
+            let _ = &foo;
             println!("callback_tag: {}", foo.callback_tag);
         })
         .join()

This is because the capturing behavior of closures was changed. In the 2021 edition, closures can capture individual fields of objects (in this case, foo.callback_tag), while they previously could not. Mentioning foo in the closure restores the old behavior by making the closure capture the whole foo variable.

If your code works fine without that, then it should be fine to remove it, but the new behavior can lead to destructors being run at a different point than they used to, so keep an eye out for that.

9 Likes

Excuse me, what is "... cargo fix --edition to migrate from edition 2018 to 2021,..."

What about me?
cargo --version
cargo 1.60.0 (d1fd9fe2c 2022-03-01)
rustc --version
rustc 1.60.0 (7737e0b5c 2022-04-04)

Check out the edition guide, it explains how to do it: Transitioning an existing project to a new edition - The Edition Guide

2 Likes

Beyond destructors, one thing that can be influenced by the new behavior is Send bounds (and the same applies to Sync, Clone, or Copy bounds).

Thte thread::spawn call requires the closure to be Send, and a closure is Send if (and only if) all the captured values/variables are Send. By the changes in how capturing works in 2021 edition, only the foo.callback_tag field might be captured instead of the whole foo, with the effect that the Sendness of the closure then depends on whether the type of Foo’s callback_tag field has a Send type, instead of on whether the type Foo itself implements Send.

For more details, check whether the warning itself (as e.g. displayed by running cargo rustc --profile check -- -W rust-2021-incompatible-closure-captures) gives more information about your concrete use case.

2 Likes

You don't need it, and in 99% of cases it's not needed at all.

Capturing behavior has subtly changed in edition 2021, and cargo fix is being very very careful not to break anyone's code, and puts this line in old code just in case it relied on the previous behavior.

3 Likes