Change:
I tried this code: This does not issue a warning for , however it fails to compile with enabled: I would expect to give a suggestion to add . Found in the 2021 crater run for: I'm uncertain if this is a duplicate of or , they seem very similar, but this case is specific to implementing Drop. : cc <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim

Discussion:
} }; <ins> // This restriction needs to be applied after we have handled adjustments for `move` // closures. We want to make sure any adjustment that might make us move the place into // the closure gets handled. let (place, capture_kind) = restrict_precision_for_drop_types(self, place, capture_kind, usage_span); </ins> capture_info.capture_kind = capture_kind; let capture_info = if let Some(existing) = processed.get(&place) { determine_capture_info(*existing, capture_info) } else {

self.tcx.struct_span_lint_hir( lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_hir_id, <del> closure_head_span, </del> <ins> closure_head_span, </ins> |lint| { let mut diagnostics_builder = lint.build( format!(

self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow); } } <ins> /// Rust doesn't permit moving fields out of a type that implements drop fn restrict_precision_for_drop_types<'a, 'tcx>( fcx: &'a FnCtxt<'a, 'tcx>, mut place: Place<'tcx>, mut curr_mode: ty::UpvarCapture<'tcx>, span: Span, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty(), span); if let (false, UpvarCapture::ByValue(..)) = (is_copy_type, curr_mode) { for i in 0..place.projections.len() { match place.ty_before_projection(i).kind() { ty::Adt(def, _) if def.destructor(fcx.tcx).is_some() => { truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i); break; } _ => {} } } } (place, curr_mode) } </ins> /// Truncate `place` so that an `unsafe` block isn't required to capture it. /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture ///   them completely.

<ins> // edition:2021 #![feature(rustc_attrs)] // Test that we can't move out of struct that impls `Drop`. use std::rc::Rc; // Test that we restrict precision when moving not-`Copy` types, if any of the parent paths // implement `Drop`. This is to ensure that we don't move out of a type that implements Drop. pub fn test1() { struct Foo(Rc<i32>); impl Drop for Foo { fn drop(self: &mut Foo) {} } let f = Foo(Rc::new(1)); let x = #[rustc_capture_analysis] move || { //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> //~| ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{:?}", f.0); //~^ NOTE: Capturing f[(0, 0)] -> ImmBorrow //~| NOTE: Min Capture f[] -> ByValue }; x(); } // Test that we don't restrict precision when moving `Copy` types(i.e. when copying), // even if any of the parent paths implement `Drop`. fn test2() { struct Character { hp: u32, name: String, } impl Drop for Character { fn drop(&mut self) {} } let character = Character { hp: 100, name: format!("A") }; let c = #[rustc_capture_analysis] move || { //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> //~| ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", character.hp) //~^ NOTE: Capturing character[(0, 0)] -> ImmBorrow //~| NOTE: Min Capture character[(0, 0)] -> ByValue }; c(); println!("{}", character.name); } fn main() {} </ins>

<ins> error[E0658]: attributes on expressions are experimental --> $DIR/issue-88476.rs:20:13 | LL |     let x = #[rustc_capture_analysis] move || { |             ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental --> $DIR/issue-88476.rs:47:13 | LL |     let c = #[rustc_capture_analysis] move || { |             ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error: First Pass analysis includes: --> $DIR/issue-88476.rs:20:39 | LL |       let x = #[rustc_capture_analysis] move || { |  _______________________________________^ LL | | LL | | LL | | ...  | LL | | LL | |     }; | |_____^ | note: Capturing f[(0, 0)] -> ImmBorrow --> $DIR/issue-88476.rs:25:26 | LL |         println!("{:?}", f.0); |                          ^^^ error: Min Capture analysis includes: --> $DIR/issue-88476.rs:20:39 | LL |       let x = #[rustc_capture_analysis] move || { |  _______________________________________^ LL | | LL | | LL | | ...  | LL | | LL | |     }; | |_____^ | note: Min Capture f[] -> ByValue --> $DIR/issue-88476.rs:25:26 | LL |         println!("{:?}", f.0); |                          ^^^ error: First Pass analysis includes: --> $DIR/issue-88476.rs:47:39 | LL |       let c = #[rustc_capture_analysis] move || { |  _______________________________________^ LL | | LL | | LL | | ...  | LL | | LL | |     }; | |_____^ | note: Capturing character[(0, 0)] -> ImmBorrow --> $DIR/issue-88476.rs:52:24 | LL |         println!("{}", character.hp) |                        ^^^^^^^^^^^^ error: Min Capture analysis includes: --> $DIR/issue-88476.rs:47:39 | LL |       let c = #[rustc_capture_analysis] move || { |  _______________________________________^ LL | | LL | | LL | | ...  | LL | | LL | |     }; | |_____^ | note: Min Capture character[(0, 0)] -> ByValue --> $DIR/issue-88476.rs:52:24 | LL |         println!("{}", character.hp) |                        ^^^^^^^^^^^^ error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. </ins>

<ins> // check-pass // edition:2021 use std::rc::Rc; // Test that we restrict precision when moving not-`Copy` types, if any of the parent paths // implement `Drop`. This is to ensure that we don't move out of a type that implements Drop. pub fn test1() { struct Foo(Rc<i32>); impl Drop for Foo { fn drop(self: &mut Foo) {} } let f = Foo(Rc::new(1)); let x = move || { println!("{:?}", f.0); }; x(); } // Test that we don't restrict precision when moving `Copy` types(i.e. when copying), // even if any of the parent paths implement `Drop`. pub fn test2() { struct Character { hp: u32, name: String, } impl Drop for Character { fn drop(&mut self) {} } let character = Character { hp: 100, name: format!("A") }; let c = move || { println!("{}", character.hp) }; c(); println!("{}", character.name); } fn main() {} </ins>