Skip to content
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

Update MSRV to 1.63 #4129

Merged
merged 4 commits into from
Apr 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
name: Prepare LD_LIBRARY_PATH (Ubuntu only)
run: echo LD_LIBRARY_PATH=${pythonLocation}/lib >> $GITHUB_ENV

- if: inputs.rust == '1.56.0'
- if: inputs.rust == '1.63.0'
name: Prepare minimal package versions (MSRV only)
run: nox -s set-minimal-package-versions

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.56.0
toolchain: 1.63.0
targets: x86_64-unknown-linux-gnu
components: rust-src
- uses: actions/setup-python@v5
Expand Down Expand Up @@ -255,7 +255,7 @@ jobs:
]
include:
# Test minimal supported Rust version
- rust: 1.56.0
- rust: 1.63.0
python-version: "3.12"
platform:
{
Expand Down
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ categories = ["api-bindings", "development-tools::ffi"]
license = "MIT OR Apache-2.0"
exclude = ["/.gitignore", ".cargo/config", "/codecov.yml", "/Makefile", "/pyproject.toml", "/noxfile.py", "/.github", "/tests/test_compile_error.rs", "/tests/ui"]
edition = "2021"
rust-version = "1.56"
rust-version = "1.63"

[dependencies]
cfg-if = "1.0"
libc = "0.2.62"
parking_lot = ">= 0.11, < 0.13"
memoffset = "0.9"
portable-atomic = "1.0"

# ffi bindings to the python interpreter, split into a separate crate so they can be used independently
pyo3-ffi = { path = "pyo3-ffi", version = "=0.21.2" }
Expand All @@ -46,6 +44,9 @@ rust_decimal = { version = "1.0.0", default-features = false, optional = true }
serde = { version = "1.0", optional = true }
smallvec = { version = "1.0", optional = true }

[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
portable-atomic = "1.0"

[dev-dependencies]
assert_approx_eq = "1.1.0"
chrono = "0.4.25"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![benchmark](https://img.shields.io/badge/benchmark-✓-Green?logo=github)](https://pyo3.rs/dev/bench/)
[![codecov](https://img.shields.io/codecov/c/gh/PyO3/pyo3?logo=codecov)](https://codecov.io/gh/PyO3/pyo3)
[![crates.io](https://img.shields.io/crates/v/pyo3?logo=rust)](https://crates.io/crates/pyo3)
[![minimum rustc 1.56](https://img.shields.io/badge/rustc-1.56+-blue?logo=rust)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
[![minimum rustc 1.63](https://img.shields.io/badge/rustc-1.63+-blue?logo=rust)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
[![discord server](https://img.shields.io/discord/1209263839632424990?logo=discord)](https://discord.gg/33kcChzH7f)
[![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green?logo=github)](https://github.com/PyO3/pyo3/blob/main/Contributing.md)

Expand All @@ -18,7 +18,7 @@

PyO3 supports the following software versions:
- Python 3.7 and up (CPython, PyPy, and GraalPy)
- Rust 1.56 and up
- Rust 1.63 and up

You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn.

Expand Down
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn configure_pyo3() -> Result<()> {
println!("{}", cfg)
}

// Emit cfgs like `thread_local_const_init`
// Emit cfgs like `invalid_from_utf8_lint`
print_feature_cfgs();

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion guide/src/building-and-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ rustflags = [
]
```

Alternatively, on rust >= 1.56, one can include in `build.rs`:
Alternatively, one can include in `build.rs`:

```rust
fn main() {
Expand Down
2 changes: 1 addition & 1 deletion guide/src/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ To get started using PyO3 you will need three things: a Rust toolchain, a Python

## Rust

First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.56.
First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.63.

If you can run `rustc --version` and the version is new enough you're good to go!

Expand Down
1 change: 1 addition & 0 deletions newsfragments/4129.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Raised the MSRV to 1.63
21 changes: 5 additions & 16 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,22 +557,11 @@ def set_minimal_package_versions(session: nox.Session):
"examples/word-count",
)
min_pkg_versions = {
"rust_decimal": "1.26.1",
"csv": "1.1.6",
"indexmap": "1.6.2",
"hashbrown": "0.9.1",
"log": "0.4.17",
"once_cell": "1.17.2",
"rayon": "1.6.1",
"rayon-core": "1.10.2",
"regex": "1.7.3",
"proptest": "1.0.0",
"chrono": "0.4.25",
"byteorder": "1.4.3",
"crossbeam-channel": "0.5.8",
"crossbeam-deque": "0.8.3",
"crossbeam-epoch": "0.9.15",
"crossbeam-utils": "0.8.16",
"regex": "1.9.6",
"proptest": "1.2.0",
"trybuild": "1.0.89",
"eyre": "0.6.8",
"allocator-api2": "0.2.10",
}

# run cargo update first to ensure that everything is at highest
Expand Down
5 changes: 0 additions & 5 deletions pyo3-build-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,6 @@ pub fn print_feature_cfgs() {

let rustc_minor_version = rustc_minor_version().unwrap_or(0);

// Enable use of const initializer for thread_local! on Rust 1.59 and greater
if rustc_minor_version >= 59 {
println!("cargo:rustc-cfg=thread_local_const_init");
}

// invalid_from_utf8 lint was added in Rust 1.74
if rustc_minor_version >= 74 {
println!("cargo:rustc-cfg=invalid_from_utf8_lint");
Expand Down
2 changes: 1 addition & 1 deletion pyo3-ffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Manual][capi] for up-to-date documentation.

PyO3 supports the following software versions:
- Python 3.7 and up (CPython and PyPy)
- Rust 1.56 and up
- Rust 1.63 and up

# Example: Building Python Native modules

Expand Down
2 changes: 1 addition & 1 deletion pyo3-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ fn configure_pyo3() -> Result<()> {
println!("{}", line);
}

// Emit cfgs like `thread_local_const_init`
// Emit cfgs like `invalid_from_utf8_lint`
print_feature_cfgs();

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion pyo3-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
//!
//! PyO3 supports the following software versions:
//! - Python 3.7 and up (CPython and PyPy)
//! - Rust 1.56 and up
//! - Rust 1.63 and up
//!
//! # Example: Building Python Native modules
//!
Expand Down
9 changes: 4 additions & 5 deletions src/coroutine/cancel.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::{Py, PyAny, PyObject};
use parking_lot::Mutex;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, Waker};

#[derive(Debug, Default)]
Expand All @@ -25,12 +24,12 @@ impl CancelHandle {

/// Returns whether the associated coroutine has been cancelled.
pub fn is_cancelled(&self) -> bool {
self.0.lock().exception.is_some()
self.0.lock().unwrap().exception.is_some()
}

/// Poll to retrieve the exception thrown in the associated coroutine.
pub fn poll_cancelled(&mut self, cx: &mut Context<'_>) -> Poll<PyObject> {
let mut inner = self.0.lock();
let mut inner = self.0.lock().unwrap();
if let Some(exc) = inner.exception.take() {
return Poll::Ready(exc);
}
Expand Down Expand Up @@ -69,7 +68,7 @@ pub struct ThrowCallback(Arc<Mutex<Inner>>);

impl ThrowCallback {
pub(super) fn throw(&self, exc: Py<PyAny>) {
let mut inner = self.0.lock();
let mut inner = self.0.lock().unwrap();
inner.exception = Some(exc);
if let Some(waker) = inner.waker.take() {
waker.wake();
Expand Down
67 changes: 29 additions & 38 deletions src/gil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,16 @@

use crate::impl_::not_send::{NotSend, NOT_SEND};
use crate::{ffi, Python};
use parking_lot::{const_mutex, Mutex, Once};
use std::cell::Cell;
#[cfg(debug_assertions)]
use std::cell::RefCell;
#[cfg(not(debug_assertions))]
use std::cell::UnsafeCell;
use std::{mem, ptr::NonNull};
use std::{mem, ptr::NonNull, sync};

static START: Once = Once::new();
static START: sync::Once = sync::Once::new();

cfg_if::cfg_if! {
if #[cfg(thread_local_const_init)] {
use std::thread_local as thread_local_const_init;
} else {
macro_rules! thread_local_const_init {
($($(#[$attr:meta])* static $name:ident: $ty:ty = const { $init:expr };)*) => (
thread_local! { $($(#[$attr])* static $name: $ty = $init;)* }
)
}
}
}

thread_local_const_init! {
std::thread_local! {
/// This is an internal counter in pyo3 monitoring whether this thread has the GIL.
///
/// It will be incremented whenever a GILGuard or GILPool is created, and decremented whenever
Expand Down Expand Up @@ -249,26 +236,26 @@ type PyObjVec = Vec<NonNull<ffi::PyObject>>;
/// Thread-safe storage for objects which were inc_ref / dec_ref while the GIL was not held.
struct ReferencePool {
// .0 is INCREFs, .1 is DECREFs
pointer_ops: Mutex<(PyObjVec, PyObjVec)>,
pointer_ops: sync::Mutex<(PyObjVec, PyObjVec)>,
}

impl ReferencePool {
const fn new() -> Self {
Self {
pointer_ops: const_mutex((Vec::new(), Vec::new())),
pointer_ops: sync::Mutex::new((Vec::new(), Vec::new())),
}
}

fn register_incref(&self, obj: NonNull<ffi::PyObject>) {
self.pointer_ops.lock().0.push(obj);
self.pointer_ops.lock().unwrap().0.push(obj);
}

fn register_decref(&self, obj: NonNull<ffi::PyObject>) {
self.pointer_ops.lock().1.push(obj);
self.pointer_ops.lock().unwrap().1.push(obj);
}

fn update_counts(&self, _py: Python<'_>) {
let mut ops = self.pointer_ops.lock();
let mut ops = self.pointer_ops.lock().unwrap();
if ops.0.is_empty() && ops.1.is_empty() {
return;
}
Expand Down Expand Up @@ -523,9 +510,9 @@ mod tests {
use super::{gil_is_acquired, GIL_COUNT, OWNED_OBJECTS, POOL};
use crate::types::any::PyAnyMethods;
use crate::{ffi, gil, PyObject, Python};
#[cfg(not(target_arch = "wasm32"))]
use parking_lot::{const_mutex, Condvar, Mutex};
use std::ptr::NonNull;
#[cfg(not(target_arch = "wasm32"))]
use std::sync;

fn get_object(py: Python<'_>) -> PyObject {
py.eval_bound("object()", None, None).unwrap().unbind()
Expand All @@ -543,6 +530,7 @@ mod tests {
!POOL
.pointer_ops
.lock()
.unwrap()
.0
.contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) })
}
Expand All @@ -551,6 +539,7 @@ mod tests {
!POOL
.pointer_ops
.lock()
.unwrap()
.1
.contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) })
}
Expand All @@ -559,6 +548,7 @@ mod tests {
fn pool_dec_refs_contains(obj: &PyObject) -> bool {
POOL.pointer_ops
.lock()
.unwrap()
.1
.contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) })
}
Expand Down Expand Up @@ -671,8 +661,8 @@ mod tests {
Python::with_gil(|py| {
assert_eq!(obj.get_refcnt(py), 1);
let non_null = unsafe { NonNull::new_unchecked(obj.as_ptr()) };
assert!(!POOL.pointer_ops.lock().0.contains(&non_null));
assert!(!POOL.pointer_ops.lock().1.contains(&non_null));
assert!(!POOL.pointer_ops.lock().unwrap().0.contains(&non_null));
assert!(!POOL.pointer_ops.lock().unwrap().1.contains(&non_null));
});
}

Expand Down Expand Up @@ -770,29 +760,30 @@ mod tests {

#[cfg(not(target_arch = "wasm32"))]
struct Event {
set: Mutex<bool>,
wait: Condvar,
set: sync::Mutex<bool>,
wait: sync::Condvar,
}

#[cfg(not(target_arch = "wasm32"))]
impl Event {
const fn new() -> Self {
Self {
set: const_mutex(false),
wait: Condvar::new(),
set: sync::Mutex::new(false),
wait: sync::Condvar::new(),
}
}

fn set(&self) {
*self.set.lock() = true;
*self.set.lock().unwrap() = true;
self.wait.notify_all();
}

fn wait(&self) {
let mut set = self.set.lock();
while !*set {
self.wait.wait(&mut set);
}
drop(
self.wait
.wait_while(self.set.lock().unwrap(), |s| !*s)
.unwrap(),
);
}
}

Expand Down Expand Up @@ -891,16 +882,16 @@ mod tests {

// The pointer should appear once in the incref pool, and once in the
// decref pool (for the clone being created and also dropped)
assert!(POOL.pointer_ops.lock().0.contains(&ptr));
assert!(POOL.pointer_ops.lock().1.contains(&ptr));
assert!(POOL.pointer_ops.lock().unwrap().0.contains(&ptr));
assert!(POOL.pointer_ops.lock().unwrap().1.contains(&ptr));

(obj, count, ptr)
});

Python::with_gil(|py| {
// Acquiring the gil clears the pool
assert!(!POOL.pointer_ops.lock().0.contains(&ptr));
assert!(!POOL.pointer_ops.lock().1.contains(&ptr));
assert!(!POOL.pointer_ops.lock().unwrap().0.contains(&ptr));
assert!(!POOL.pointer_ops.lock().unwrap().1.contains(&ptr));

// Overall count is still unchanged
assert_eq!(count, obj.get_refcnt(py));
Expand Down
10 changes: 9 additions & 1 deletion src/impl_/pymodule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ use std::{cell::UnsafeCell, marker::PhantomData};
#[cfg(all(
not(any(PyPy, GraalPy)),
Py_3_9,
not(all(windows, Py_LIMITED_API, not(Py_3_10)))
not(all(windows, Py_LIMITED_API, not(Py_3_10))),
not(target_has_atomic = "64"),
))]
use portable_atomic::{AtomicI64, Ordering};
#[cfg(all(
not(any(PyPy, GraalPy)),
Py_3_9,
not(all(windows, Py_LIMITED_API, not(Py_3_10))),
target_has_atomic = "64",
))]
use std::sync::atomic::{AtomicI64, Ordering};
adamreichold marked this conversation as resolved.
Show resolved Hide resolved

#[cfg(not(any(PyPy, GraalPy)))]
use crate::exceptions::PyImportError;
Expand Down