Skip to content

bump MSRV to 1.74 #5171

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

Merged
merged 14 commits into from
Jun 20, 2025
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
python-version: "3.13"
- name: resolve MSRV
id: resolve-msrv
run: echo MSRV=`python -c 'import tomllib; print(tomllib.load(open("Cargo.toml", "rb"))["package"]["rust-version"])'` >> $GITHUB_OUTPUT
run: echo MSRV=`python -c 'import tomllib; print(tomllib.load(open("Cargo.toml", "rb"))["workspace"]["package"]["rust-version"])'` >> $GITHUB_OUTPUT

semver-checks:
if: github.ref != 'refs/heads/main'
Expand Down
18 changes: 15 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,23 @@ repository = "https://github.com/pyo3/pyo3"
documentation = "https://docs.rs/crate/pyo3/"
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"]
exclude = [
"/.gitignore",
".cargo/config",
"/codecov.yml",
"/Makefile",
"/pyproject.toml",
"/noxfile.py",
"/.github",
"/tests/test_compile_error.rs",
"/tests/ui",
]
edition = "2021"
rust-version = "1.63"
rust-version.workspace = true

[dependencies]
libc = "0.2.62"
memoffset = "0.9"
once_cell = "1.13"

# ffi bindings to the python interpreter, split into a separate crate so they can be used independently
pyo3-ffi = { path = "pyo3-ffi", version = "=0.25.0" }
Expand Down Expand Up @@ -140,6 +149,7 @@ full = [
"eyre",
"hashbrown",
"indexmap",
"jiff-02",
"lock_api",
"num-bigint",
"num-complex",
Expand All @@ -150,6 +160,7 @@ full = [
"rust_decimal",
"serde",
"smallvec",
"time",
"uuid",
]

Expand All @@ -163,6 +174,7 @@ members = [
"pytests",
"examples",
]
package.rust-version = "1.74"

[package.metadata.docs.rs]
no-default-features = true
Expand Down
1 change: 0 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ fn configure_pyo3() -> Result<()> {
println!("{cfg}")
}

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

// Make `cargo test` etc work on macOS with Xcode bundled Python
Expand Down
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "pyo3-examples"
version = "0.0.0"
publish = false
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[dev-dependencies]
pyo3 = { path = "..", features = ["auto-initialize", "extension-module"] }
Expand Down
2 changes: 1 addition & 1 deletion examples/decorator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "decorator"
version = "0.1.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[lib]
name = "decorator"
Expand Down
2 changes: 1 addition & 1 deletion examples/getitem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "getitem"
version = "0.1.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[lib]
name = "getitem"
Expand Down
2 changes: 1 addition & 1 deletion examples/maturin-starter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "maturin-starter"
version = "0.1.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[lib]
name = "maturin_starter"
Expand Down
6 changes: 3 additions & 3 deletions examples/plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
name = "plugin_example"
version = "0.1.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[dependencies]
pyo3={path="../../", features=["macros"]}
plugin_api={path="plugin_api"}
pyo3 = { path = "../../", features = ["macros"] }
plugin_api = { path = "plugin_api" }


[workspace]
2 changes: 1 addition & 1 deletion examples/setuptools-rust-starter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "setuptools-rust-starter"
version = "0.1.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[lib]
name = "setuptools_rust_starter"
Expand Down
2 changes: 1 addition & 1 deletion examples/word-count/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "word-count"
version = "0.1.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[lib]
name = "word_count"
Expand Down
2 changes: 2 additions & 0 deletions newsfragments/5171.packaging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Update MSRV to 1.74.
Drop `once_cell` dependency.
28 changes: 4 additions & 24 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from contextlib import contextmanager
import json
import os
import re
Expand All @@ -7,6 +6,7 @@
import sys
import sysconfig
import tempfile
from contextlib import contextmanager
from functools import lru_cache
from glob import glob
from pathlib import Path
Expand All @@ -21,7 +21,6 @@
Tuple,
)

import nox
import nox.command

try:
Expand Down Expand Up @@ -460,14 +459,6 @@ def docs(session: nox.Session) -> None:

features = "full"

if get_rust_version()[:2] >= (1, 67):
# time needs MSRC 1.67+
features += ",time"

if get_rust_version()[:2] >= (1, 70):
# jiff needs MSRC 1.70+
features += ",jiff-02"

shutil.rmtree(PYO3_DOCS_TARGET, ignore_errors=True)
_run_cargo(
session,
Expand Down Expand Up @@ -670,10 +661,7 @@ def set_msrv_package_versions(session: nox.Session):
*(Path(p).parent for p in glob("examples/*/Cargo.toml")),
*(Path(p).parent for p in glob("pyo3-ffi/examples/*/Cargo.toml")),
)
min_pkg_versions = {
"trybuild": "1.0.89",
"allocator-api2": "0.2.10",
}
min_pkg_versions = {}

