-
Notifications
You must be signed in to change notification settings - Fork 776
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use RefCell to enforce aliasing rules #342
Comments
Another issue closely related to this are mutable Python native types where PyO3 returns references to the internal buffer, e.g.: extern crate pyo3;
use pyo3::{prelude::*, wrap_pyfunction};
#[pyfunction]
fn sum_as_string() -> PyResult<()> {
let gil = Python::acquire_gil();
let py = gil.python();
let byte_arr = pyo3::types::PyByteArray::new(py, &[1, 2, 3]);
let byte_arr_data = byte_arr.data();
println!("Pre mut: {:#?}", byte_arr_data);
use pyo3::types::IntoPyDict;
let d = [("byte_arr", byte_arr)].into_py_dict(py);
py.run("byte_arr.clear()", None, Some(&d)).unwrap();
println!("oh shit ...");
println!("Post mut: {:#?}", byte_arr_data);
Ok(())
}
/// This module is a python module implemented in Rust.
#[pymodule]
fn pyo3bug(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(sum_as_string))?;
Ok(())
}
I don't think this could be fixed using just a |
Here's what /// Gets the buffer memory as a slice.
///
/// This function succeeds if:
/// * the buffer format is compatible with `T`
/// * alignment and size of buffer elements is matching the expectations for type `T`
/// * the buffer is C-style contiguous
///
/// The returned slice uses type `Cell<T>` because it's theoretically possible for any call into the Python runtime
/// to modify the values in the slice.
pub fn as_slice<'a, T: Element>(
&'a self,
_py: Python<'a>,
) -> Option<&'a [ReadOnlyCell<T>]>;
/// Gets the buffer memory as a slice.
///
/// This function succeeds if:
/// * the buffer is not read-only
/// * the buffer format is compatible with `T`
/// * alignment and size of buffer elements is matching the expectations for type `T`
/// * the buffer is C-style contiguous
///
/// The returned slice uses type `Cell<T>` because it's theoretically possible for any call into the Python runtime
/// to modify the values in the slice.
pub fn as_mut_slice<'a, T: Element>(
&'a self,
_py: Python<'a>,
) -> Option<&'a [cell::Cell<T>]> |
Given that all python objects happen to have a reference counter in them already, this should be fairly easy to fix in the glue that exists between Python and Rust. Any attempt to downcast |
Possibly. I suspect that it would be impractical to use in practice. A refcount of 1 is nigh unattainable in any sort of realistic scenario, especially in the context of calling Rust from Python. Even something like: def f0(x): return f1(x)
def f1(x): return f2(x)
def f2(x): return x needs to produces additional references to That said, I'm not certain what happens precisely when the interpreter calls methods and functions defined in extension modules. I know that the |
If we replaced the impl PyByteArray {
fn data<'p>(&'p self, py: &'p Python) -> &'p [u8];
fn data<'p>(&'p self, py: &'p mut Python) -> &mut 'p [u8];
} In other words,
|
Currently pyo3 allows to break rust's aliasing guarantees, i.e. you can get two mutable references to the same object. This is not a big issue because you can only have those two references on the same thread, but this still needs to be fixed eventually. See this capter in wasm bindgen's guide for a good write-up on the why and how.
The text was updated successfully, but these errors were encountered: