Skip to content

Commit 08b3a8e

Browse files
committed
Regression tests.
1 parent 88284ba commit 08b3a8e

5 files changed

+344
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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+
type Boxed<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>;
26+
27+
fn return_borrow_from_dropped_box<'a>(x: Boxed<'a, '_>) -> &'a mut u32 {
28+
&mut *x.0
29+
}
30+
31+
fn return_borrow_from_dropped_tupled_box<'a>(x: (Boxed<'a, '_>, &mut u32)) -> &'a mut u32 {
32+
&mut *(x.0).0
33+
}
34+
35+
fn basic_tests() {
36+
let mut x = 2;
37+
let mut y = 3;
38+
let mut z = 4;
39+
*return_borrow_from_dropped_box(Box::new((&mut x, &mut y))) += 10;
40+
assert_eq!((x, y, z), (12, 3, 4));
41+
*return_borrow_from_dropped_tupled_box((Box::new((&mut x, &mut y)), &mut z)) += 10;
42+
assert_eq!((x, y, z), (22, 3, 4));
43+
}
44+
45+
// These scribbling tests have been transcribed from
46+
// issue-45696-scribble-on-boxed-borrow.rs
47+
//
48+
// In the context of that file, these tests are meant to show cases
49+
// that should be *accepted* by the compiler, so here we are actually
50+
// checking that the code we get when they are compiled matches our
51+
// expectations.
52+
53+
struct Scribble<'a>(&'a mut u32);
54+
55+
impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
56+
57+
// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
58+
// to strictly outlive `'a`
59+
fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
60+
&mut *s.0
61+
}
62+
63+
// this, by analogy to previous case, is also okay.
64+
fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
65+
&mut *(*s).0
66+
}
67+
68+
// this, by analogy to previous case, is also okay.
69+
fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
70+
&mut *(**s).0
71+
}
72+
73+
fn scribbling_tests() {
74+
let mut x = 1;
75+
{
76+
let mut long_lived = Scribble(&mut x);
77+
*borrowed_scribble(&mut long_lived) += 10;
78+
assert_eq!(*long_lived.0, 11);
79+
// (Scribble dtor runs here, after `&mut`-borrow above ends)
80+
}
81+
assert_eq!(x, 42);
82+
x = 1;
83+
{
84+
let mut long_lived = Scribble(&mut x);
85+
*boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
86+
assert_eq!(*long_lived.0, 11);
87+
// (Scribble dtor runs here, after `&mut`-borrow above ends)
88+
}
89+
assert_eq!(x, 42);
90+
x = 1;
91+
{
92+
let mut long_lived = Scribble(&mut x);
93+
*boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
94+
assert_eq!(*long_lived.0, 11);
95+
// (Scribble dtor runs here, after `&mut`-borrow above ends)
96+
}
97+
assert_eq!(x, 42);
98+
}
99+
100+
fn main() {
101+
basic_tests();
102+
scribbling_tests();
103+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: compilation successful
2+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1
3+
|
4+
LL | / fn main() { //[ast]~ ERROR compilation successful
5+
LL | | //[migrate]~^ ERROR compilation successful
6+
LL | | let mut x = 1;
7+
LL | | {
8+
... |
9+
LL | | *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
10+
LL | | }
11+
| |_^
12+
13+
error: aborting due to previous error
14+
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
warning[E0597]: `*s.0` does not live long enough
2+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:63:5
3+
|
4+
LL | &mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
5+
| ^^^^^^^^^ borrowed value does not live long enough
6+
...
7+
LL | }
8+
| - `*s.0` dropped here while still borrowed
9+
|
10+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 62:14...
11+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:14
12+
|
13+
LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
14+
| ^^
15+
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
16+
It represents potential unsoundness in your code.
17+
This warning will become a hard error in the future.
18+
19+
warning[E0597]: `*s.0` does not live long enough
20+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
21+
|
22+
LL | &mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
23+
| ^^^^^^^^^^^^ borrowed value does not live long enough
24+
...
25+
LL | }
26+
| - `*s.0` dropped here while still borrowed
27+
|
28+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 72:20...
29+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:72:20
30+
|
31+
LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
32+
| ^^
33+
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
34+
It represents potential unsoundness in your code.
35+
This warning will become a hard error in the future.
36+
37+
warning[E0597]: `*s.0` does not live long enough
38+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5
39+
|
40+
LL | &mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
41+
| ^^^^^^^^^^^^^ borrowed value does not live long enough
42+
...
43+
LL | }
44+
| - `*s.0` dropped here while still borrowed
45+
|
46+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 82:26...
47+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:26
48+
|
49+
LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
50+
| ^^
51+
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
52+
It represents potential unsoundness in your code.
53+
This warning will become a hard error in the future.
54+
55+
error: compilation successful
56+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1
57+
|
58+
LL | / fn main() { //[ast]~ ERROR compilation successful
59+
LL | | //[migrate]~^ ERROR compilation successful
60+
LL | | let mut x = 1;
61+
LL | | {
62+
... |
63+
LL | | *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
64+
LL | | }
65+
| |_^
66+
67+
error: aborting due to previous error
68+
69+
For more information about this error, try `rustc --explain E0597`.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0597]: `*s.0` does not live long enough
2+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:63:5
3+
|
4+
LL | &mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
5+
| ^^^^^^^^^ borrowed value does not live long enough
6+
...
7+
LL | }
8+
| - `*s.0` dropped here while still borrowed
9+
|
10+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 62:14...
11+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:14
12+
|
13+
LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
14+
| ^^
15+
16+
error[E0597]: `*s.0` does not live long enough
17+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
18+
|
19+
LL | &mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
20+
| ^^^^^^^^^^^^ borrowed value does not live long enough
21+
...
22+
LL | }
23+
| - `*s.0` dropped here while still borrowed
24+
|
25+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 72:20...
26+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:72:20
27+
|
28+
LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
29+
| ^^
30+
31+
error[E0597]: `*s.0` does not live long enough
32+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5
33+
|
34+
LL | &mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
35+
| ^^^^^^^^^^^^^ borrowed value does not live long enough
36+
...
37+
LL | }
38+
| - `*s.0` dropped here while still borrowed
39+
|
40+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 82:26...
41+
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:26
42+
|
43+
LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
44+
| ^^
45+
46+
error: aborting due to 3 previous errors
47+
48+
For more information about this error, try `rustc --explain E0597`.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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 *cannot* return
12+
// mutable borrows that would be scribbled over by destructors before
13+
// the return occurs.
14+
//
15+
// We will explicitly test AST-borrowck, NLL, and migration modes;
16+
// thus we will also skip the automated compare-mode=nll.
17+
18+
// revisions: ast nll migrate
19+
// ignore-compare-mode-nll
20+
21+
// This test is going to pass in the ast and migrate revisions,
22+
// because the AST-borrowck accepted this code in the past (see notes
23+
// below). So we use `#[rustc_error]` to keep the outcome as an error
24+
// in all scenarios, and rely on the stderr files to show what the
25+
// actual behavior is. (See rust-lang/rust#49855.)
26+
#![feature(rustc_attrs)]
27+
28+
#![cfg_attr(nll, feature(nll))]
29+
//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
30+
31+
struct Scribble<'a>(&'a mut u32);
32+
33+
impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
34+
35+
// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
36+
// to strictly outlive `'a`
37+
fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
38+
&mut *s.0
39+
}
40+
41+
// this, by analogy to previous case, is also okay.
42+
fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
43+
&mut *(*s).0
44+
}
45+
46+
// this, by analogy to previous case, is also okay.
47+
fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
48+
&mut *(**s).0
49+
}
50+
51+
// this is not okay: in between the time that we take the mutable
52+
// borrow and the caller receives it as a return value, the drop of
53+
// `s` will scribble on it, violating our aliasing guarantees.
54+
//
55+
// * (Maybe in the future the two-phase borrows system will be
56+
// extended to support this case. But for now, it is an error in
57+
// NLL, even with two-phase borrows.)
58+
//
59+
// In any case, the AST-borrowck was not smart enough to know that
60+
// this should be an error. (Which is perhaps the essence of why
61+
// rust-lang/rust#45696 arose in the first place.)
62+
fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
63+
&mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
64+
//[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
65+
//[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
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_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
73+
&mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
74+
//[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
75+
//[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
76+
}
77+
78+
// This, by analogy to previous case, is *also* not okay.
79+
//
80+
// (But again, AST-borrowck was not smart enogh to know that this
81+
// should be an error.)
82+
fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
83+
&mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
84+
//[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
85+
//[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
86+
}
87+
88+
#[rustc_error]
89+
fn main() { //[ast]~ ERROR compilation successful
90+
//[migrate]~^ ERROR compilation successful
91+
let mut x = 1;
92+
{
93+
let mut long_lived = Scribble(&mut x);
94+
*borrowed_scribble(&mut long_lived) += 10;
95+
// (Scribble dtor runs here, after `&mut`-borrow above ends)
96+
}
97+
{
98+
let mut long_lived = Scribble(&mut x);
99+
*boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
100+
// (Scribble dtor runs here, after `&mut`-borrow above ends)
101+
}
102+
{
103+
let mut long_lived = Scribble(&mut x);
104+
*boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
105+
// (Scribble dtor runs here, after `&mut`-borrow above ends)
106+
}
107+
*scribbled(Scribble(&mut x)) += 10;
108+
*boxed_scribbled(Box::new(Scribble(&mut x))) += 10;
109+
*boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
110+
}

0 commit comments

Comments
 (0)