rust/hg-cpython/src/ref_sharing.rs
author Yuya Nishihara <yuya@tcha.org>
Sat, 19 Oct 2019 16:48:34 +0900
changeset 44205 f015d679f08c
parent 44204 bafdaf4858d8
child 44206 9804badd5970
permissions -rw-r--r--
rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new() For the same reason as the previous patch. The unsafe stuff can be better documented if these functions are inlined.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    25
use crate::exceptions::AlreadyBorrowed;
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
    26
use cpython::{exc, PyClone, PyErr, PyObject, PyResult, Python};
43428
6c0e47874217 rust-cpython: drop manual management of mutably_borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43427
diff changeset
    27
use std::cell::{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
    28
use std::ops::{Deref, DerefMut};
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>,
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   142
    ) -> PyResult<RefMut<'a, T>> {
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 {
bafdaf4858d8 rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents: 44203
diff changeset
   144
            return Err(AlreadyBorrowed::new(
bafdaf4858d8 rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents: 44203
diff changeset
   145
                py,
bafdaf4858d8 rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents: 44203
diff changeset
   146
                "Cannot borrow mutably while immutably borrowed",
bafdaf4858d8 rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents: 44203
diff changeset
   147
            ));
bafdaf4858d8 rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents: 44203
diff changeset
   148
        }
44189
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   149
        let inner_ref = self
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   150
            .inner
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   151
            .try_borrow_mut()
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   152
            .map_err(|e| AlreadyBorrowed::new(py, e.to_string()))?;
44204
bafdaf4858d8 rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents: 44203
diff changeset
   153
        self.py_shared_state.increment_generation(py);
bafdaf4858d8 rust-cpython: inline PySharedState::try_borrow_mut()
Yuya Nishihara <yuya@tcha.org>
parents: 44203
diff changeset
   154
        Ok(inner_ref)
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
   155
    }
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
   156
}
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
   157
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   158
/// 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
   159
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
   160
    py: Python<'a>,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   161
    owner: &'a PyObject,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   162
    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
   163
}
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
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
   166
    /// # Safety
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   167
    ///
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   168
    /// 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
   169
    /// would get wrong.
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   170
    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
   171
        py: Python<'a>,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   172
        owner: &'a PyObject,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   173
        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
   174
    ) -> Self {
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   175
        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
   176
    }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   177
43272
00222775d59b rust-refsharing: add missing lifetime parameter in ref_sharing
Rapha?l Gom?s <rgomes@octobus.net>
parents: 43180
diff changeset
   178
    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
   179
        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
   180
    }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   181
44203
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   182
    /// 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
   183
    ///
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   184
    /// # Panics
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   185
    ///
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   186
    /// 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
   187
    /// or `PyLeaked`.
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   188
    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
   189
        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
   190
    }
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   191
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   192
    /// 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
   193
    /// is currently borrowed.
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   194
    pub fn try_borrow_mut(&self) -> PyResult<RefMut<'a, T>> {
44189
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   195
        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
   196
    }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   197
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   198
    /// 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
   199
    ///
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
   200
    /// # Panics
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
   201
    ///
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
   202
    /// 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
   203
    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
   204
        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
   205
        // 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
   206
        // 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
   207
        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
   208
f015d679f08c rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents: 44204
diff changeset
   209
        // &'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
   210
        // 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
   211
        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
   212
        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
   213
        PyLeaked::<&'static T> {
f015d679f08c rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents: 44204
diff changeset
   214
            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
   215
            data: unsafe { &*data_ptr },
f015d679f08c rust-cpython: inline PySharedState::leak_immutable() and PyLeaked::new()
Yuya Nishihara <yuya@tcha.org>
parents: 44204
diff changeset
   216
            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
   217
            generation: state.current_generation(self.py),
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   218
        }
43178
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
}
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   221
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   222
/// 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
   223
/// data members with Python.
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   224
///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   225
/// # Parameters
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   226
///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   227
/// * `$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
   228
/// * `$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
   229
/// * `$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
   230
/// 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
   231
/// * `$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
   232
/// 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
   233
///
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   234
/// # Safety
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   235
///
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   236
/// `$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
   237
/// 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
   238
///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   239
/// # Example
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
/// ```
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   242
/// struct MyStruct {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   243
///     inner: Vec<u32>;
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
///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   246
/// py_class!(pub class MyType |py| {
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
   247
///     data inner: PySharedRefCell<MyStruct>;
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   248
/// });
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   249
///
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   250
/// 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
   251
/// ```
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   252
macro_rules! py_shared_ref {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   253
    (
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   254
        $name: ident,
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   255
        $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
   256
        $data_member: ident,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   257
        $shared_accessor: ident
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   258
    ) => {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   259
        impl $name {
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   260
            /// 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
   261
            ///
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   262
            /// 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
   263
            /// 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
   264
            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
   265
                &'a self,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   266
                py: Python<'a>,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   267
            ) -> $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
   268
                use cpython::PythonObject;
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
   269
                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
   270
                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
   271
                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
   272
                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
   273
            }
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   274
        }
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
   275
    };
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
   276
}
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   277
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
   278