# run cargo update first to ensure that everything is at highest
# possible version, so that this matches what CI will resolve to.
Expand Down Expand Up @@ -854,8 +842,8 @@ def update_ui_tests(session: nox.Session):
env["TRYBUILD"] = "overwrite"
command = ["test", "--test", "test_compile_error"]
_run_cargo(session, *command, env=env)
_run_cargo(session, *command, "--features=full,jiff-02,time", env=env)
_run_cargo(session, *command, "--features=abi3,full,jiff-02,time", env=env)
_run_cargo(session, *command, "--features=full", env=env)
_run_cargo(session, *command, "--features=abi3,full", env=env)


@nox.session(name="test-introspection")
Expand Down Expand Up @@ -925,14 +913,6 @@ def _get_feature_sets() -> Tuple[Optional[str], ...]:
# multiple-pymethods not supported on wasm
features += ",multiple-pymethods"

if get_rust_version()[:2] >= (1, 67):
# time needs MSRC 1.67+
features += ",time"

if get_rust_version()[:2] >= (1, 70):
# jiff needs MSRC 1.70+
features += ",jiff-02"

if is_rust_nightly():
features += ",nightly"

Expand Down
3 changes: 1 addition & 2 deletions pyo3-build-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ repository = "https://github.com/pyo3/pyo3"
categories = ["api-bindings", "development-tools::ffi"]
license = "MIT OR Apache-2.0"
edition = "2021"
rust-version = "1.63"
rust-version.workspace = true

[dependencies]
once_cell = "1"
python3-dll-a = { version = "0.2.12", optional = true }
target-lexicon = "0.13"

