28 |
26 |
29 /// "leak" in the sense of `UnsafePyLeaked` the `string` data field, |
27 /// "leak" in the sense of `UnsafePyLeaked` the `string` data field, |
30 /// taking care of all the boilerplate |
28 /// taking care of all the boilerplate |
31 fn leak_string(owner: &Bound<'_, Owner>) -> UnsafePyLeaked<&'static String> { |
29 fn leak_string(owner: &Bound<'_, Owner>) -> UnsafePyLeaked<&'static String> { |
32 let cell = &owner.borrow().string; |
30 let cell = &owner.borrow().string; |
33 let shared_ref = unsafe { cell.borrow(owner) }; |
31 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
34 shared_ref.leak_immutable() |
32 shared_ref.leak_immutable() |
35 } |
33 } |
36 |
34 |
37 fn try_leak_string( |
35 fn try_leak_string( |
38 owner: &Bound<'_, Owner>, |
36 owner: &Bound<'_, Owner>, |
39 ) -> Result<UnsafePyLeaked<&'static String>, TryLeakError> { |
37 ) -> Result<UnsafePyLeaked<&'static String>, TryLeakError> { |
40 let cell = &owner.borrow().string; |
38 let cell = &owner.borrow().string; |
41 let shared_ref = unsafe { cell.borrow(owner) }; |
39 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
42 shared_ref.try_leak_immutable() |
40 shared_ref.try_leak_immutable() |
43 } |
41 } |
44 |
42 |
45 /// Mutate the `string` field of `owner` as would be done from Python code |
43 /// Mutate the `string` field of `owner` as would be done from Python code |
46 /// |
44 /// |
52 fn mutate_string<'py>( |
50 fn mutate_string<'py>( |
53 owner: &'py Bound<'py, Owner>, |
51 owner: &'py Bound<'py, Owner>, |
54 f: impl FnOnce(&mut String), |
52 f: impl FnOnce(&mut String), |
55 ) -> () { |
53 ) -> () { |
56 let cell = &owner.borrow_mut().string; |
54 let cell = &owner.borrow_mut().string; |
57 let shared_ref = unsafe { cell.borrow(owner) }; |
55 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
58 f(&mut shared_ref.borrow_mut()); |
56 f(&mut shared_ref.borrow_mut()); |
59 } |
57 } |
60 |
58 |
61 #[test] |
59 #[test] |
62 fn test_leaked_borrow() -> PyResult<()> { |
60 fn test_leaked_borrow() -> PyResult<()> { |
121 /// |
119 /// |
122 /// Simply returning the `Result` is not possible, because that is |
120 /// Simply returning the `Result` is not possible, because that is |
123 /// returning a reference to data owned by the function |
121 /// returning a reference to data owned by the function |
124 fn assert_try_borrow_string_mut_ok(owner: &Bound<'_, Owner>) { |
122 fn assert_try_borrow_string_mut_ok(owner: &Bound<'_, Owner>) { |
125 let cell = &owner.borrow().string; |
123 let cell = &owner.borrow().string; |
126 let shared_ref = unsafe { cell.borrow(owner) }; |
124 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
127 assert!(shared_ref.try_borrow_mut().is_ok()); |
125 assert!(shared_ref.try_borrow_mut().is_ok()); |
128 } |
126 } |
129 |
127 |
130 fn assert_try_borrow_string_mut_err(owner: &Bound<'_, Owner>) { |
128 fn assert_try_borrow_string_mut_err(owner: &Bound<'_, Owner>) { |
131 let cell = &owner.borrow().string; |
129 let cell = &owner.borrow().string; |
132 let shared_ref = unsafe { cell.borrow(owner) }; |
130 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
133 assert!(shared_ref.try_borrow_mut().is_err()); |
131 assert!(shared_ref.try_borrow_mut().is_err()); |
134 } |
132 } |
135 |
133 |
136 fn assert_try_borrow_string_err(owner: &Bound<'_, Owner>) { |
134 fn assert_try_borrow_string_err(owner: &Bound<'_, Owner>) { |
137 let cell = &owner.borrow().string; |
135 let cell = &owner.borrow().string; |
138 let shared_ref = unsafe { cell.borrow(owner) }; |
136 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
139 assert!(shared_ref.try_borrow().is_err()); |
137 assert!(shared_ref.try_borrow().is_err()); |
140 } |
138 } |
141 |
139 |
142 #[test] |
140 #[test] |
143 fn test_try_borrow_mut_while_leaked_ref() -> PyResult<()> { |
141 fn test_try_borrow_mut_while_leaked_ref() -> PyResult<()> { |
176 |
174 |
177 #[test] |
175 #[test] |
178 fn test_try_leak_while_borrow_mut() -> PyResult<()> { |
176 fn test_try_leak_while_borrow_mut() -> PyResult<()> { |
179 with_setup(|_py, owner| { |
177 with_setup(|_py, owner| { |
180 let cell = &owner.borrow().string; |
178 let cell = &owner.borrow().string; |
181 let shared_ref = unsafe { cell.borrow(owner) }; |
179 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
182 let _mut_ref = shared_ref.borrow_mut(); |
180 let _mut_ref = shared_ref.borrow_mut(); |
183 |
181 |
184 assert!(try_leak_string(owner).is_err()); |
182 assert!(try_leak_string(owner).is_err()); |
185 Ok(()) |
183 Ok(()) |
186 }) |
184 }) |
189 #[test] |
187 #[test] |
190 #[should_panic(expected = "already mutably borrowed")] |
188 #[should_panic(expected = "already mutably borrowed")] |
191 fn test_leak_while_borrow_mut() { |
189 fn test_leak_while_borrow_mut() { |
192 with_setup(|_py, owner| { |
190 with_setup(|_py, owner| { |
193 let cell = &owner.borrow().string; |
191 let cell = &owner.borrow().string; |
194 let shared_ref = unsafe { cell.borrow(owner) }; |
192 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
195 let _mut_ref = shared_ref.borrow_mut(); |
193 let _mut_ref = shared_ref.borrow_mut(); |
196 |
194 |
197 leak_string(owner); |
195 leak_string(owner); |
198 Ok(()) |
196 Ok(()) |
199 }) |
197 }) |
202 |
200 |
203 #[test] |
201 #[test] |
204 fn test_try_borrow_mut_while_borrow() -> PyResult<()> { |
202 fn test_try_borrow_mut_while_borrow() -> PyResult<()> { |
205 with_setup(|_py, owner| { |
203 with_setup(|_py, owner| { |
206 let cell = &owner.borrow().string; |
204 let cell = &owner.borrow().string; |
207 let shared_ref = unsafe { cell.borrow(owner) }; |
205 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
208 let _ref = shared_ref.borrow(); |
206 let _ref = shared_ref.borrow(); |
209 |
207 |
210 assert_try_borrow_string_mut_err(owner); |
208 assert_try_borrow_string_mut_err(owner); |
211 Ok(()) |
209 Ok(()) |
212 }) |
210 }) |
215 #[test] |
213 #[test] |
216 #[should_panic(expected = "already borrowed")] |
214 #[should_panic(expected = "already borrowed")] |
217 fn test_borrow_mut_while_borrow() { |
215 fn test_borrow_mut_while_borrow() { |
218 with_setup(|_py, owner| { |
216 with_setup(|_py, owner| { |
219 let cell = &owner.borrow().string; |
217 let cell = &owner.borrow().string; |
220 let shared_ref = unsafe { cell.borrow(owner) }; |
218 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
221 let _ref = shared_ref.borrow(); |
219 let _ref = shared_ref.borrow(); |
222 |
220 |
223 let shared_ref2 = unsafe { cell.borrow(owner) }; |
221 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) }; |
224 let _mut_ref = shared_ref2.borrow_mut(); |
222 let _mut_ref = shared_ref2.borrow_mut(); |
225 Ok(()) |
223 Ok(()) |
226 }) |
224 }) |
227 .expect("should already have panicked") |
225 .expect("should already have panicked") |
228 } |
226 } |
229 |
227 |
230 #[test] |
228 #[test] |
231 fn test_try_borrow_while_borrow_mut() -> PyResult<()> { |
229 fn test_try_borrow_while_borrow_mut() -> PyResult<()> { |
232 with_setup(|_py, owner| { |
230 with_setup(|_py, owner| { |
233 let cell = &owner.borrow().string; |
231 let cell = &owner.borrow().string; |
234 let shared_ref = unsafe { cell.borrow(owner) }; |
232 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
235 let _mut_ref = shared_ref.borrow_mut(); |
233 let _mut_ref = shared_ref.borrow_mut(); |
236 |
234 |
237 assert_try_borrow_string_err(owner); |
235 assert_try_borrow_string_err(owner); |
238 Ok(()) |
236 Ok(()) |
239 }) |
237 }) |
242 #[test] |
240 #[test] |
243 #[should_panic(expected = "already mutably borrowed")] |
241 #[should_panic(expected = "already mutably borrowed")] |
244 fn test_borrow_while_borrow_mut() { |
242 fn test_borrow_while_borrow_mut() { |
245 with_setup(|_py, owner| { |
243 with_setup(|_py, owner| { |
246 let cell = &owner.borrow().string; |
244 let cell = &owner.borrow().string; |
247 let shared_ref = unsafe { cell.borrow(owner) }; |
245 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
248 let _mut_ref = shared_ref.borrow_mut(); |
246 let _mut_ref = shared_ref.borrow_mut(); |
249 |
247 |
250 let shared_ref2 = unsafe { cell.borrow(owner) }; |
248 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) }; |
251 let _ref = shared_ref2.borrow(); |
249 let _ref = shared_ref2.borrow(); |
252 Ok(()) |
250 Ok(()) |
253 }) |
251 }) |
254 .expect("should already have panicked") |
252 .expect("should already have panicked") |
255 } |
253 } |