]> git.lizzy.rs Git - rust.git/blob - src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs
Rollup merge of #62337 - Mark-Simulacrum:fix-cpu-usage-script, r=alexcrichton
[rust.git] / src / test / ui / issues / 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 // We will explicitly test NLL, and migration modes;
6 // thus we will also skip the automated compare-mode=nll.
7
8 // revisions: nll migrate
9 // ignore-compare-mode-nll
10
11 // This test is going to pass in the migrate revision, because the AST-borrowck
12 // accepted this code in the past (see notes below). So we use `#[rustc_error]`
13 // to keep the outcome as an error in all scenarios, and rely on the stderr
14 // files to show what the actual behavior is. (See rust-lang/rust#49855.)
15 #![feature(rustc_attrs)]
16
17 #![cfg_attr(nll, feature(nll))]
18
19 struct Scribble<'a>(&'a mut u32);
20
21 impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
22
23 // this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
24 // to strictly outlive `'a`
25 fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
26     &mut *s.0
27 }
28
29 // this, by analogy to previous case, is also okay.
30 fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
31     &mut *(*s).0
32 }
33
34 // this, by analogy to previous case, is also okay.
35 fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
36     &mut *(**s).0
37 }
38
39 // this is not okay: in between the time that we take the mutable
40 // borrow and the caller receives it as a return value, the drop of
41 // `s` will scribble on it, violating our aliasing guarantees.
42 //
43 // * (Maybe in the future the two-phase borrows system will be
44 //   extended to support this case. But for now, it is an error in
45 //   NLL, even with two-phase borrows.)
46 //
47 // In any case, the AST-borrowck was not smart enough to know that
48 // this should be an error. (Which is perhaps the essence of why
49 // rust-lang/rust#45696 arose in the first place.)
50 fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
51     &mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
52     //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
53     //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
54     //[migrate]~| WARNING this represents potential undefined behavior in your code
55 }
56
57 // This, by analogy to previous case, is *also* not okay.
58 //
59 // (But again, AST-borrowck was not smart enogh to know that this
60 // should be an error.)
61 fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
62     &mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
63     //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
64     //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
65     //[migrate]~| WARNING this represents potential undefined behavior in your code
66 }
67
68 // This, by analogy to previous case, is *also* not okay.
69 //
70 // (But again, AST-borrowck was not smart enogh to know that this
71 // should be an error.)
72 fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
73     &mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
74     //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
75     //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
76     //[migrate]~| WARNING this represents potential undefined behavior in your code
77 }
78
79 #[rustc_error]
80 fn main() { //[migrate]~ ERROR compilation successful
81     let mut x = 1;
82     {
83         let mut long_lived = Scribble(&mut x);
84         *borrowed_scribble(&mut long_lived) += 10;
85         // (Scribble dtor runs here, after `&mut`-borrow above ends)
86     }
87     {
88         let mut long_lived = Scribble(&mut x);
89         *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
90         // (Scribble dtor runs here, after `&mut`-borrow above ends)
91     }
92     {
93         let mut long_lived = Scribble(&mut x);
94         *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
95         // (Scribble dtor runs here, after `&mut`-borrow above ends)
96     }
97     *scribbled(Scribble(&mut x)) += 10;
98     *boxed_scribbled(Box::new(Scribble(&mut x))) += 10;
99     *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
100 }