Skip to content

Commit b0b8245

Browse files
committed
[WIP, not ready for review] PyCell document
1 parent 3d0ee2a commit b0b8245

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

guide/src/class.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,10 @@ like [std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html
122122

123123
Users who are familiar with `RefCell` can use `PyCell` just like `RefCell`.
124124

125-
For users who doesn't know `RefCell` well, we repeat the Rust's borrowing rule here:
125+
For users who doesn't know `RefCell` well, here we repeat the Rust's borrowing rule:
126126
- At any given time, you can have either (but not both of) one mutable reference or any number of immutable references.
127127
- References must always be valid.
128-
`PyCell` ensures these borrowing rules by managing a reference counter.
128+
`PyCell` ensures these borrowing rules by tracking references at runtime.
129129

130130
TODO: link to the API document
131131

src/pycell.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Traits and structs for `#[pyclass]`.
1+
//! Includes `PyCell` implementation.
22
use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
33
use crate::pyclass_init::PyClassInitializer;
44
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
@@ -90,12 +90,19 @@ impl<T: PyClass> PyCellInner<T> {
9090
}
9191
}
9292

93-
// TODO(kngwyu): Mutability example
94-
/// `PyCell` represents the concrete layout of `T: PyClass` when it is converted
95-
/// to a Python class.
93+
/// `PyCell` is the container type for [`PyClass`](trait.PyClass.html).
9694
///
97-
/// You can use it to test your `#[pyclass]` correctly works.
95+
/// From Python side, `PyCell<T>` is the concrete layout of `T: PyClass` in the Python heap,
96+
/// which means we can convert `*const PyClass<T>` to `*mut ffi::PyObject`.
9897
///
98+
/// From Rust side, `PyCell<T>` is the mutable container of `T`.
99+
/// Since `PyCell<T: PyClass>` is always on the Python heap, we don't have the ownership of it.
100+
/// Thus, to mutate the data behind `&PyCell<T>` safely, we employ the
101+
/// [Interior Mutability Pattern](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html)
102+
/// like [std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html).
103+
///
104+
/// In most cases, `PyCell` is hidden behind `#[pymethods]`.
105+
/// However, you can construct `&PyCell` directly to test your pyclass in Rust code.
99106
/// ```
100107
/// # use pyo3::prelude::*;
101108
/// # use pyo3::{py_run, PyCell};
@@ -112,6 +119,7 @@ impl<T: PyClass> PyCellInner<T> {
112119
/// author: "Philip Kindred Dick",
113120
/// };
114121
/// let book_cell = PyCell::new(py, book).unwrap();
122+
/// // you can expose PyCell to Python snippets
115123
/// py_run!(py, book_cell, "assert book_cell.name[-6:] == 'Castle'");
116124
/// ```
117125
#[repr(C)]
@@ -254,6 +262,9 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyCell<T> {
254262
}
255263
}
256264

265+
/// Wraps a borrowed reference to a value in a `PyCell<T>`.
266+
///
267+
/// See the [`PyCell`](struct.PyCell.html) documentation for more.
257268
pub struct PyRef<'p, T: PyClass> {
258269
inner: &'p PyCellInner<T>,
259270
}
@@ -319,6 +330,9 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyRef<'_, T> {
319330
}
320331
}
321332

333+
/// Wraps a mutable borrowed reference to a value in a `PyCell<T>`.
334+
///
335+
/// See the [`PyCell`](struct.PyCell.html) documentation for more.
322336
pub struct PyRefMut<'p, T: PyClass> {
323337
inner: &'p PyCellInner<T>,
324338
}

0 commit comments

Comments
 (0)