Static rustc_ap_rustc_lint_defs::builtin::DISJOINT_CAPTURE_MIGRATION[][src]

pub static DISJOINT_CAPTURE_MIGRATION: &Lint
Expand description

The disjoint_capture_migration lint detects variables that aren’t completely captured when the feature capture_disjoint_fields is enabled and it affects the Drop order of at least one path starting at this variable. It can also detect when a variable implements a trait, but one of its field 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

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 if the feature capture_disjoint_fields is enabled.

Example of auto-trait

#![deny(disjoint_capture_migration)]
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 fptr.0 is captured when feature capture_disjoint_fields is enabled. The field is of type *mut i32 which doesn’t implement Send, making the code invalid as the field cannot be sent between thread safely.