]> git.lizzy.rs Git - rust.git/blob - src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs
Auto merge of #54624 - arielb1:evaluate-outlives, r=nikomatsakis
[rust.git] / src / test / ui / issues / issue-45696-long-live-borrows-in-boxes.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // rust-lang/rust#45696: This test is checking that we can return
12 // mutable borrows owned by boxes even when the boxes are dropped.
13 //
14 // We will explicitly test AST-borrowck, NLL, and migration modes;
15 // thus we will also skip the automated compare-mode=nll.
16
17 // revisions: ast nll migrate
18 // ignore-compare-mode-nll
19
20 #![cfg_attr(nll, feature(nll))]
21 //[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
22
23 // run-pass
24
25 // This function shows quite directly what is going on: We have a
26 // reborrow of contents within the box.
27 fn return_borrow_from_dropped_box_1(x: Box<&mut u32>) -> &mut u32 { &mut **x }
28
29 // This function is the way you'll probably see this in practice (the
30 // reborrow is now implicit).
31 fn return_borrow_from_dropped_box_2(x: Box<&mut u32>) -> &mut u32 { *x }
32
33 // For the remaining tests we just add some fields or other
34 // indirection to ensure that the compiler isn't just special-casing
35 // the above `Box<&mut T>` as the only type that would work.
36
37 // Here we add a tuple of indirection between the box and the
38 // reference.
39 type BoxedTup<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>;
40
41 fn return_borrow_of_field_from_dropped_box_1<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
42     &mut *x.0
43 }
44
45 fn return_borrow_of_field_from_dropped_box_2<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
46     x.0
47 }
48
49 fn return_borrow_from_dropped_tupled_box_1<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
50     &mut *(x.0).0
51 }
52
53 fn return_borrow_from_dropped_tupled_box_2<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
54     (x.0).0
55 }
56
57 fn basic_tests() {
58     let mut x = 2;
59     let mut y = 3;
60     let mut z = 4;
61     *return_borrow_from_dropped_box_1(Box::new(&mut x)) += 10;
62     assert_eq!((x, y, z), (12, 3, 4));
63     *return_borrow_from_dropped_box_2(Box::new(&mut x)) += 10;
64     assert_eq!((x, y, z), (22, 3, 4));
65     *return_borrow_of_field_from_dropped_box_1(Box::new((&mut x, &mut y))) += 10;
66     assert_eq!((x, y, z), (32, 3, 4));
67     *return_borrow_of_field_from_dropped_box_2(Box::new((&mut x, &mut y))) += 10;
68     assert_eq!((x, y, z), (42, 3, 4));
69     *return_borrow_from_dropped_tupled_box_1((Box::new((&mut x, &mut y)), &mut z)) += 10;
70     assert_eq!((x, y, z), (52, 3, 4));
71     *return_borrow_from_dropped_tupled_box_2((Box::new((&mut x, &mut y)), &mut z)) += 10;
72     assert_eq!((x, y, z), (62, 3, 4));
73 }
74
75 // These scribbling tests have been transcribed from
76 // issue-45696-scribble-on-boxed-borrow.rs
77 //
78 // In the context of that file, these tests are meant to show cases
79 // that should be *accepted* by the compiler, so here we are actually
80 // checking that the code we get when they are compiled matches our
81 // expectations.
82
83 struct Scribble<'a>(&'a mut u32);
84
85 impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
86
87 // this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
88 // to strictly outlive `'a`
89 fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
90     &mut *s.0
91 }
92
93 // this, by analogy to previous case, is also okay.
94 fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
95     &mut *(*s).0
96 }
97
98 // this, by analogy to previous case, is also okay.
99 fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
100     &mut *(**s).0
101 }
102
103 fn scribbling_tests() {
104     let mut x = 1;
105     {
106         let mut long_lived = Scribble(&mut x);
107         *borrowed_scribble(&mut long_lived) += 10;
108         assert_eq!(*long_lived.0, 11);
109         // (Scribble dtor runs here, after `&mut`-borrow above ends)
110     }
111     assert_eq!(x, 42);
112     x = 1;
113     {
114         let mut long_lived = Scribble(&mut x);
115         *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
116         assert_eq!(*long_lived.0, 11);
117         // (Scribble dtor runs here, after `&mut`-borrow above ends)
118     }
119     assert_eq!(x, 42);
120     x = 1;
121     {
122         let mut long_lived = Scribble(&mut x);
123         *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
124         assert_eq!(*long_lived.0, 11);
125         // (Scribble dtor runs here, after `&mut`-borrow above ends)
126     }
127     assert_eq!(x, 42);
128 }
129
130 fn main() {
131     basic_tests();
132     scribbling_tests();
133 }