From a1b8a93f81f4da89eaaa75f27df395f46c17c470 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 30 Jul 2018 16:17:04 +0200 Subject: [PATCH] Expand long-live-borrows-in-boxes test to include simplier illustrative cases. After talking about the PR with eddyb, I decided it was best to try to have some test cases that simplify the problem down to its core, so that people trying to understand what the issue is here will see those core examples first. --- .../issue-45696-long-live-borrows-in-boxes.rs | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/test/ui/issue-45696-long-live-borrows-in-boxes.rs b/src/test/ui/issue-45696-long-live-borrows-in-boxes.rs index e5326bb315e..881f37c2e0b 100644 --- a/src/test/ui/issue-45696-long-live-borrows-in-boxes.rs +++ b/src/test/ui/issue-45696-long-live-borrows-in-boxes.rs @@ -22,24 +22,54 @@ // run-pass -type Boxed<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>; +// This function shows quite directly what is going on: We have a +// reborrow of contents within the box. +fn return_borrow_from_dropped_box_1(x: Box<&mut u32>) -> &mut u32 { &mut **x } -fn return_borrow_from_dropped_box<'a>(x: Boxed<'a, '_>) -> &'a mut u32 { +// This function is the way you'll probably see this in practice (the +// reborrow is now implicit). +fn return_borrow_from_dropped_box_2(x: Box<&mut u32>) -> &mut u32 { *x } + +// For the remaining tests we just add some fields or other +// indirection to ensure that the compiler isn't just special-casing +// the above `Box<&mut T>` as the only type that would work. + +// Here we add a tuple of indirection between the box and the +// reference. +type BoxedTup<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>; + +fn return_borrow_of_field_from_dropped_box_1<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 { &mut *x.0 } -fn return_borrow_from_dropped_tupled_box<'a>(x: (Boxed<'a, '_>, &mut u32)) -> &'a mut u32 { +fn return_borrow_of_field_from_dropped_box_2<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 { + x.0 +} + +fn return_borrow_from_dropped_tupled_box_1<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 { &mut *(x.0).0 } +fn return_borrow_from_dropped_tupled_box_2<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 { + (x.0).0 +} + fn basic_tests() { let mut x = 2; let mut y = 3; let mut z = 4; - *return_borrow_from_dropped_box(Box::new((&mut x, &mut y))) += 10; + *return_borrow_from_dropped_box_1(Box::new(&mut x)) += 10; assert_eq!((x, y, z), (12, 3, 4)); - *return_borrow_from_dropped_tupled_box((Box::new((&mut x, &mut y)), &mut z)) += 10; + *return_borrow_from_dropped_box_2(Box::new(&mut x)) += 10; assert_eq!((x, y, z), (22, 3, 4)); + *return_borrow_of_field_from_dropped_box_1(Box::new((&mut x, &mut y))) += 10; + assert_eq!((x, y, z), (32, 3, 4)); + *return_borrow_of_field_from_dropped_box_2(Box::new((&mut x, &mut y))) += 10; + assert_eq!((x, y, z), (42, 3, 4)); + *return_borrow_from_dropped_tupled_box_1((Box::new((&mut x, &mut y)), &mut z)) += 10; + assert_eq!((x, y, z), (52, 3, 4)); + *return_borrow_from_dropped_tupled_box_2((Box::new((&mut x, &mut y)), &mut z)) += 10; + assert_eq!((x, y, z), (62, 3, 4)); } // These scribbling tests have been transcribed from