Skip to content

Commit 7b0fbe5

Browse files
authored
make PyTypeCheck an unsafe trait (#5473)
* make `PyTypeCheck` an `unsafe` trait * newsfragment * fix implementation sites
1 parent bf22000 commit 7b0fbe5

File tree

5 files changed

+23
-6
lines changed

5 files changed

+23
-6
lines changed

guide/src/migration.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Before:
5757
struct MyWrapper<T>(T);
5858
5959
impl<'py, T> FromPyObject<'py> for MyWrapper<T>
60-
where
60+
where
6161
T: FromPyObject<'py>
6262
{
6363
fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
@@ -66,7 +66,7 @@ where
6666
}
6767
```
6868

69-
After:
69+
After:
7070
```rust
7171
# use pyo3::prelude::*;
7272
# #[allow(dead_code)]
@@ -133,6 +133,12 @@ This is very similar to `serde`s [`Deserialize`] and [`DeserializeOwned`] traits
133133
[`DeserializeOwned`]: https://docs.rs/serde/latest/serde/de/trait.DeserializeOwned.html
134134
</details>
135135

136+
## `PyTypeCheck` is now an `unsafe trait`
137+
138+
Because `PyTypeCheck` is the trait used to guard the `.cast()` functions to treat Python objects as specific concrete types, the trait is `unsafe` to implement.
139+
140+
This should always have been the case, it was an unfortunate omission from its original implementation which is being corrected in this release.
141+
136142
## from 0.25.* to 0.26
137143
### Rename of `Python::with_gil`, `Python::allow_threads`, and `pyo3::prepare_freethreaded_python`
138144
<details open>

newsfragments/5473.changed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make `PyTypeCheck` an `unsafe trait`.

src/type_object.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ pub trait PySizedLayout<T>: PyLayout<T> + Sized {}
3535
///
3636
/// Implementations must provide an implementation for `type_object_raw` which infallibly produces a
3737
/// non-null pointer to the corresponding Python type object.
38+
///
39+
/// `is_type_of` must only return true for objects which can safely be treated as instances of `Self`.
40+
///
41+
/// `is_exact_type_of` must only return true for objects whose type is exactly `Self`.
3842
pub unsafe trait PyTypeInfo: Sized {
3943
/// Class name.
4044
const NAME: &'static str;
@@ -85,7 +89,13 @@ pub unsafe trait PyTypeInfo: Sized {
8589
}
8690

8791
/// Implemented by types which can be used as a concrete Python type inside `Py<T>` smart pointers.
88-
pub trait PyTypeCheck {
92+
///
93+
/// # Safety
94+
///
95+
/// This trait is used to determine whether [`Bound::cast`] and similar functions can safely cast
96+
/// to a concrete type. The implementor is responsible for ensuring that `type_check` only returns
97+
/// true for objects which can safely be treated as Python instances of `Self`.
98+
pub unsafe trait PyTypeCheck {
8999
/// Name of self. This is used in error messages, for example.
90100
#[deprecated(
91101
since = "0.27.0",
@@ -108,7 +118,7 @@ pub trait PyTypeCheck {
108118
fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny>;
109119
}
110120

111-
impl<T> PyTypeCheck for T
121+
unsafe impl<T> PyTypeCheck for T
112122
where
113123
T: PyTypeInfo,
114124
{

src/types/weakref/anyref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pyobject_native_type_named!(PyWeakref);
1818
// #[cfg(not(Py_LIMITED_API))]
1919
// pyobject_native_type_sized!(PyWeakref, ffi::PyWeakReference);
2020

21-
impl PyTypeCheck for PyWeakref {
21+
unsafe impl PyTypeCheck for PyWeakref {
2222
const NAME: &'static str = "weakref";
2323

2424
#[cfg(feature = "experimental-inspect")]

src/types/weakref/proxy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pyobject_native_type_named!(PyWeakrefProxy);
2020
// #[cfg(not(Py_LIMITED_API))]
2121
// pyobject_native_type_sized!(PyWeakrefProxy, ffi::PyWeakReference);
2222

23-
impl PyTypeCheck for PyWeakrefProxy {
23+
unsafe impl PyTypeCheck for PyWeakrefProxy {
2424
const NAME: &'static str = "weakref.ProxyTypes";
2525

2626
#[cfg(feature = "experimental-inspect")]

0 commit comments

Comments
 (0)