Expand Down
4 changes: 2 additions & 2 deletions pyo3-build-config/src/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ fn have_python_interpreter() -> bool {
/// Must be called from a PyO3 crate build script.
fn is_abi3() -> bool {
cargo_env_var("CARGO_FEATURE_ABI3").is_some()
|| env_var("PYO3_USE_ABI3_FORWARD_COMPATIBILITY").map_or(false, |os_str| os_str == "1")
|| env_var("PYO3_USE_ABI3_FORWARD_COMPATIBILITY").is_some_and(|os_str| os_str == "1")
}

/// Gets the minimum supported Python version from PyO3 `abi3-py*` features.
Expand Down Expand Up @@ -1464,7 +1464,7 @@ fn search_lib_dir(path: impl AsRef<Path>, cross: &CrossCompileConfig) -> Result<
sysconfig_paths.extend(match &f {
// Python 3.7+ sysconfigdata with platform specifics
Ok(f) if starts_with(f, "_sysconfigdata_") && ends_with(f, "py") => vec![f.path()],
Ok(f) if f.metadata().map_or(false, |metadata| metadata.is_dir()) => {
Ok(f) if f.metadata().is_ok_and(|metadata| metadata.is_dir()) => {
let file_name = f.file_name();
let file_name = file_name.to_string_lossy();
if file_name == "build" || file_name == "lib" {
Expand Down
16 changes: 5 additions & 11 deletions pyo3-build-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ use std::{
path::{Path, PathBuf},
};

use std::{env, process::Command, str::FromStr};

use once_cell::sync::OnceCell;
use std::{env, process::Command, str::FromStr, sync::OnceLock};

pub use impl_::{
cross_compiling_from_to, find_all_sysconfigdata, parse_sysconfigdata, BuildFlag, BuildFlags,
Expand Down Expand Up @@ -109,10 +107,10 @@ fn _add_python_framework_link_args(

/// Loads the configuration determined from the build environment.
///
/// Because this will never change in a given compilation run, this is cached in a `once_cell`.
/// Because this will never change in a given compilation run, this is cached in a `OnceLock`.
#[cfg(feature = "resolve-config")]
pub fn get() -> &'static InterpreterConfig {
static CONFIG: OnceCell<InterpreterConfig> = OnceCell::new();
static CONFIG: OnceLock<InterpreterConfig> = OnceLock::new();
CONFIG.get_or_init(|| {
// Check if we are in a build script and cross compiling to a different target.
let cross_compile_config_path = resolve_cross_compile_config_path();
Expand Down Expand Up @@ -183,10 +181,6 @@ fn print_feature_cfg(minor_version_required: u32, cfg: &str) {
/// so this function is unstable.
#[doc(hidden)]
pub fn print_feature_cfgs() {
print_feature_cfg(70, "rustc_has_once_lock");
print_feature_cfg(70, "cargo_toml_lints");
print_feature_cfg(71, "rustc_has_extern_c_unwind");
print_feature_cfg(74, "invalid_from_utf8_lint");
print_feature_cfg(79, "c_str_lit");
// Actually this is available on 1.78, but we should avoid
// https://github.com/rust-lang/rust/issues/124651 just in case
Expand All @@ -201,7 +195,7 @@ pub fn print_feature_cfgs() {
/// - <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg>
#[doc(hidden)]
pub fn print_expected_cfgs() {
if rustc_minor_version().map_or(false, |version| version < 80) {
if rustc_minor_version().is_some_and(|version| version < 80) {
// rustc 1.80.0 stabilized `rustc-check-cfg` feature, don't emit before
return;
}
Expand Down Expand Up @@ -280,7 +274,7 @@ pub mod pyo3_build_script_impl {
}

fn rustc_minor_version() -> Option<u32> {
static RUSTC_MINOR_VERSION: OnceCell<Option<u32>> = OnceCell::new();
static RUSTC_MINOR_VERSION: OnceLock<Option<u32>> = OnceLock::new();
*RUSTC_MINOR_VERSION.get_or_init(|| {
let rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
Expand Down
6 changes: 3 additions & 3 deletions pyo3-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ categories = ["api-bindings", "development-tools::ffi"]
license = "MIT OR Apache-2.0"
edition = "2021"
links = "python"
rust-version = "1.63"
rust-version.workspace = true

[dependencies]
libc = "0.2.62"
Expand Down Expand Up @@ -51,8 +51,8 @@ workspace = true

[package.metadata.cpython]
min-version = "3.7"
max-version = "3.14" # inclusive
max-version = "3.14" # inclusive

[package.metadata.pypy]
min-version = "3.9"
max-version = "3.11" # inclusive
max-version = "3.11" # inclusive
5 changes: 2 additions & 3 deletions pyo3-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> {
= help: The free-threaded build of CPython does not support the limited API so this check cannot be suppressed.",
interpreter_config.version, versions.max, std::env::var("CARGO_PKG_VERSION").unwrap()
);
ensure!(env_var("PYO3_USE_ABI3_FORWARD_COMPATIBILITY").map_or(false, |os_str| os_str == "1"),
ensure!(env_var("PYO3_USE_ABI3_FORWARD_COMPATIBILITY").is_some_and(|os_str| os_str == "1"),
"the configured Python interpreter version ({}) is newer than PyO3's maximum supported version ({})\n\
= help: please check if an updated version of PyO3 is available. Current version: {}\n\
= help: set PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 to suppress this check and build anyway using the stable ABI",
Expand Down Expand Up @@ -192,7 +192,7 @@ fn emit_link_config(interpreter_config: &InterpreterConfig) -> Result<()> {
fn configure_pyo3() -> Result<()> {
let interpreter_config = resolve_interpreter_config()?;

if env_var("PYO3_PRINT_CONFIG").map_or(false, |os_str| os_str == "1") {
if env_var("PYO3_PRINT_CONFIG").is_some_and(|os_str| os_str == "1") {
print_config_and_exit(&interpreter_config);
}

Expand All @@ -215,7 +215,6 @@ fn configure_pyo3() -> Result<()> {
println!("{line}");
}

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

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion pyo3-ffi/examples/sequential/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "sequential"
version = "0.1.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[lib]
name = "sequential"
Expand Down
2 changes: 1 addition & 1 deletion pyo3-ffi/examples/string-sum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "string_sum"
version = "0.1.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.74"

[lib]
name = "string_sum"
Expand Down
1 change: 1 addition & 0 deletions pyo3-ffi/src/cpython/genobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct PyGenObject {
pub gi_weakreflist: *mut PyObject,
pub gi_name: *mut PyObject,
pub gi_qualname: *mut PyObject,
#[allow(private_interfaces)]
pub gi_exc_state: crate::cpython::pystate::_PyErr_StackItem,
#[cfg(Py_3_11)]
pub gi_origin_or_finalizer: *mut PyObject,
Expand Down
3 changes: 1 addition & 2 deletions pyo3-ffi/src/cpython/pystate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ pub const PyTrace_OPCODE: c_int = 7;
#[cfg(not(PyPy))]
#[repr(C)]
#[derive(Clone, Copy)]
#[doc(hidden)] // TODO should be able to make pub(crate) after MSRV 1.74
pub struct _PyErr_StackItem {
pub(crate) struct _PyErr_StackItem {
#[cfg(not(Py_3_11))]
exc_type: *mut PyObject,
exc_value: *mut PyObject,
Expand Down
Loading
Loading