]> git.lizzy.rs Git - rust.git/blob - tests/ui/nll/issue-45696-scribble-on-boxed-borrow.rs
Auto merge of #101138 - Rejyr:diagnostic-migration-rustc-lint-pt2, r=davidtwco
[rust.git] / tests / ui / nll / issue-45696-scribble-on-boxed-borrow.rs
1 // rust-lang/rust#45696: This test is checking that we *cannot* return
2 // mutable borrows that would be scribbled over by destructors before
3 // the return occurs.
4
5 // ignore-compare-mode-polonius
6
7 struct Scribble<'a>(&'a mut u32);
8
9 impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
10
11 // this is okay: The `Scribble` here *has* to strictly outlive `'a`
12 fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
13     &mut *s.0
14 }
15
16 // this, by analogy to previous case, is also okay.
17 fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
18     &mut *(*s).0
19 }
20
21 // this, by analogy to previous case, is also okay.
22 fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
23     &mut *(**s).0
24 }
25
26 // this is not okay: in between the time that we take the mutable
27 // borrow and the caller receives it as a return value, the drop of
28 // `s` will scribble on it, violating our aliasing guarantees.
29 //
30 // * (Maybe in the future the two-phase borrows system will be
31 //   extended to support this case. But for now, it is an error in
32 //   NLL, even with two-phase borrows.)
33 fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
34     &mut *s.0 //~ ERROR borrow may still be in use when destructor runs [E0713]
35 }
36
37 // This, by analogy to previous case, is *also* not okay.
38 fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
39     &mut *(*s).0 //~ ERROR borrow may still be in use when destructor runs [E0713]
40 }
41
42 // This, by analogy to previous case, is *also* not okay.
43 fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
44     &mut *(**s).0 //~ ERROR borrow may still be in use when destructor runs [E0713]
45 }
46
47 fn main() {
48     let mut x = 1;
49     {
50         let mut long_lived = Scribble(&mut x);
51         *borrowed_scribble(&mut long_lived) += 10;
52         // (Scribble dtor runs here, after `&mut`-borrow above ends)
53     }
54     {
55         let mut long_lived = Scribble(&mut x);
56         *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
57         // (Scribble dtor runs here, after `&mut`-borrow above ends)
58     }
59     {
60         let mut long_lived = Scribble(&mut x);
61         *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
62         // (Scribble dtor runs here, after `&mut`-borrow above ends)
63     }
64     *scribbled(Scribble(&mut x)) += 10;
65     *boxed_scribbled(Box::new(Scribble(&mut x))) += 10;
66     *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
67 }