msrv: bump to 1.48

This commit is contained in:
David Hewitt 2021-11-18 11:38:47 +00:00
parent f29a8e1b91
commit 6a65f98bd2
20 changed files with 82 additions and 113 deletions

View File

@ -123,7 +123,7 @@ jobs:
rust-target: "x86_64-apple-darwin", rust-target: "x86_64-apple-darwin",
} }
# Test minimal supported Rust version # Test minimal supported Rust version
- rust: 1.41.1 - rust: 1.48.0
python-version: "3.10" python-version: "3.10"
platform: platform:
{ {

View File

@ -6,6 +6,14 @@ PyO3 versions, please see the [migration guide](https://pyo3.rs/latest/migration
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Packaging
- Update MSRV to Rust 1.48. [#2004](https://github.com/PyO3/pyo3/pull/2004)
- Update `indoc` optional dependency to 1.0. [#2004](https://github.com/PyO3/pyo3/pull/2004)
- Update `paste` optional dependency to 1.0. [#2004](https://github.com/PyO3/pyo3/pull/2004)
## [0.15.1] - 2021-11-19 ## [0.15.1] - 2021-11-19
### Added ### Added

View File

@ -21,9 +21,8 @@ parking_lot = "0.11.0"
# support crates for macros feature # support crates for macros feature
pyo3-macros = { path = "pyo3-macros", version = "=0.15.1", optional = true } pyo3-macros = { path = "pyo3-macros", version = "=0.15.1", optional = true }
# indoc must stay at 0.3.x for Rust 1.41 compatibility indoc = { version = "1.0.3", optional = true }
indoc = { version = "0.3.6", optional = true } paste = { version = "1.0.6", optional = true }
paste = { version = "0.1.18", optional = true }
unindent = { version = "0.1.4", optional = true } unindent = { version = "0.1.4", optional = true }
# support crate for multiple-pymethods feature # support crate for multiple-pymethods feature
@ -32,7 +31,7 @@ inventory = { version = "0.1.4", optional = true }
# crate integrations that can be added using the eponymous features # crate integrations that can be added using the eponymous features
anyhow = { version = "1.0", optional = true } anyhow = { version = "1.0", optional = true }
eyre = { version = ">= 0.4, < 0.7" , optional = true } eyre = { version = ">= 0.4, < 0.7", optional = true }
hashbrown = { version = ">= 0.9, < 0.12", optional = true } hashbrown = { version = ">= 0.9, < 0.12", optional = true }
indexmap = { version = ">= 1.6, < 1.8", optional = true } indexmap = { version = ">= 1.6, < 1.8", optional = true }
num-bigint = { version = "0.4", optional = true } num-bigint = { version = "0.4", optional = true }
@ -41,11 +40,7 @@ serde = { version = "1.0", optional = true }
[dev-dependencies] [dev-dependencies]
assert_approx_eq = "1.1.0" assert_approx_eq = "1.1.0"
# O.3.5 uses the matches! macro, which isn't compatible with Rust 1.41 criterion = "0.3.5"
criterion = "=0.3.4"
# half and bitflags use if/match in const fn, which isn't compatible with Rust 1.41
half = "=1.7.1"
bitflags = "=1.2.1"
trybuild = "1.0.49" trybuild = "1.0.49"
rustversion = "1.0" rustversion = "1.0"
# 1.0.0 requires Rust 1.50 # 1.0.0 requires Rust 1.50

View File

@ -4,7 +4,7 @@
[![benchmark](https://github.com/PyO3/pyo3/actions/workflows/bench.yml/badge.svg)](https://pyo3.rs/dev/bench/) [![benchmark](https://github.com/PyO3/pyo3/actions/workflows/bench.yml/badge.svg)](https://pyo3.rs/dev/bench/)
[![codecov](https://codecov.io/gh/PyO3/pyo3/branch/main/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3) [![codecov](https://codecov.io/gh/PyO3/pyo3/branch/main/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3)
[![crates.io](https://img.shields.io/crates/v/pyo3)](https://crates.io/crates/pyo3) [![crates.io](https://img.shields.io/crates/v/pyo3)](https://crates.io/crates/pyo3)
[![minimum rustc 1.41](https://img.shields.io/badge/rustc-1.41+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![minimum rustc 1.48](https://img.shields.io/badge/rustc-1.48+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
[![dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby) [![dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby)
[![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green)](https://github.com/PyO3/pyo3/blob/main/Contributing.md) [![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green)](https://github.com/PyO3/pyo3/blob/main/Contributing.md)
@ -18,7 +18,7 @@
PyO3 supports the following software versions: PyO3 supports the following software versions:
- Python 3.6 and up (CPython and PyPy) - Python 3.6 and up (CPython and PyPy)
- Rust 1.41 and up - Rust 1.48 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. 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.

View File

@ -352,15 +352,12 @@ impl<'a> FnSpec<'a> {
parse_method_receiver(first_arg) parse_method_receiver(first_arg)
}; };
#[allow(clippy::manual_strip)] // for strip_prefix replacement supporting rust < 1.45
// strip get_ or set_ // strip get_ or set_
let strip_fn_name = |prefix: &'static str| { let strip_fn_name = |prefix: &'static str| {
let ident = name.unraw().to_string(); name.unraw()
if ident.starts_with(prefix) { .to_string()
Some(syn::Ident::new(&ident[prefix.len()..], ident.span())) .strip_prefix(prefix)
} else { .map(|stripped| syn::Ident::new(stripped, name.span()))
None
}
}; };
let (fn_type, skip_first_arg, fixed_convention) = match fn_type_attr { let (fn_type, skip_first_arg, fixed_convention) = match fn_type_attr {

View File

@ -15,13 +15,11 @@ pub struct MethodProto {
} }
impl MethodProto { impl MethodProto {
// TODO: workaround for no unsized casts in const fn on Rust 1.45 (stable in 1.46)
const EMPTY_ARGS: &'static [&'static str] = &[];
pub const fn new(name: &'static str, proto: &'static str) -> Self { pub const fn new(name: &'static str, proto: &'static str) -> Self {
MethodProto { MethodProto {
name, name,
proto, proto,
args: MethodProto::EMPTY_ARGS, args: &[],
with_self: false, with_self: false,
with_result: true, with_result: true,
} }

View File

@ -399,14 +399,9 @@ pub fn impl_py_getter_def(cls: &syn::Type, property_type: PropertyType) -> Resul
/// Split an argument of pyo3::Python from the front of the arg list, if present /// Split an argument of pyo3::Python from the front of the arg list, if present
fn split_off_python_arg<'a>(args: &'a [FnArg<'a>]) -> (Option<&FnArg>, &[FnArg]) { fn split_off_python_arg<'a>(args: &'a [FnArg<'a>]) -> (Option<&FnArg>, &[FnArg]) {
if args match args {
.get(0) [py, args @ ..] if utils::is_python(py.ty) => (Some(py), args),
.map(|py| utils::is_python(py.ty)) args => (None, args),
.unwrap_or(false)
{
(Some(&args[0]), &args[1..])
} else {
(None, args)
} }
} }

View File

@ -62,8 +62,6 @@ pub fn option_type_argument(ty: &syn::Type) -> Option<&syn::Type> {
#[derive(Clone)] #[derive(Clone)]
pub struct PythonDoc(TokenStream); pub struct PythonDoc(TokenStream);
// TODO(#1782) use strip_prefix on Rust 1.45 or greater
#[allow(clippy::manual_strip)]
/// Collects all #[doc = "..."] attributes into a TokenStream evaluating to a null-terminated string /// Collects all #[doc = "..."] attributes into a TokenStream evaluating to a null-terminated string
/// e.g. concat!("...", "\n", "\0") /// e.g. concat!("...", "\n", "\0")
pub fn get_doc( pub fn get_doc(
@ -107,11 +105,11 @@ pub fn get_doc(
// Strip single left space from literal strings, if needed. // Strip single left space from literal strings, if needed.
// e.g. `/// Hello world` expands to #[doc = " Hello world"] // e.g. `/// Hello world` expands to #[doc = " Hello world"]
let doc_line = lit_str.value(); let doc_line = lit_str.value();
if doc_line.starts_with(' ') { doc_line
syn::LitStr::new(&doc_line[1..], lit_str.span()).to_tokens(tokens) .strip_prefix(' ')
} else { .map(|stripped| syn::LitStr::new(stripped, lit_str.span()))
lit_str.to_tokens(tokens) .unwrap_or(lit_str)
} .to_tokens(tokens);
} else { } else {
// This is probably a macro doc from Rust 1.54, e.g. #[doc = include_str!(...)] // This is probably a macro doc from Rust 1.54, e.g. #[doc = include_str!(...)]
token_stream.to_tokens(tokens) token_stream.to_tokens(tokens)

View File

@ -75,12 +75,7 @@ impl ElementType {
pub fn from_format(format: &CStr) -> ElementType { pub fn from_format(format: &CStr) -> ElementType {
match format.to_bytes() { match format.to_bytes() {
[char] | [b'@', char] => native_element_type_from_type_char(*char), [char] | [b'@', char] => native_element_type_from_type_char(*char),
[modifier, char] [modifier, char] if matches!(modifier, b'=' | b'<' | b'>' | b'!') => {
if (*modifier == b'='
|| *modifier == b'<'
|| *modifier == b'>'
|| *modifier == b'!') =>
{
standard_element_type_from_type_char(*char) standard_element_type_from_type_char(*char)
} }
_ => ElementType::Unknown, _ => ElementType::Unknown,

View File

@ -542,7 +542,6 @@ pub unsafe extern "C" fn alloc_with_freelist<T: PyClassWithFreeList>(
/// # Safety /// # Safety
/// - `obj` must be a valid pointer to an instance of T (not a subclass). /// - `obj` must be a valid pointer to an instance of T (not a subclass).
/// - The GIL must be held. /// - The GIL must be held.
#[allow(clippy::collapsible_if)] // for if cfg!
pub unsafe extern "C" fn free_with_freelist<T: PyClassWithFreeList>(obj: *mut c_void) { pub unsafe extern "C" fn free_with_freelist<T: PyClassWithFreeList>(obj: *mut c_void) {
let obj = obj as *mut ffi::PyObject; let obj = obj as *mut ffi::PyObject;
debug_assert_eq!( debug_assert_eq!(
@ -560,10 +559,9 @@ pub unsafe extern "C" fn free_with_freelist<T: PyClassWithFreeList>(obj: *mut c_
}; };
free(obj as *mut c_void); free(obj as *mut c_void);
if cfg!(Py_3_8) { #[cfg(Py_3_8)]
if ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE) != 0 { if ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE) != 0 {
ffi::Py_DECREF(ty as *mut ffi::PyObject); ffi::Py_DECREF(ty as *mut ffi::PyObject);
}
} }
} }
} }

View File

@ -52,7 +52,6 @@ extern "C" {
fn _Py_CheckRecursiveCall(_where: *mut c_char) -> c_int; fn _Py_CheckRecursiveCall(_where: *mut c_char) -> c_int;
} }
// TODO
// skipped Py_EnterRecursiveCall // skipped Py_EnterRecursiveCall
// skipped Py_LeaveRecursiveCall // skipped Py_LeaveRecursiveCall

View File

@ -69,33 +69,36 @@ pub(crate) fn gil_is_acquired() -> bool {
/// # } /// # }
/// ``` /// ```
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
#[allow(clippy::collapsible_if)] // for if cfg!
pub fn prepare_freethreaded_python() { pub fn prepare_freethreaded_python() {
// Protect against race conditions when Python is not yet initialized and multiple threads // Protect against race conditions when Python is not yet initialized and multiple threads
// concurrently call 'prepare_freethreaded_python()'. Note that we do not protect against // concurrently call 'prepare_freethreaded_python()'. Note that we do not protect against
// concurrent initialization of the Python runtime by other users of the Python C API. // concurrent initialization of the Python runtime by other users of the Python C API.
START.call_once_force(|_| unsafe { START.call_once_force(|_| unsafe {
if cfg!(not(Py_3_7)) { // Use call_once_force because if initialization panics, it's okay to try again.
// Use call_once_force because if initialization panics, it's okay to try again.
if ffi::Py_IsInitialized() != 0 {
if ffi::PyEval_ThreadsInitialized() == 0 {
// We can only safely initialize threads if this thread holds the GIL.
assert!(
!ffi::PyGILState_GetThisThreadState().is_null(),
"Python threading is not initialized and cannot be initialized by this \
thread, because it is not the thread which initialized Python."
);
ffi::PyEval_InitThreads();
}
} else {
ffi::Py_InitializeEx(0);
ffi::PyEval_InitThreads();
// Release the GIL. // TODO(#1782) - Python 3.6 legacy code
ffi::PyEval_SaveThread(); #[cfg(not(Py_3_7))]
if ffi::Py_IsInitialized() != 0 {
if ffi::PyEval_ThreadsInitialized() == 0 {
// We can only safely initialize threads if this thread holds the GIL.
assert!(
!ffi::PyGILState_GetThisThreadState().is_null(),
"Python threading is not initialized and cannot be initialized by this \
thread, because it is not the thread which initialized Python."
);
ffi::PyEval_InitThreads();
} }
} else if ffi::Py_IsInitialized() == 0 { } else {
// In Python 3.7 and up PyEval_InitThreads is irrelevant. ffi::Py_InitializeEx(0);
ffi::PyEval_InitThreads();
// Release the GIL.
ffi::PyEval_SaveThread();
}
// In Python 3.7 and up PyEval_InitThreads is irrelevant.
#[cfg(Py_3_7)]
if ffi::Py_IsInitialized() == 0 {
ffi::Py_InitializeEx(0); ffi::Py_InitializeEx(0);
// Release the GIL. // Release the GIL.
@ -134,7 +137,6 @@ pub fn prepare_freethreaded_python() {
/// # } /// # }
/// ``` /// ```
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
#[allow(clippy::collapsible_if)] // for if cfg!
pub unsafe fn with_embedded_python_interpreter<F, R>(f: F) -> R pub unsafe fn with_embedded_python_interpreter<F, R>(f: F) -> R
where where
F: for<'p> FnOnce(Python<'p>) -> R, F: for<'p> FnOnce(Python<'p>) -> R,
@ -149,10 +151,9 @@ where
// Changed in version 3.7: This function is now called by Py_Initialize(), so you dont have to // Changed in version 3.7: This function is now called by Py_Initialize(), so you dont have to
// call it yourself anymore. // call it yourself anymore.
if cfg!(not(Py_3_7)) { #[cfg(not(Py_3_7))]
if ffi::PyEval_ThreadsInitialized() == 0 { if ffi::PyEval_ThreadsInitialized() == 0 {
ffi::PyEval_InitThreads(); ffi::PyEval_InitThreads();
}
} }
// Safe: the GIL is already held because of the Py_IntializeEx call. // Safe: the GIL is already held because of the Py_IntializeEx call.

View File

@ -111,7 +111,7 @@
//! //!
//! PyO3 supports the following software versions: //! PyO3 supports the following software versions:
//! - Python 3.6 and up (CPython and PyPy) //! - Python 3.6 and up (CPython and PyPy)
//! - Rust 1.41 and up //! - Rust 1.48 and up
//! //!
//! # Example: Building a native Python module //! # Example: Building a native Python module
//! //!

View File

@ -83,7 +83,8 @@ where
slots.push(ffi::Py_tp_free, free as _); slots.push(ffi::Py_tp_free, free as _);
} }
if cfg!(Py_3_9) { #[cfg(Py_3_9)]
{
let members = py_class_members::<T>(); let members = py_class_members::<T>();
if !members.is_empty() { if !members.is_empty() {
slots.push(ffi::Py_tp_members, into_raw(members)) slots.push(ffi::Py_tp_members, into_raw(members))
@ -155,7 +156,8 @@ fn tp_init_additional<T: PyClass>(type_object: *mut ffi::PyTypeObject) {
// Setting buffer protocols via slots doesn't work until Python 3.9, so on older versions we // Setting buffer protocols via slots doesn't work until Python 3.9, so on older versions we
// must manually fixup the type object. // must manually fixup the type object.
if cfg!(not(Py_3_9)) { #[cfg(not(Py_3_9))]
{
if let Some(buffer) = T::get_buffer() { if let Some(buffer) = T::get_buffer() {
unsafe { unsafe {
(*(*type_object).tp_as_buffer).bf_getbuffer = buffer.bf_getbuffer; (*(*type_object).tp_as_buffer).bf_getbuffer = buffer.bf_getbuffer;
@ -166,7 +168,8 @@ fn tp_init_additional<T: PyClass>(type_object: *mut ffi::PyTypeObject) {
// Setting tp_dictoffset and tp_weaklistoffset via slots doesn't work until Python 3.9, so on // Setting tp_dictoffset and tp_weaklistoffset via slots doesn't work until Python 3.9, so on
// older versions again we must fixup the type object. // older versions again we must fixup the type object.
if cfg!(not(Py_3_9)) { #[cfg(not(Py_3_9))]
{
// __dict__ support // __dict__ support
if let Some(dict_offset) = PyCell::<T>::dict_offset() { if let Some(dict_offset) = PyCell::<T>::dict_offset() {
unsafe { unsafe {
@ -258,12 +261,6 @@ fn py_class_members<T: PyClass>() -> Vec<ffi::structmember::PyMemberDef> {
members members
} }
// Stub needed since the `if cfg!()` above still compiles contained code.
#[cfg(not(Py_3_9))]
fn py_class_members<T: PyClass>() -> Vec<ffi::structmember::PyMemberDef> {
vec![]
}
const PY_GET_SET_DEF_INIT: ffi::PyGetSetDef = ffi::PyGetSetDef { const PY_GET_SET_DEF_INIT: ffi::PyGetSetDef = ffi::PyGetSetDef {
name: ptr::null_mut(), name: ptr::null_mut(),
get: None, get: None,
@ -272,7 +269,6 @@ const PY_GET_SET_DEF_INIT: ffi::PyGetSetDef = ffi::PyGetSetDef {
closure: ptr::null_mut(), closure: ptr::null_mut(),
}; };
#[allow(clippy::collapsible_if)] // for if cfg!
fn py_class_properties( fn py_class_properties(
is_dummy: bool, is_dummy: bool,
for_each_method_def: &dyn Fn(&mut dyn FnMut(&[PyMethodDefType])), for_each_method_def: &dyn Fn(&mut dyn FnMut(&[PyMethodDefType])),

View File

@ -227,8 +227,9 @@ impl PyString {
pub unsafe fn data(&self) -> PyResult<PyStringData<'_>> { pub unsafe fn data(&self) -> PyResult<PyStringData<'_>> {
let ptr = self.as_ptr(); let ptr = self.as_ptr();
if cfg!(not(Py_3_12)) { #[cfg(not(Py_3_12))]
#[allow(deprecated)] #[allow(deprecated)]
{
let ready = ffi::PyUnicode_READY(ptr); let ready = ffi::PyUnicode_READY(ptr);
if ready != 0 { if ready != 0 {
// Exception was created on failure. // Exception was created on failure.

View File

@ -23,22 +23,15 @@ fn _test_compile_errors() {
t.compile_fail("tests/ui/invalid_pymethods.rs"); t.compile_fail("tests/ui/invalid_pymethods.rs");
t.compile_fail("tests/ui/invalid_pymethod_names.rs"); t.compile_fail("tests/ui/invalid_pymethod_names.rs");
t.compile_fail("tests/ui/invalid_argument_attributes.rs"); t.compile_fail("tests/ui/invalid_argument_attributes.rs");
t.compile_fail("tests/ui/missing_clone.rs");
t.compile_fail("tests/ui/reject_generics.rs"); t.compile_fail("tests/ui/reject_generics.rs");
t.compile_fail("tests/ui/wrong_aspyref_lifetimes.rs");
tests_rust_1_48(&t);
tests_rust_1_49(&t); tests_rust_1_49(&t);
tests_rust_1_54(&t); tests_rust_1_54(&t);
tests_rust_1_55(&t); tests_rust_1_55(&t);
tests_rust_1_56(&t); tests_rust_1_56(&t);
#[rustversion::since(1.48)]
fn tests_rust_1_48(t: &trybuild::TestCases) {
t.compile_fail("tests/ui/missing_clone.rs");
t.compile_fail("tests/ui/wrong_aspyref_lifetimes.rs");
}
#[rustversion::before(1.48)]
fn tests_rust_1_48(_t: &trybuild::TestCases) {}
#[rustversion::since(1.49)] #[rustversion::since(1.49)]
fn tests_rust_1_49(t: &trybuild::TestCases) { fn tests_rust_1_49(t: &trybuild::TestCases) {
t.compile_fail("tests/ui/deprecations.rs"); t.compile_fail("tests/ui/deprecations.rs");

View File

@ -2,9 +2,7 @@
//! but can't even be cfg-ed out on MSRV because the compiler doesn't support //! but can't even be cfg-ed out on MSRV because the compiler doesn't support
//! the syntax. //! the syntax.
// TODO(#1782) rustversion attribute can't go on modules until Rust 1.42, so this #[rustversion::since(1.54)]
// funky dance has to happen...
mod requires_1_54 { mod requires_1_54 {
#[rustversion::since(1.54)]
include!("not_msrv/requires_1_54.rs"); include!("not_msrv/requires_1_54.rs");
} }

View File

@ -6,15 +6,15 @@ error[E0277]: the trait bound `PyDict: PyClass` is not satisfied
| |
= note: required because of the requirements on the impl of `PyClassBaseType` for `PyDict` = note: required because of the requirements on the impl of `PyClassBaseType` for `PyDict`
note: required by a bound in `PyClassBaseType` note: required by a bound in `PyClassBaseType`
--> src/class/impl_.rs:766:1 --> src/class/impl_.rs
| |
766 | / pub trait PyClassBaseType: Sized { | / pub trait PyClassBaseType: Sized {
767 | | type Dict; | | type Dict;
768 | | type WeakRef; | | type WeakRef;
769 | | type LayoutAsBase: PyCellLayout<Self>; | | type LayoutAsBase: PyCellLayout<Self>;
... | ... |
772 | | type Initializer: PyObjectInit<Self>; | | type Initializer: PyObjectInit<Self>;
773 | | } | | }
| |_^ required by this bound in `PyClassBaseType` | |_^ required by this bound in `PyClassBaseType`
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)
@ -26,8 +26,8 @@ error[E0277]: the trait bound `PyDict: PyClass` is not satisfied
| |
= note: required because of the requirements on the impl of `PyClassBaseType` for `PyDict` = note: required because of the requirements on the impl of `PyClassBaseType` for `PyDict`
note: required by a bound in `ThreadCheckerInherited` note: required by a bound in `ThreadCheckerInherited`
--> src/class/impl_.rs:753:47 --> src/class/impl_.rs
| |
753 | pub struct ThreadCheckerInherited<T: Send, U: PyClassBaseType>(PhantomData<T>, U::ThreadChecker); | pub struct ThreadCheckerInherited<T: Send, U: PyClassBaseType>(PhantomData<T>, U::ThreadChecker);
| ^^^^^^^^^^^^^^^ required by this bound in `ThreadCheckerInherited` | ^^^^^^^^^^^^^^^ required by this bound in `ThreadCheckerInherited`
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -50,6 +50,3 @@ fn my_module(_py: Python, m: &PyModule) -> PyResult<()> {
fn main() { fn main() {
} }
// TODO: ensure name deprecated on #[pyfunction] and #[pymodule]

View File

@ -11,8 +11,8 @@ note: required because it appears within the type `NotThreadSafe`
5 | struct NotThreadSafe { 5 | struct NotThreadSafe {
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
note: required by a bound in `ThreadCheckerStub` note: required by a bound in `ThreadCheckerStub`
--> src/class/impl_.rs:710:33 --> src/class/impl_.rs
| |
710 | pub struct ThreadCheckerStub<T: Send>(PhantomData<T>); | pub struct ThreadCheckerStub<T: Send>(PhantomData<T>);
| ^^^^ required by this bound in `ThreadCheckerStub` | ^^^^ required by this bound in `ThreadCheckerStub`
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)