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