// edition:2021 // Test that move closures drop derefs with `capture_disjoint_fields` enabled. #![feature(rustc_attrs)] fn simple_move_closure() { struct S(String); struct T(S); let t = T(S("s".into())); let mut c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: t.0.0 = "new S".into(); //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow //~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue }; c(); } // Test move closure use reborrows when using references fn simple_ref() { let mut s = 10; let ref_s = &mut s; let mut c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: *ref_s += 10; //~^ NOTE: Capturing ref_s[Deref] -> MutBorrow //~| NOTE: Min Capture ref_s[] -> ByValue }; c(); } // Test move closure use reborrows when using references fn struct_contains_ref_to_another_struct_1() { struct S(String); struct T<'a>(&'a mut S); let mut s = S("s".into()); let t = T(&mut s); let mut c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: t.0.0 = "new s".into(); //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow //~| NOTE: Min Capture t[(0, 0)] -> ByValue }; c(); } // Test that we can use reborrows to read data of Copy types // i.e. without truncating derefs fn struct_contains_ref_to_another_struct_2() { struct S(i32); struct T<'a>(&'a S); let s = S(0); let t = T(&s); let mut c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let _t = t.0.0; //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow //~| NOTE: Min Capture t[(0, 0)] -> ByValue }; c(); } // Test that we can use truncate to move out of !Copy types fn struct_contains_ref_to_another_struct_3() { struct S(String); struct T<'a>(&'a S); let s = S("s".into()); let t = T(&s); let mut c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let _t = t.0.0; //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue //~| NOTE: Min Capture t[(0, 0)] -> ByValue }; c(); } // Test that derefs of box are truncated in move closures fn truncate_box_derefs() { struct S(i32); // Content within the box is moved within the closure let b = Box::new(S(10)); let c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let _t = b.0; //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow //~| NOTE: Min Capture b[] -> ByValue }; c(); // Content within the box is used by a shared ref and the box is the root variable let b = Box::new(S(10)); let c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", b.0); //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow //~| NOTE: Min Capture b[] -> ByValue }; c(); // Content within the box is used by a shared ref and the box is not the root variable let b = Box::new(S(10)); let t = (0, b); let c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", t.1.0); //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow //~| NOTE: Min Capture t[(1, 0)] -> ByValue }; } struct Foo { x: i32 } // Ensure that even in move closures, if the data is not owned by the root variable // then we don't truncate the derefs or a ByValue capture, rather do a reborrow fn box_mut_1() { let mut foo = Foo { x: 0 } ; let p_foo = &mut foo; let box_p_foo = Box::new(p_foo); let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 //~| First Pass analysis includes: //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow //~| Min Capture analysis includes: //~| NOTE: Min Capture box_p_foo[] -> ByValue } // Ensure that even in move closures, if the data is not owned by the root variable // then we don't truncate the derefs or a ByValue capture, rather do a reborrow fn box_mut_2() { let foo = Foo { x: 0 } ; let mut box_foo = Box::new(foo); let p_foo = &mut box_foo; let c = #[rustc_capture_analysis] move || p_foo.x += 10; //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 //~| First Pass analysis includes: //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow //~| Min Capture analysis includes: //~| NOTE: Min Capture p_foo[] -> ByValue } // Test that move closures can take ownership of Copy type fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 { let x = 10; let c = #[rustc_capture_analysis] move || x; //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 //~| First Pass analysis includes: //~| NOTE: Capturing x[] -> ImmBorrow //~| Min Capture analysis includes: //~| NOTE: Min Capture x[] -> ByValue c } fn main() { simple_move_closure(); simple_ref(); struct_contains_ref_to_another_struct_1(); struct_contains_ref_to_another_struct_2(); struct_contains_ref_to_another_struct_3(); truncate_box_derefs(); box_mut_2(); box_mut_1(); }