/// 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
   279
///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   280
/// 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
   281
/// borrowed.
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
   282
pub struct PyLeaked<T> {
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   283
    inner: PyObject,
44188
1f9e6fbdd3e6 rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents: 43430
diff changeset
   284
    data: T,
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
   285
    py_shared_state: &'static PySharedState,
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   286
    /// 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
   287
    generation: usize,
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
   288
}
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   289
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
   290
// 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
   291
// 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
   292
// 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
   293
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
   294
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
   295
    /// Immutably borrows the wrapped value.
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   296
    ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   297
    /// Borrowing fails if the underlying reference has been invalidated.
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   298
    pub fn try_borrow<'a>(
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   299
        &'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
   300
        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
   301
    ) -> PyResult<PyLeakedRef<'a, T>> {
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   302
        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
   303
        Ok(PyLeakedRef {
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
   304
            _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
   305
            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
   306
        })
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   307
    }
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   308
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   309
    /// Mutably borrows the wrapped value.
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   310
    ///
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   311
    /// 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
   312
    ///
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   313
    /// 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
   314
    /// `get_mut()` is useless since the inner value can't be mutated.
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   315
    pub fn try_borrow_mut<'a>(
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   316
        &'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
   317
        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
   318
    ) -> PyResult<PyLeakedRefMut<'a, T>> {
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   319
        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
   320
        Ok(PyLeakedRefMut {
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
   321
            _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
   322
            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
   323
        })
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   324
    }
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   325
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   326
    /// 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
   327
    ///
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   328
    /// 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
   329
    /// iterator of that container.
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   330
    ///
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   331
    /// # Panics
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   332
    ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   333
    /// 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
   334
    ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   335
    /// 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
   336
    /// 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
   337
    ///
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   338
    /// # Safety
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   339
    ///
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   340
    /// 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
   341
    /// 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
   342
    /// 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
   343
    /// function call.
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   344
    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
   345
        self,
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   346
        py: Python,
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   347
        f: impl FnOnce(T) -> U,
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
   348
    ) -> PyLeaked<U> {
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   349
        // 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
   350
        // is still intact.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   351
        self.validate_generation(py)
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   352
            .expect("map() over invalidated leaked reference");
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   353
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   354
        // 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
   355
        // 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
   356
        // 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
   357
        // 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
   358
        let new_data = f(self.data);
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
   359
        PyLeaked {
44188
1f9e6fbdd3e6 rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents: 43430
diff changeset
   360
            inner: self.inner,
1f9e6fbdd3e6 rust-cpython: remove useless wrappers from PyLeaked, just move by map()
Yuya Nishihara <yuya@tcha.org>
parents: 43430
diff changeset
   361
            data: new_data,
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   362
            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
   363
            generation: self.generation,
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   364
        }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   365
    }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   366
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   367
    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
   368
        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
   369
            Ok(())
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   370
        } else {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   371
            Err(PyErr::new::<exc::RuntimeError, _>(
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   372
                py,
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   373
                "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
   374
            ))
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   375
        }
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   376
    }
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
   377
}
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   378
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   379
/// 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
   380
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
   381
    _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
   382
    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
   383
}
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   384
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   385
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
   386
    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
   387
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   388
    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
   389
        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
   390
    }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   391
}
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   392
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   393
/// 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
   394
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
   395
    _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
   396
    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
   397
}
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   398
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   399
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
   400
    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
   401
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   402
    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
   403
        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
   404
    }
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> 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
   408
    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
   409
        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
   410
    }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   411
}
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   412
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   413
/// 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
   414
///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   415
/// 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
   416
///     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
   417
///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   418
/// # Parameters
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   419
///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   420
/// * `$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
   421
/// * `$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
   422
/// * `$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
   423
/// * `$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
   424
/// 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
   425
/// * `$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
   426
///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   427
/// # Example
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   428
///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   429
/// ```
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   430
/// struct MyStruct {
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   431
///     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
   432
/// }
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   433
///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   434
/// 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
   435
///     data inner: PySharedRefCell<MyStruct>;
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
///     def __iter__(&self) -> PyResult<MyTypeItemsIterator> {
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
   438
///         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
   439
///         MyTypeItemsIterator::from_inner(
42888
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   440
///             py,
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
   441
///             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
   442
///         )
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   443
///     }
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   444
/// });
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   445
///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   446
/// impl MyType {
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   447
///     fn translate_key_value(
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   448
///         py: Python,
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   449
///         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
   450
///     ) -> PyResult<Option<(PyBytes, PyBytes)>> {
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   451
///         let (f, entry) = res;
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   452
///         Ok(Some((
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   453
///             PyBytes::new(py, f),
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   454
///             PyBytes::new(py, entry),
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
/// }
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   458
///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   459
/// 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
   460
///
42889
ea91a126c803 rust-cpython: rename py_shared_iterator_impl to py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 42888
diff changeset
   461
