Skip to content

Commit 073bd67

Browse files
kngwyubirkenfeld
andcommitted
Apply suggestions from georg's review to migration.md
Co-Authored-By: Georg Brandl <[email protected]>
1 parent 6832816 commit 073bd67

File tree

1 file changed

+21
-18
lines changed

1 file changed

+21
-18
lines changed

guide/src/migration.md

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ For more, see [the constructor section](https://pyo3.rs/master/class.html#constr
4242
PyO3 0.9 introduces [`PyCell`](https://pyo3.rs/master/doc/pyo3/pycell/struct.PyCell.html), which is
4343
a [`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) like object wrapper
4444
for dynamically ensuring
45-
[Rust's rules of references](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references).
45+
[The Rules of References](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references).
4646

4747
For `#[pymethods]` or `#[pyfunction]`s, your existing code should continue to work without any change.
4848
Python exceptions will automatically be raised when your functions are used in a way which breaks Rust's
@@ -58,13 +58,13 @@ struct Names {
5858
5959
#[pymethods]
6060
impl Names {
61-
#[new]
62-
fn new() -> Self {
63-
Names { names: vec![] }
64-
}
65-
fn merge(&mut self, other: &mut Names) {
66-
self.names.append(&mut other.names)
67-
}
61+
#[new]
62+
fn new() -> Self {
63+
Names { names: vec![] }
64+
}
65+
fn merge(&mut self, other: &mut Names) {
66+
self.names.append(&mut other.names)
67+
}
6868
}
6969
# let gil = Python::acquire_gil();
7070
# let py = gil.python();
@@ -78,16 +78,18 @@ impl Names {
7878
# isinstance(e, borrow_mut_err)
7979
# ");
8080
```
81-
`Names` has `merge` method, which takes `&mut self` and `&mut Self`.
81+
`Names` has a `merge` method, which takes `&mut self` and another argument of type `&mut Self`.
8282
Given this `#[pyclass]`, calling `names.merge(names)` in Python raises a `PyBorrowMutError` exception,
8383
since it requires two mutable borrows of `names`.
8484

85-
However, for `#[pyproto]` and some functions, you need to manually fix codes.
85+
However, for `#[pyproto]` and some functions, you need to manually fix the code.
8686

8787
#### Object creation
88-
We could use the older `PyRef` and `PyRefMut` for object creation, but now they are just
89-
reference wrappers for `PyCell`.
90-
Use `PyCell::new` instead.
88+
In 0.8 object creation was done with `PyRef::new` and `PyRefMut::new`.
89+
In 0.9 these have both been removed.
90+
To upgrade code, please use `PyCell::new` instead.
91+
If a `PyRef` or `PyRefMut` is needed, just call `.borrow()` or `.borrow_mut()`
92+
on the newly-created `PyCell`.
9193

9294
Before:
9395
```compile_fail
@@ -111,8 +113,8 @@ let obj_ref = obj.borrow();
111113
```
112114

113115
#### Object extraction
114-
`T: PyClass`, `&T` and `&mut T` no longer have `FromPyObject` implementations.
115-
Instead you should extract `&PyCell`, `PyRef`, and `PyRefMut` respectively.
116+
For `PyClass` types `T`, `&T` and `&mut T` no longer have `FromPyObject` implementations.
117+
Instead you should extract `PyRef<T>` or `PyRefMut<T>`, respectively. You can also extract `&PyCell<T>`.
116118

117119
Before:
118120
```ignore
@@ -125,7 +127,7 @@ After:
125127
```
126128
# use pyo3::prelude::*;
127129
# use pyo3::types::{PyAny, IntoPyDict};
128-
# #[pyclass] struct MyClass {}
130+
# #[derive(Clone)] #[pyclass] struct MyClass {}
129131
# #[pymethods] impl MyClass { #[new]fn new() -> Self { MyClass {} }}
130132
# let gil = Python::acquire_gil();
131133
# let py = gil.python();
@@ -134,6 +136,7 @@ After:
134136
# let create_obj = || py.eval("c()", None, Some(d)).unwrap();
135137
let obj: &PyAny = create_obj();
136138
let obj_cell: &PyCell<MyClass> = obj.extract().unwrap();
139+
let obj: MyClass = obj.extract().unwrap(); // extracted via Clone
137140
{
138141
let obj_ref: PyRef<MyClass> = obj.extract().unwrap();
139142
// we need to drop obj_ref before we can extract a PyRefMut due to Rust's rules of references
@@ -143,8 +146,8 @@ let obj_ref_mut: PyRefMut<MyClass> = obj.extract().unwrap();
143146

144147

145148
#### `#[pyproto]`
146-
Most of `#[pyproto]` arguments requires [`FromPyObject`] implementation.
147-
So if your protocol methods take `&T` or `&mut T`(where `T: PyClass`),
149+
Most of the arguments to methods in `#[pyproto]` impls require a [`FromPyObject`] implementation.
150+
So if your protocol methods take `&T` or `&mut T` (where `T: PyClass`),
148151
please use `PyRef` or `PyRefMut` instead.
149152

150153
Before:

0 commit comments

Comments
 (0)