]> git.lizzy.rs Git - rust.git/blob - src/test/ui/nll/issue-45696-long-live-borrows-in-boxes.rs
Auto merge of #105145 - Ayush1325:sequential-remote-server, r=Mark-Simulacrum
[rust.git] / src / test / ui / nll / issue-45696-long-live-borrows-in-boxes.rs
1 // rust-lang/rust#45696: This test is checking that we can return
2 // mutable borrows owned by boxes even when the boxes are dropped.
3
4 // run-pass
5
6 // This function shows quite directly what is going on: We have a
7 // reborrow of contents within the box.
8 fn return_borrow_from_dropped_box_1(x: Box<&mut u32>) -> &mut u32 { &mut **x }
9
10 // This function is the way you'll probably see this in practice (the
11 // reborrow is now implicit).
12 fn return_borrow_from_dropped_box_2(x: Box<&mut u32>) -> &mut u32 { *x }
13
14 // For the remaining tests we just add some fields or other
15 // indirection to ensure that the compiler isn't just special-casing
16 // the above `Box<&mut T>` as the only type that would work.
17
18 // Here we add a tuple of indirection between the box and the
19 // reference.
20 type BoxedTup<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>;
21
22 fn return_borrow_of_field_from_dropped_box_1<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
23     &mut *x.0
24 }
25
26 fn return_borrow_of_field_from_dropped_box_2<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
27     x.0
28 }
29
30 fn return_borrow_from_dropped_tupled_box_1<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
31     &mut *(x.0).0
32 }
33
34 fn return_borrow_from_dropped_tupled_box_2<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
35     (x.0).0
36 }
37
38 fn basic_tests() {
39     let mut x = 2;
40     let mut y = 3;
41     let mut z = 4;
42     *return_borrow_from_dropped_box_1(Box::new(&mut x)) += 10;
43     assert_eq!((x, y, z), (12, 3, 4));
44     *return_borrow_from_dropped_box_2(Box::new(&mut x)) += 10;
45     assert_eq!((x, y, z), (22, 3, 4));
46     *return_borrow_of_field_from_dropped_box_1(Box::new((&mut x, &mut y))) += 10;
47     assert_eq!((x, y, z), (32, 3, 4));
48     *return_borrow_of_field_from_dropped_box_2(Box::new((&mut x, &mut y))) += 10;
49     assert_eq!((x, y, z), (42, 3, 4));
50     *return_borrow_from_dropped_tupled_box_1((Box::new((&mut x, &mut y)), &mut z)) += 10;
51     assert_eq!((x, y, z), (52, 3, 4));
52     *return_borrow_from_dropped_tupled_box_2((Box::new((&mut x, &mut y)), &mut z)) += 10;
53     assert_eq!((x, y, z), (62, 3, 4));
54 }
55
56 // These scribbling tests have been transcribed from
57 // issue-45696-scribble-on-boxed-borrow.rs
58 //
59 // In the context of that file, these tests are meant to show cases
60 // that should be *accepted* by the compiler, so here we are actually
61 // checking that the code we get when they are compiled matches our
62 // expectations.
63
64 struct Scribble<'a>(&'a mut u32);
65
66 impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
67
68 // this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
69 // to strictly outlive `'a`
70 fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
71     &mut *s.0
72 }
73
74 // this, by analogy to previous case, is also okay.
75 fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
76     &mut *(*s).0
77 }
78
79 // this, by analogy to previous case, is also okay.
80 fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
81     &mut *(**s).0
82 }
83
84 fn scribbling_tests() {
85     let mut x = 1;
86     {
87         let mut long_lived = Scribble(&mut x);
88         *borrowed_scribble(&mut long_lived) += 10;
89         assert_eq!(*long_lived.0, 11);
90         // (Scribble dtor runs here, after `&mut`-borrow above ends)
91     }
92     assert_eq!(x, 42);
93     x = 1;
94     {
95         let mut long_lived = Scribble(&mut x);
96         *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
97         assert_eq!(*long_lived.0, 11);
98         // (Scribble dtor runs here, after `&mut`-borrow above ends)
99     }
100     assert_eq!(x, 42);
101     x = 1;
102     {
103         let mut long_lived = Scribble(&mut x);
104         *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
105         assert_eq!(*long_lived.0, 11);
106         // (Scribble dtor runs here, after `&mut`-borrow above ends)
107     }
108     assert_eq!(x, 42);
109 }
110
111 fn main() {
112     basic_tests();
113     scribbling_tests();
114 }