/// py_shared_iterator!(
42888
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   462
///     MyTypeItemsIterator,
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
   463
///     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
   464
///     MyType::translate_key_value,
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   465
///     Option<(PyBytes, PyBytes)>
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   466
/// );
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
   467
/// ```
42889
ea91a126c803 rust-cpython: rename py_shared_iterator_impl to py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 42888
diff changeset
   468
macro_rules! py_shared_iterator {
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   469
    (
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   470
        $name: ident,
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
   471
        $leaked: ty,
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   472
        $success_func: expr,
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   473
        $success_type: ty
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   474
    ) => {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   475
        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
   476
            data inner: RefCell<$leaked>;
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   477
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   478
            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
   479
                let mut leaked = self.inner(py).borrow_mut();
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
   480
                let mut iter = leaked.try_borrow_mut(py)?;
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
   481
                match iter.next() {
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
   482
                    None => Ok(None),
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
   483
                    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
   484
                }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   485
            }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   486
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   487
            def __iter__(&self) -> PyResult<Self> {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   488
                Ok(self.clone_ref(py))
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   489
            }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   490
        });
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   491
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   492
        impl $name {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   493
            pub fn from_inner(
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   494
                py: Python,
42890
74d67c645278 rust-cpython: remove Option<_> from interface of py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 42889
diff changeset
   495
                leaked: $leaked,
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   496
            ) -> PyResult<Self> {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   497
                Self::create_instance(
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   498
                    py,
43426
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
   499
                    RefCell::new(leaked),
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   500
                )
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
        }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   503
    };
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   504
}
43289
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   505
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   506
#[cfg(test)]
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   507
#[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
   508
mod test {
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   509
    use super::*;
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   510
    use cpython::{GILGuard, Python};
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   511
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   512
    py_class!(class Owner |py| {
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   513
        data string: PySharedRefCell<String>;
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   514
    });
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   515
    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
   516
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   517
    fn prepare_env() -> (GILGuard, Owner) {
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   518
        let gil = Python::acquire_gil();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   519
        let py = gil.python();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   520
        let owner =
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   521
            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
   522
                .unwrap();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   523
        (gil, owner)
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   524
    }
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   525
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   526
    #[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
   527
    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
   528
        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
   529
        let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
   530
        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
   531
        let leaked_ref = leaked.try_borrow(py).unwrap();
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   532
        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
   533
    }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   534
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   535
    #[test]
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   536
    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
   537
        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
   538
        let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
   539
        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
   540
        let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   541
        let mut leaked_ref = leaked_iter.try_borrow_mut(py).unwrap();
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   542
        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
   543
        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
   544
        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
   545
        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
   546
    }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   547
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
   548
    #[test]
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   549
    fn test_leaked_borrow_after_mut() {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   550
        let (gil, owner) = prepare_env();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   551
        let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
   552
        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
   553
        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
   554
        assert!(leaked.try_borrow(py).is_err());
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   555
    }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   556
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   557
    #[test]
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   558
    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
   559
        let (gil, owner) = prepare_env();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   560
        let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
   561
        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
   562
        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
   563
        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
   564
        assert!(leaked_iter.try_borrow_mut(py).is_err());
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   565
    }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   566
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   567
    #[test]
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   568
    #[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
   569
    fn test_leaked_map_after_mut() {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   570
        let (gil, owner) = prepare_env();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   571
        let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
   572
        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
   573
        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
   574
        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
   575
    }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   576
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
   577
    #[test]
44203
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   578
    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
   579
        let (gil, owner) = prepare_env();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   580
        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
   581
        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
   582
        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
   583
        {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
   584
            let _leaked_ref = 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
   585
            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
   586
            {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
   587
                let _leaked_ref2 = 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
   588
                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
   589
            }
44203
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   590
            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
   591
        }
44203
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   592
        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
   593
    }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
   594
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
   595
    #[test]
44203
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   596
    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
   597
        let (gil, owner) = prepare_env();
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
   598
        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
   599
        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
   600
        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
   601
        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
   602
        {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
   603
            let _leaked_ref = 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
   604
            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
   605
        }
44203
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   606
        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
   607
    }
43427
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
   608
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
   609
    #[test]
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
   610
    #[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
   611
    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
   612
        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
   613
        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
   614
        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
   615
        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
   616
    }
44189
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   617
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   618
    #[test]
44203
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   619
    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
   620
        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
   621
        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
   622
        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
   623
        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
   624
    }
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   625
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   626
    #[test]
2a24ead003f0 rust-cpython: add panicking version of borrow_mut() and use it
Yuya Nishihara <yuya@tcha.org>
parents: 44189
diff changeset
   627
    #[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
   628
    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
   629
        let (gil, owner) = prepare_env();
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   630
        let py = gil.python();
4a4c3b9fd91b rust-cpython: make sure PySharedRef::borrow_mut() never panics
Yuya Nishihara <yuya@tcha.org>
parents: 44188
diff changeset
   631
        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
   632
        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
   633
    }
43289
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
   634
}