Mercurial > public > mercurial-scm > hg
annotate rust/hg-cpython/src/ref_sharing.rs @ 44207:e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Unfortunately, these methods can be abused to obtain the inner 'static
reference. The simplest (pseudo-code) example is:
let leaked: PyLeaked<&'static _> = shared.leak_immutable();
let static_ref: &'static _ = &*leaked.try_borrow(py)?;
// PyLeakedRef::deref() tries to bound the lifetime to itself, but
// the underlying data is a &'static reference, so the returned
// reference can be &'static.
This problem can be easily fixed by coercing the lifetime, but there are
many other ways to achieve that, and there wouldn't be a generic solution:
let leaked: PyLeaked<&'static [_]> = shared.leak_immutable();
let leaked_iter: PyLeaked<slice::Iter<'static, _>>
= unsafe { leaked.map(|v| v.iter()) };
let static_slice: &'static [_] = leaked_iter.try_borrow(py)?.as_slice();
So basically I failed to design the safe borrowing interface. Maybe we'll
instead have to add much more restricted interface on top of the unsafe
PyLeaked methods? For instance, Iterator::next() could be implemented if
its Item type is not &'a (where 'a may be cheated.)
Anyway, this seems not an easy issue, so it's probably better to leave the
current interface as unsafe, and get broader comments while upstreaming this
feature.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Tue, 22 Oct 2019 16:04:34 +0900 |
parents | 9804badd5970 |
children | 6b7aef44274b |
rev | line source |
---|---|
43082
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
1 // ref_sharing.rs |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
2 // |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net> |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
4 // |
43082
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
5 // Permission is hereby granted, free of charge, to any person obtaining a copy |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
6 // of this software and associated documentation files (the "Software"), to |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
7 // deal in the Software without restriction, including without limitation the |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
9 // sell copies of the Software, and to permit persons to whom the Software is |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
10 // furnished to do so, subject to the following conditions: |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
11 // |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
12 // The above copyright notice and this permission notice shall be included in |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
13 // all copies or substantial portions of the Software. |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
14 // |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
fdfe5cfb3723
rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents:
42939
diff
changeset
|
21 // IN THE SOFTWARE. |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
22 |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
23 //! Macros for use in the `hg-cpython` bridge library. |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
24 |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
25 use cpython::{exc, PyClone, PyErr, PyObject, PyResult, Python}; |
44206
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
26 use std::cell::{BorrowMutError, Ref, RefCell, RefMut}; |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
27 use std::ops::{Deref, DerefMut}; |
44206
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
28 use std::result; |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
29 use std::sync::atomic::{AtomicUsize, Ordering}; |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
30 |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
31 /// Manages the shared state between Python and Rust |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
32 /// |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
33 /// `PySharedState` is owned by `PySharedRefCell`, and is shared across its |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
34 /// derived references. The consistency of these references are guaranteed |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
35 /// as follows: |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
36 /// |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
37 /// - The immutability of `py_class!` object fields. Any mutation of |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
38 /// `PySharedRefCell` is allowed only through its `borrow_mut()`. |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
39 /// - The `py: Python<'_>` token, which makes sure that any data access is |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
40 /// synchronized by the GIL. |
43427
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
41 /// - The underlying `RefCell`, which prevents `PySharedRefCell` data from |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
42 /// being directly borrowed or leaked while it is mutably borrowed. |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
43 /// - The `borrow_count`, which is the number of references borrowed from |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
44 /// `PyLeaked`. Just like `RefCell`, mutation is prohibited while `PyLeaked` |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
45 /// is borrowed. |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
46 /// - The `generation` counter, which increments on `borrow_mut()`. `PyLeaked` |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
47 /// reference is valid only if the `current_generation()` equals to the |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
48 /// `generation` at the time of `leak_immutable()`. |
43173
070a38737334
rust-cpython: move py_shared_state to PySharedRefCell object
Yuya Nishihara <yuya@tcha.org>
parents:
43082
diff
changeset
|
49 #[derive(Debug, Default)] |
43288
434d7a3e92e3
rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents:
43287
diff
changeset
|
50 struct PySharedState { |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
51 // The counter variable could be Cell<usize> since any operation on |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
52 // PySharedState is synchronized by the GIL, but being "atomic" makes |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
53 // PySharedState inherently Sync. The ordering requirement doesn't |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
54 // matter thanks to the GIL. |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
55 borrow_count: AtomicUsize, |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
56 generation: AtomicUsize, |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
57 } |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
58 |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
59 impl PySharedState { |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
60 fn current_borrow_count(&self, _py: Python) -> usize { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
61 self.borrow_count.load(Ordering::Relaxed) |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
62 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
63 |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
64 fn increase_borrow_count(&self, _py: Python) { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
65 // Note that this wraps around if there are more than usize::MAX |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
66 // borrowed references, which shouldn't happen due to memory limit. |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
67 self.borrow_count.fetch_add(1, Ordering::Relaxed); |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
68 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
69 |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
70 fn decrease_borrow_count(&self, _py: Python) { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
71 let prev_count = self.borrow_count.fetch_sub(1, Ordering::Relaxed); |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
72 assert!(prev_count > 0); |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
73 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
74 |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
75 fn current_generation(&self, _py: Python) -> usize { |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
76 self.generation.load(Ordering::Relaxed) |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
77 } |
44204
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
78 |
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
79 fn increment_generation(&self, py: Python) { |
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
80 assert_eq!(self.current_borrow_count(py), 0); |
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
81 // Note that this wraps around to the same value if mutably |
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
82 // borrowed more than usize::MAX times, which wouldn't happen |
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
83 // in practice. |
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
84 self.generation.fetch_add(1, Ordering::Relaxed); |
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
85 } |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
86 } |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
87 |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
88 /// Helper to keep the borrow count updated while the shared object is |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
89 /// immutably borrowed without using the `RefCell` interface. |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
90 struct BorrowPyShared<'a> { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
91 py: Python<'a>, |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
92 py_shared_state: &'a PySharedState, |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
93 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
94 |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
95 impl<'a> BorrowPyShared<'a> { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
96 fn new( |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
97 py: Python<'a>, |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
98 py_shared_state: &'a PySharedState, |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
99 ) -> BorrowPyShared<'a> { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
100 py_shared_state.increase_borrow_count(py); |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
101 BorrowPyShared { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
102 py, |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
103 py_shared_state, |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
104 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
105 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
106 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
107 |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
108 impl Drop for BorrowPyShared<'_> { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
109 fn drop(&mut self) { |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
110 self.py_shared_state.decrease_borrow_count(self.py); |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
111 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
112 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
113 |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
114 /// `RefCell` wrapper to be safely used in conjunction with `PySharedState`. |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
115 /// |
43288
434d7a3e92e3
rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents:
43287
diff
changeset
|
116 /// This object can be stored in a `py_class!` object as a data field. Any |
434d7a3e92e3
rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents:
43287
diff
changeset
|
117 /// operation is allowed through the `PySharedRef` interface. |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
118 #[derive(Debug)] |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
119 pub struct PySharedRefCell<T> { |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
120 inner: RefCell<T>, |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
121 py_shared_state: PySharedState, |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
122 } |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
123 |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
124 impl<T> PySharedRefCell<T> { |
43173
070a38737334
rust-cpython: move py_shared_state to PySharedRefCell object
Yuya Nishihara <yuya@tcha.org>
parents:
43082
diff
changeset
|
125 pub fn new(value: T) -> PySharedRefCell<T> { |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
126 Self { |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
127 inner: RefCell::new(value), |
43173
070a38737334
rust-cpython: move py_shared_state to PySharedRefCell object
Yuya Nishihara <yuya@tcha.org>
parents:
43082
diff
changeset
|
128 py_shared_state: PySharedState::default(), |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
129 } |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
130 } |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
131 |
43288
434d7a3e92e3
rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents:
43287
diff
changeset
|
132 fn borrow<'a>(&'a self, _py: Python<'a>) -> Ref<'a, T> { |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
133 // py_shared_state isn't involved since |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
134 // - inner.borrow() would fail if self is mutably borrowed, |
44189
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
135 // - and inner.try_borrow_mut() would fail while self is borrowed. |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
136 self.inner.borrow() |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
137 } |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
138 |
44189
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
139 fn try_borrow_mut<'a>( |
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
140 &'a self, |
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
141 py: Python<'a>, |
44206
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
142 ) -> result::Result<RefMut<'a, T>, BorrowMutError> { |
44204
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
143 if self.py_shared_state.current_borrow_count(py) > 0 { |
44206
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
144 // propagate borrow-by-leaked state to inner to get BorrowMutError |
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
145 let _dummy = self.inner.borrow(); |
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
146 self.inner.try_borrow_mut()?; |
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
147 unreachable!("BorrowMutError must be returned"); |
44204
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
148 } |
44206
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
149 let inner_ref = self.inner.try_borrow_mut()?; |
44204
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
150 self.py_shared_state.increment_generation(py); |
bafdaf4858d8
rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents:
44203
diff
changeset
|
151 Ok(inner_ref) |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
152 } |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
153 } |
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
154 |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
155 /// Sharable data member of type `T` borrowed from the `PyObject`. |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
156 pub struct PySharedRef<'a, T> { |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
157 py: Python<'a>, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
158 owner: &'a PyObject, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
159 data: &'a PySharedRefCell<T>, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
160 } |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
161 |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
162 impl<'a, T> PySharedRef<'a, T> { |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
163 /// # Safety |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
164 /// |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
165 /// The `data` must be owned by the `owner`. Otherwise, the leak count |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
166 /// would get wrong. |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
167 pub unsafe fn new( |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
168 py: Python<'a>, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
169 owner: &'a PyObject, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
170 data: &'a PySharedRefCell<T>, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
171 ) -> Self { |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
172 Self { py, owner, data } |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
173 } |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
174 |
43272
00222775d59b
rust-refsharing: add missing lifetime parameter in ref_sharing
Rapha?l Gom?s <rgomes@octobus.net>
parents:
43180
diff
changeset
|
175 pub fn borrow(&self) -> Ref<'a, T> { |
43286
f8c114f20d2d
rust-cpython: require GIL to borrow immutable reference from PySharedRefCell
Yuya Nishihara <yuya@tcha.org>
parents:
43285
diff
changeset
|
176 self.data.borrow(self.py) |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
177 } |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
178 |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
179 /// Mutably borrows the wrapped value. |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
180 /// |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
181 /// # Panics |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
182 /// |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
183 /// Panics if the value is currently borrowed through `PySharedRef` |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
184 /// or `PyLeaked`. |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
185 pub fn borrow_mut(&self) -> RefMut<'a, T> { |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
186 self.try_borrow_mut().expect("already borrowed") |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
187 } |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
188 |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
189 /// Mutably borrows the wrapped value, returning an error if the value |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
190 /// is currently borrowed. |
44206
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
191 pub fn try_borrow_mut( |
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
192 &self, |
9804badd5970
rust-cpython: make PySharedRef::try_borrow_mut() return BorrowMutError
Yuya Nishihara <yuya@tcha.org>
parents:
44205
diff
changeset
|
193 ) -> result::Result<RefMut<'a, T>, BorrowMutError> { |
44189
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
194 self.data.try_borrow_mut(self.py) |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
195 } |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
196 |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
197 /// Returns a leaked reference. |
43427
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
198 /// |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
199 /// # Panics |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
200 /// |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
201 /// Panics if this is mutably borrowed. |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
202 pub fn leak_immutable(&self) -> PyLeaked<&'static T> { |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
203 let state = &self.data.py_shared_state; |
43427
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
204 // make sure self.data isn't mutably borrowed; otherwise the |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
205 // generation number can't be trusted. |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
206 let data_ref = self.borrow(); |
44205
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
207 |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
208 // &'static cast is safe because data_ptr and state_ptr are owned |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
209 // by self.owner, and we do have the GIL for thread safety. |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
210 let data_ptr: *const T = &*data_ref; |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
211 let state_ptr: *const PySharedState = state; |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
212 PyLeaked::<&'static T> { |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
213 inner: self.owner.clone_ref(self.py), |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
214 data: unsafe { &*data_ptr }, |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
215 py_shared_state: unsafe { &*state_ptr }, |
f015d679f08c
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents:
44204
diff
changeset
|
216 generation: state.current_generation(self.py), |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
217 } |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
218 } |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
219 } |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
220 |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
221 /// Allows a `py_class!` generated struct to share references to one of its |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
222 /// data members with Python. |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
223 /// |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
224 /// # Parameters |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
225 /// |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
226 /// * `$name` is the same identifier used in for `py_class!` macro call. |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
227 /// * `$inner_struct` is the identifier of the underlying Rust struct |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
228 /// * `$data_member` is the identifier of the data member of `$inner_struct` |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
229 /// that will be shared. |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
230 /// * `$shared_accessor` is the function name to be generated, which allows |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
231 /// safe access to the data member. |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
232 /// |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
233 /// # Safety |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
234 /// |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
235 /// `$data_member` must persist while the `$name` object is alive. In other |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
236 /// words, it must be an accessor to a data field of the Python object. |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
237 /// |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
238 /// # Example |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
239 /// |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
240 /// ``` |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
241 /// struct MyStruct { |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
242 /// inner: Vec<u32>; |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
243 /// } |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
244 /// |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
245 /// py_class!(pub class MyType |py| { |
42849
8db8fa1de2ef
rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents:
42839
diff
changeset
|
246 /// data inner: PySharedRefCell<MyStruct>; |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
247 /// }); |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
248 /// |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
249 /// py_shared_ref!(MyType, MyStruct, inner, inner_shared); |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
250 /// ``` |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
251 macro_rules! py_shared_ref { |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
252 ( |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
253 $name: ident, |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
254 $inner_struct: ident, |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
255 $data_member: ident, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
256 $shared_accessor: ident |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
257 ) => { |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
258 impl $name { |
43178
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
259 /// Returns a safe reference to the shared `$data_member`. |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
260 /// |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
261 /// This function guarantees that `PySharedRef` is created with |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
262 /// the valid `self` and `self.$data_member(py)` pair. |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
263 fn $shared_accessor<'a>( |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
264 &'a self, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
265 py: Python<'a>, |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
266 ) -> $crate::ref_sharing::PySharedRef<'a, $inner_struct> { |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
267 use cpython::PythonObject; |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
268 use $crate::ref_sharing::PySharedRef; |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
269 let owner = self.as_object(); |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
270 let data = self.$data_member(py); |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
271 unsafe { PySharedRef::new(py, owner, data) } |
1b2200bd06b6
rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents:
43177
diff
changeset
|
272 } |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
273 } |
43177
5cb8867c9e2b
rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents:
43176
diff
changeset
|
274 }; |
5cb8867c9e2b
rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents:
43176
diff
changeset
|
275 } |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
276 |
43177
5cb8867c9e2b
rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents:
43176
diff
changeset
|
277 /// Manage immutable references to `PyObject` leaked into Python iterators. |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
278 /// |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
279 /// This reference will be invalidated once the original value is mutably |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
280 /// borrowed. |
43422
b9f791090211
rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents:
43289
diff
changeset
|
281 pub struct PyLeaked<T> { |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
282 inner: PyObject, |
44188
1f9e6fbdd3e6
rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents:
43430
diff
changeset
|
283 data: T, |
43177
5cb8867c9e2b
rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents:
43176
diff
changeset
|
284 py_shared_state: &'static PySharedState, |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
285 /// Generation counter of data `T` captured when PyLeaked is created. |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
286 generation: usize, |
43177
5cb8867c9e2b
rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents:
43176
diff
changeset
|
287 } |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
288 |
43422
b9f791090211
rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents:
43289
diff
changeset
|
289 // DO NOT implement Deref for PyLeaked<T>! Dereferencing PyLeaked |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
290 // without taking Python GIL wouldn't be safe. Also, the underling reference |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
291 // is invalid if generation != py_shared_state.generation. |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
292 |
43422
b9f791090211
rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents:
43289
diff
changeset
|
293 impl<T> PyLeaked<T> { |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
294 /// Immutably borrows the wrapped value. |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
295 /// |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
296 /// Borrowing fails if the underlying reference has been invalidated. |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
297 /// |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
298 /// # Safety |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
299 /// |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
300 /// The lifetime of the innermost object is cheated. Do not obtain and |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
301 /// copy it out of the borrow scope. See the example of `try_borrow_mut()` |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
302 /// for details. |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
303 pub unsafe fn try_borrow<'a>( |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
304 &'a self, |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
305 py: Python<'a>, |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
306 ) -> PyResult<PyLeakedRef<'a, T>> { |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
307 self.validate_generation(py)?; |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
308 Ok(PyLeakedRef { |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
309 _borrow: BorrowPyShared::new(py, self.py_shared_state), |
44188
1f9e6fbdd3e6
rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents:
43430
diff
changeset
|
310 data: &self.data, |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
311 }) |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
312 } |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
313 |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
314 /// Mutably borrows the wrapped value. |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
315 /// |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
316 /// Borrowing fails if the underlying reference has been invalidated. |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
317 /// |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
318 /// Typically `T` is an iterator. If `T` is an immutable reference, |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
319 /// `get_mut()` is useless since the inner value can't be mutated. |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
320 /// |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
321 /// # Safety |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
322 /// |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
323 /// The lifetime of the innermost object is cheated. Do not obtain and |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
324 /// copy it out of the borrow scope. For example, the following code |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
325 /// is unsafe: |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
326 /// |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
327 /// ```compile_fail |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
328 /// let slice; |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
329 /// { |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
330 /// let iter = leaked.try_borrow_mut(py); |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
331 /// // slice can outlive since the iterator is of Iter<'static, T> |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
332 /// // type, but it shouldn't. |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
333 /// slice = iter.as_slice(); |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
334 /// } |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
335 /// println!("{:?}", slice); |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
336 /// ``` |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
337 pub unsafe fn try_borrow_mut<'a>( |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
338 &'a mut self, |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
339 py: Python<'a>, |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
340 ) -> PyResult<PyLeakedRefMut<'a, T>> { |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
341 self.validate_generation(py)?; |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
342 Ok(PyLeakedRefMut { |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
343 _borrow: BorrowPyShared::new(py, self.py_shared_state), |
44188
1f9e6fbdd3e6
rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents:
43430
diff
changeset
|
344 data: &mut self.data, |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
345 }) |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
346 } |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
347 |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
348 /// Converts the inner value by the given function. |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
349 /// |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
350 /// Typically `T` is a static reference to a container, and `U` is an |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
351 /// iterator of that container. |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
352 /// |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
353 /// # Panics |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
354 /// |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
355 /// Panics if the underlying reference has been invalidated. |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
356 /// |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
357 /// This is typically called immediately after the `PyLeaked` is obtained. |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
358 /// In which case, the reference must be valid and no panic would occur. |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
359 /// |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
360 /// # Safety |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
361 /// |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
362 /// The lifetime of the object passed in to the function `f` is cheated. |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
363 /// It's typically a static reference, but is valid only while the |
43422
b9f791090211
rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents:
43289
diff
changeset
|
364 /// corresponding `PyLeaked` is alive. Do not copy it out of the |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
365 /// function call. |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
366 pub unsafe fn map<U>( |
44188
1f9e6fbdd3e6
rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents:
43430
diff
changeset
|
367 self, |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
368 py: Python, |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
369 f: impl FnOnce(T) -> U, |
43422
b9f791090211
rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents:
43289
diff
changeset
|
370 ) -> PyLeaked<U> { |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
371 // Needs to test the generation value to make sure self.data reference |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
372 // is still intact. |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
373 self.validate_generation(py) |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
374 .expect("map() over invalidated leaked reference"); |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
375 |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
376 // f() could make the self.data outlive. That's why map() is unsafe. |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
377 // In order to make this function safe, maybe we'll need a way to |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
378 // temporarily restrict the lifetime of self.data and translate the |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
379 // returned object back to Something<'static>. |
44188
1f9e6fbdd3e6
rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents:
43430
diff
changeset
|
380 let new_data = f(self.data); |
43422
b9f791090211
rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents:
43289
diff
changeset
|
381 PyLeaked { |
44188
1f9e6fbdd3e6
rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents:
43430
diff
changeset
|
382 inner: self.inner, |
1f9e6fbdd3e6
rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents:
43430
diff
changeset
|
383 data: new_data, |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
384 py_shared_state: self.py_shared_state, |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
385 generation: self.generation, |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
386 } |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
387 } |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
388 |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
389 fn validate_generation(&self, py: Python) -> PyResult<()> { |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
390 if self.py_shared_state.current_generation(py) == self.generation { |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
391 Ok(()) |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
392 } else { |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
393 Err(PyErr::new::<exc::RuntimeError, _>( |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
394 py, |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
395 "Cannot access to leaked reference after mutation", |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
396 )) |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
397 } |
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
398 } |
43177
5cb8867c9e2b
rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents:
43176
diff
changeset
|
399 } |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
400 |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
401 /// Immutably borrowed reference to a leaked value. |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
402 pub struct PyLeakedRef<'a, T> { |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
403 _borrow: BorrowPyShared<'a>, |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
404 data: &'a T, |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
405 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
406 |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
407 impl<T> Deref for PyLeakedRef<'_, T> { |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
408 type Target = T; |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
409 |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
410 fn deref(&self) -> &T { |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
411 self.data |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
412 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
413 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
414 |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
415 /// Mutably borrowed reference to a leaked value. |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
416 pub struct PyLeakedRefMut<'a, T> { |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
417 _borrow: BorrowPyShared<'a>, |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
418 data: &'a mut T, |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
419 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
420 |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
421 impl<T> Deref for PyLeakedRefMut<'_, T> { |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
422 type Target = T; |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
423 |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
424 fn deref(&self) -> &T { |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
425 self.data |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
426 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
427 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
428 |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
429 impl<T> DerefMut for PyLeakedRefMut<'_, T> { |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
430 fn deref_mut(&mut self) -> &mut T { |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
431 self.data |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
432 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
433 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
434 |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
435 /// Defines a `py_class!` that acts as a Python iterator over a Rust iterator. |
42888
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
436 /// |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
437 /// TODO: this is a bit awkward to use, and a better (more complicated) |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
438 /// procedural macro would simplify the interface a lot. |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
439 /// |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
440 /// # Parameters |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
441 /// |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
442 /// * `$name` is the identifier to give to the resulting Rust struct. |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
443 /// * `$leaked` corresponds to `$leaked` in the matching `py_shared_ref!` call. |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
444 /// * `$iterator_type` is the type of the Rust iterator. |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
445 /// * `$success_func` is a function for processing the Rust `(key, value)` |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
446 /// tuple on iteration success, turning it into something Python understands. |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
447 /// * `$success_func` is the return type of `$success_func` |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
448 /// |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
449 /// # Safety |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
450 /// |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
451 /// `$success_func` may take a reference, but it's lifetime may be cheated. |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
452 /// Do not copy it out of the function call. |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
453 /// |
42888
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
454 /// # Example |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
455 /// |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
456 /// ``` |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
457 /// struct MyStruct { |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
458 /// inner: HashMap<Vec<u8>, Vec<u8>>; |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
459 /// } |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
460 /// |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
461 /// py_class!(pub class MyType |py| { |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
462 /// data inner: PySharedRefCell<MyStruct>; |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
463 /// |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
464 /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> { |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
465 /// let leaked_ref = self.inner_shared(py).leak_immutable(); |
42891
5ccc08d02280
rust-cpython: leverage py_shared_iterator::from_inner() where appropriate
Yuya Nishihara <yuya@tcha.org>
parents:
42890
diff
changeset
|
466 /// MyTypeItemsIterator::from_inner( |
42888
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
467 /// py, |
43285
ffc1fbd7d1f5
rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents:
43284
diff
changeset
|
468 /// unsafe { leaked_ref.map(py, |o| o.iter()) }, |
42888
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
469 /// ) |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
470 /// } |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
471 /// }); |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
472 /// |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
473 /// impl MyType { |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
474 /// fn translate_key_value( |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
475 /// py: Python, |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
476 /// res: (&Vec<u8>, &Vec<u8>), |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
477 /// ) -> PyResult<Option<(PyBytes, PyBytes)>> { |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
478 /// let (f, entry) = res; |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
479 /// Ok(Some(( |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
480 /// PyBytes::new(py, f), |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
481 /// PyBytes::new(py, entry), |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
482 /// ))) |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
483 /// } |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
484 /// } |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
485 /// |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
486 /// py_shared_ref!(MyType, MyStruct, inner, MyTypeLeakedRef); |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
487 /// |
42889
ea91a126c803
rust-cpython: rename py_shared_iterator_impl to py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
42888
diff
changeset
|
488 /// py_shared_iterator!( |
42888
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
489 /// MyTypeItemsIterator, |
43422
b9f791090211
rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents:
43289
diff
changeset
|
490 /// PyLeaked<HashMap<'static, Vec<u8>, Vec<u8>>>, |
42888
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
491 /// MyType::translate_key_value, |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
492 /// Option<(PyBytes, PyBytes)> |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
493 /// ); |
67853749961b
rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents:
42887
diff
changeset
|
494 /// ``` |
42889
ea91a126c803
rust-cpython: rename py_shared_iterator_impl to py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
42888
diff
changeset
|
495 macro_rules! py_shared_iterator { |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
496 ( |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
497 $name: ident, |
43177
5cb8867c9e2b
rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents:
43176
diff
changeset
|
498 $leaked: ty, |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
499 $success_func: expr, |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
500 $success_type: ty |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
501 ) => { |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
502 py_class!(pub class $name |py| { |
43426
6f9f15a476a4
rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
43425
diff
changeset
|
503 data inner: RefCell<$leaked>; |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
504 |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
505 def __next__(&self) -> PyResult<$success_type> { |
43426
6f9f15a476a4
rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
43425
diff
changeset
|
506 let mut leaked = self.inner(py).borrow_mut(); |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
507 let mut iter = unsafe { leaked.try_borrow_mut(py)? }; |
43426
6f9f15a476a4
rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
43425
diff
changeset
|
508 match iter.next() { |
6f9f15a476a4
rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
43425
diff
changeset
|
509 None => Ok(None), |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
510 // res may be a reference of cheated 'static lifetime |
43426
6f9f15a476a4
rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
43425
diff
changeset
|
511 Some(res) => $success_func(py, res), |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
512 } |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
513 } |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
514 |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
515 def __iter__(&self) -> PyResult<Self> { |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
516 Ok(self.clone_ref(py)) |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
517 } |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
518 }); |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
519 |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
520 impl $name { |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
521 pub fn from_inner( |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
522 py: Python, |
42890
74d67c645278
rust-cpython: remove Option<_> from interface of py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
42889
diff
changeset
|
523 leaked: $leaked, |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
524 ) -> PyResult<Self> { |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
525 Self::create_instance( |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
526 py, |
43426
6f9f15a476a4
rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents:
43425
diff
changeset
|
527 RefCell::new(leaked), |
42752
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
528 ) |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
529 } |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
530 } |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
531 }; |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
532 } |
43289
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
533 |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
534 #[cfg(test)] |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
535 #[cfg(any(feature = "python27-bin", feature = "python3-bin"))] |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
536 mod test { |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
537 use super::*; |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
538 use cpython::{GILGuard, Python}; |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
539 |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
540 py_class!(class Owner |py| { |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
541 data string: PySharedRefCell<String>; |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
542 }); |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
543 py_shared_ref!(Owner, String, string, string_shared); |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
544 |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
545 fn prepare_env() -> (GILGuard, Owner) { |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
546 let gil = Python::acquire_gil(); |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
547 let py = gil.python(); |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
548 let owner = |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
549 Owner::create_instance(py, PySharedRefCell::new("new".to_owned())) |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
550 .unwrap(); |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
551 (gil, owner) |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
552 } |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
553 |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
554 #[test] |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
555 fn test_leaked_borrow() { |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
556 let (gil, owner) = prepare_env(); |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
557 let py = gil.python(); |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
558 let leaked = owner.string_shared(py).leak_immutable(); |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
559 let leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap(); |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
560 assert_eq!(*leaked_ref, "new"); |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
561 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
562 |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
563 #[test] |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
564 fn test_leaked_borrow_mut() { |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
565 let (gil, owner) = prepare_env(); |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
566 let py = gil.python(); |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
567 let leaked = owner.string_shared(py).leak_immutable(); |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
568 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
569 let mut leaked_ref = |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
570 unsafe { leaked_iter.try_borrow_mut(py) }.unwrap(); |
43423
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
571 assert_eq!(leaked_ref.next(), Some('n')); |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
572 assert_eq!(leaked_ref.next(), Some('e')); |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
573 assert_eq!(leaked_ref.next(), Some('w')); |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
574 assert_eq!(leaked_ref.next(), None); |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
575 } |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
576 |
945d4dba5e78
rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents:
43422
diff
changeset
|
577 #[test] |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
578 fn test_leaked_borrow_after_mut() { |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
579 let (gil, owner) = prepare_env(); |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
580 let py = gil.python(); |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
581 let leaked = owner.string_shared(py).leak_immutable(); |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
582 owner.string_shared(py).borrow_mut().clear(); |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
583 assert!(unsafe { leaked.try_borrow(py) }.is_err()); |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
584 } |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
585 |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
586 #[test] |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
587 fn test_leaked_borrow_mut_after_mut() { |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
588 let (gil, owner) = prepare_env(); |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
589 let py = gil.python(); |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
590 let leaked = owner.string_shared(py).leak_immutable(); |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
591 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
592 owner.string_shared(py).borrow_mut().clear(); |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
593 assert!(unsafe { leaked_iter.try_borrow_mut(py) }.is_err()); |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
594 } |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
595 |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
596 #[test] |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
597 #[should_panic(expected = "map() over invalidated leaked reference")] |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
598 fn test_leaked_map_after_mut() { |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
599 let (gil, owner) = prepare_env(); |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
600 let py = gil.python(); |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
601 let leaked = owner.string_shared(py).leak_immutable(); |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
602 owner.string_shared(py).borrow_mut().clear(); |
43424
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
603 let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
604 } |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
605 |
0836efe4967b
rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents:
43423
diff
changeset
|
606 #[test] |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
607 fn test_try_borrow_mut_while_leaked_ref() { |
43289
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
608 let (gil, owner) = prepare_env(); |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
609 let py = gil.python(); |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
610 assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
611 let leaked = owner.string_shared(py).leak_immutable(); |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
612 { |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
613 let _leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap(); |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
614 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
615 { |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
616 let _leaked_ref2 = unsafe { leaked.try_borrow(py) }.unwrap(); |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
617 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
618 } |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
619 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
620 } |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
621 assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
622 } |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
623 |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
624 #[test] |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
625 fn test_try_borrow_mut_while_leaked_ref_mut() { |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
626 let (gil, owner) = prepare_env(); |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
627 let py = gil.python(); |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
628 assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
629 let leaked = owner.string_shared(py).leak_immutable(); |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
630 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
631 { |
44207
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
632 let _leaked_ref = |
e960c30d7e50
rust-cpython: mark all PyLeaked methods as unsafe
Yuya Nishihara <yuya@tcha.org>
parents:
44206
diff
changeset
|
633 unsafe { leaked_iter.try_borrow_mut(py) }.unwrap(); |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
634 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
43425
ed50f2c31a4c
rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents:
43424
diff
changeset
|
635 } |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
636 assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
43289
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
637 } |
43427
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
638 |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
639 #[test] |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
640 #[should_panic(expected = "mutably borrowed")] |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
641 fn test_leak_while_borrow_mut() { |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
642 let (gil, owner) = prepare_env(); |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
643 let py = gil.python(); |
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
644 let _mut_ref = owner.string_shared(py).borrow_mut(); |
43430
8418b77132c1
rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents:
43429
diff
changeset
|
645 owner.string_shared(py).leak_immutable(); |
43427
b7ab3a0a9e57
rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents:
43426
diff
changeset
|
646 } |
44189
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
647 |
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
648 #[test] |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
649 fn test_try_borrow_mut_while_borrow() { |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
650 let (gil, owner) = prepare_env(); |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
651 let py = gil.python(); |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
652 let _ref = owner.string_shared(py).borrow(); |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
653 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
654 } |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
655 |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
656 #[test] |
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
657 #[should_panic(expected = "already borrowed")] |
44189
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
658 fn test_borrow_mut_while_borrow() { |
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
659 let (gil, owner) = prepare_env(); |
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
660 let py = gil.python(); |
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
661 let _ref = owner.string_shared(py).borrow(); |
44203
2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents:
44189
diff
changeset
|
662 owner.string_shared(py).borrow_mut(); |
44189
4a4c3b9fd91b
rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents:
44188
diff
changeset
|
663 } |
43289
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43288
diff
changeset
|
664 } |