rustc_lint::builtin

Static RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES

pub static RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES: &'static Lint
Expand description

The rust_2021_incompatible_closure_captures lint detects variables that aren’t completely captured in Rust 2021, such that the Drop order of their fields may differ between Rust 2018 and 2021.

It can also detect when a variable implements a trait like Send, but one of its fields does not, and the field is captured by a closure and used with the assumption that said field implements the same trait as the root variable.

§Example of drop reorder

#![deny(rust_2021_incompatible_closure_captures)]

struct FancyInteger(i32);

impl Drop for FancyInteger {
    fn drop(&mut self) {
        println!("Just dropped {}", self.0);
    }
}

struct Point { x: FancyInteger, y: FancyInteger }

fn main() {
  let p = Point { x: FancyInteger(10), y: FancyInteger(20) };

  let c = || {
     let x = p.x;
  };

  c();

  // ... More code ...
}

{{produces}}

§Explanation

In the above example, p.y will be dropped at the end of f instead of with c in Rust 2021.

§Example of auto-trait

#![deny(rust_2021_incompatible_closure_captures)]
use std::thread;

struct Pointer(*mut i32);
unsafe impl Send for Pointer {}

fn main() {
    let mut f = 10;
    let fptr = Pointer(&mut f as *mut i32);
    thread::spawn(move || unsafe {
        *fptr.0 = 20;
    });
}

{{produces}}

§Explanation

In the above example, only fptr.0 is captured in Rust 2021. The field is of type *mut i32, which doesn’t implement Send, making the code invalid as the field cannot be sent between threads safely.