diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9743d6727e7..2d3219d8b02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,7 @@ jobs: platform: { os: "windows-latest" } include: # Test minimal supported Rust version - - rust: 1.39.0 + - rust: 1.45.0 python-version: 3.9 platform: { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu" } msrv: "MSRV" diff --git a/CHANGELOG.md b/CHANGELOG.md index 227a9d41cfa..df6b97e3bf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Packaging - Drop support for Python 3.5 (as it is now end-of-life). [#1250](https://github.com/PyO3/pyo3/pull/1250) +- Bump minimum supported Rust version to 1.45. [#1272](https://github.com/PyO3/pyo3/pull/1272) +- Bump indoc dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272) +- Bump paste dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272) ### Added - Add support for building for CPython limited API. This required a few minor changes to runtime behaviour of of pyo3 `#[pyclass]` types. See the migration guide for full details. [#1152](https://github.com/PyO3/pyo3/pull/1152) diff --git a/Cargo.toml b/Cargo.toml index 72a907135a7..29a2674140d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,13 +16,13 @@ edition = "2018" [dependencies] ctor = { version = "0.1", optional = true } -indoc = { version = "0.3.4", optional = true } +indoc = { version = "1.0.3", optional = true } inventory = { version = "0.1.4", optional = true } libc = "0.2.62" parking_lot = "0.11.0" num-bigint = { version = "0.3", optional = true } num-complex = { version = "0.3", optional = true } -paste = { version = "0.1.6", optional = true } +paste = { version = "1.0.3", optional = true } pyo3cls = { path = "pyo3cls", version = "=0.12.3", optional = true } unindent = { version = "0.1.4", optional = true } hashbrown = { version = "0.9", optional = true } diff --git a/README.md b/README.md index 53ace4f3d73..8c0f3e42317 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Actions Status](https://github.com/PyO3/pyo3/workflows/Test/badge.svg)](https://github.com/PyO3/pyo3/actions) [![codecov](https://codecov.io/gh/PyO3/pyo3/branch/master/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3) [![crates.io](http://meritbadge.herokuapp.com/pyo3)](https://crates.io/crates/pyo3) -[![minimum rustc 1.39](https://img.shields.io/badge/rustc-1.39+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![minimum rustc 1.45](https://img.shields.io/badge/rustc-1.45+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![Join the dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby) [Rust](http://www.rust-lang.org/) bindings for [Python](https://www.python.org/). This includes running and interacting with Python code from a Rust binary, as well as writing native Python modules. @@ -18,7 +18,7 @@ A comparison with rust-cpython can be found [in the guide](https://pyo3.rs/maste ## Usage -PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.39.0. +PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.45.0. Building with PyPy is also possible (via cpyext) for Python 3.6, targeted PyPy version is 7.3+. Please refer to the [pypy section in the guide](https://pyo3.rs/master/pypy.html). diff --git a/build.rs b/build.rs index 57df18d38cf..5065f82fcc3 100644 --- a/build.rs +++ b/build.rs @@ -341,16 +341,16 @@ fn find_sysconfigdata(cross: &CrossCompileConfig) -> Result { /// recursive search for _sysconfigdata, returns all possibilities of sysconfigdata paths fn search_lib_dir(path: impl AsRef, cross: &CrossCompileConfig) -> Vec { let mut sysconfig_paths = vec![]; - let version_pat = if let Some(ref v) = cross.version { + let version_pat = if let Some(v) = &cross.version { format!("python{}", v) } else { "python3.".into() }; for f in fs::read_dir(path).expect("Path does not exist") { - let sysc = match f { - Ok(ref f) if starts_with(f, "_sysconfigdata") && ends_with(f, "py") => vec![f.path()], - Ok(ref f) if starts_with(f, "build") => search_lib_dir(f.path(), cross), - Ok(ref f) if starts_with(f, "lib.") => { + let sysc = match &f { + Ok(f) if starts_with(f, "_sysconfigdata") && ends_with(f, "py") => vec![f.path()], + Ok(f) if starts_with(f, "build") => search_lib_dir(f.path(), cross), + Ok(f) if starts_with(f, "lib.") => { let name = f.file_name(); // check if right target os if !name.to_string_lossy().contains(if cross.os == "android" { @@ -366,7 +366,7 @@ fn search_lib_dir(path: impl AsRef, cross: &CrossCompileConfig) -> Vec search_lib_dir(f.path(), cross), + Ok(f) if starts_with(f, &version_pat) => search_lib_dir(f.path(), cross), _ => continue, }; sysconfig_paths.extend(sysc); @@ -569,7 +569,7 @@ fn run_python_script(interpreter: &Path, script: &str) -> Result { ); } } - Ok(ref ok) if !ok.status.success() => bail!("Python script failed: {}"), + Ok(ok) if !ok.status.success() => bail!("Python script failed: {}"), Ok(ok) => Ok(String::from_utf8(ok.stdout)?), } } diff --git a/guide/src/class/protocols.md b/guide/src/class/protocols.md index efefa48d0d1..f0098abb02a 100644 --- a/guide/src/class/protocols.md +++ b/guide/src/class/protocols.md @@ -175,7 +175,7 @@ struct ClassWithGCSupport { #[pyproto] impl PyGCProtocol for ClassWithGCSupport { fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> { - if let Some(ref obj) = self.obj { + if let Some(obj) = &self.obj { visit.call(obj)? } Ok(()) diff --git a/pyo3-derive-backend/src/from_pyobject.rs b/pyo3-derive-backend/src/from_pyobject.rs index 2275dfac886..01e281d5e22 100644 --- a/pyo3-derive-backend/src/from_pyobject.rs +++ b/pyo3-derive-backend/src/from_pyobject.rs @@ -137,13 +137,10 @@ impl<'a> Container<'a> { } let style = match (fields, transparent) { (Fields::Unnamed(_), true) => ContainerType::TupleNewtype, - (Fields::Unnamed(unnamed), false) => { - if unnamed.unnamed.len() == 1 { - ContainerType::TupleNewtype - } else { - ContainerType::Tuple(unnamed.unnamed.len()) - } - } + (Fields::Unnamed(unnamed), false) => match unnamed.unnamed.len() { + 1 => ContainerType::TupleNewtype, + len => ContainerType::Tuple(len), + }, (Fields::Named(named), true) => { let field = named .named @@ -457,14 +454,15 @@ fn get_pyo3_meta_list(attrs: &[Attribute]) -> Result { } fn verify_and_get_lifetime(generics: &syn::Generics) -> Result> { - let lifetimes = generics.lifetimes().collect::>(); - if lifetimes.len() > 1 { + let mut lifetimes = generics.lifetimes(); + let lifetime = lifetimes.next(); + if lifetimes.next().is_some() { return Err(spanned_err( &generics, "FromPyObject can be derived with at most one lifetime parameter.", )); } - Ok(lifetimes.into_iter().next()) + Ok(lifetime) } /// Derive FromPyObject for enums and structs. diff --git a/pyo3-derive-backend/src/method.rs b/pyo3-derive-backend/src/method.rs index 492ca08cc55..70957c8ad8d 100644 --- a/pyo3-derive-backend/src/method.rs +++ b/pyo3-derive-backend/src/method.rs @@ -100,7 +100,7 @@ pub struct FnSpec<'a> { pub fn get_return_info(output: &syn::ReturnType) -> syn::Type { match output { syn::ReturnType::Default => syn::Type::Infer(syn::parse_quote! {_}), - syn::ReturnType::Type(_, ref ty) => *ty.clone(), + syn::ReturnType::Type(_, ty) => *ty.clone(), } } @@ -109,7 +109,7 @@ pub fn parse_method_receiver(arg: &syn::FnArg) -> syn::Result { syn::FnArg::Receiver(recv) => Ok(SelfType::Receiver { mutable: recv.mutability.is_some(), }), - syn::FnArg::Typed(syn::PatType { ref ty, .. }) => Ok(SelfType::TryFromPyCell(ty.span())), + syn::FnArg::Typed(syn::PatType { ty, .. }) => Ok(SelfType::TryFromPyCell(ty.span())), } } @@ -198,14 +198,12 @@ impl<'a> FnSpec<'a> { "Unexpected receiver for method", )); } - syn::FnArg::Typed(syn::PatType { - ref pat, ref ty, .. - }) => { - let (ident, by_ref, mutability) = match **pat { + syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => { + let (ident, by_ref, mutability) = match &**pat { syn::Pat::Ident(syn::PatIdent { - ref ident, - ref by_ref, - ref mutability, + ident, + by_ref, + mutability, .. }) => (ident, by_ref, mutability), _ => { @@ -267,7 +265,7 @@ impl<'a> FnSpec<'a> { pub fn is_args(&self, name: &syn::Ident) -> bool { for s in self.attrs.iter() { - if let Argument::VarArgs(ref path) = s { + if let Argument::VarArgs(path) = s { return path.is_ident(name); } } @@ -276,7 +274,7 @@ impl<'a> FnSpec<'a> { pub fn is_kwargs(&self, name: &syn::Ident) -> bool { for s in self.attrs.iter() { - if let Argument::KeywordArgs(ref path) = s { + if let Argument::KeywordArgs(path) = s { return path.is_ident(name); } } @@ -285,10 +283,10 @@ impl<'a> FnSpec<'a> { pub fn default_value(&self, name: &syn::Ident) -> Option { for s in self.attrs.iter() { - match *s { - Argument::Arg(ref path, ref opt) | Argument::Kwarg(ref path, ref opt) => { + match s { + Argument::Arg(path, opt) | Argument::Kwarg(path, opt) => { if path.is_ident(name) { - if let Some(ref val) = opt { + if let Some(val) = opt { let i: syn::Expr = syn::parse_str(&val).unwrap(); return Some(i.into_token_stream()); } @@ -302,7 +300,7 @@ impl<'a> FnSpec<'a> { pub fn is_kw_only(&self, name: &syn::Ident) -> bool { for s in self.attrs.iter() { - if let Argument::Kwarg(ref path, _) = s { + if let Argument::Kwarg(path, _) = s { if path.is_ident(name) { return true; } @@ -341,7 +339,7 @@ fn parse_method_attributes( for attr in attrs.iter() { match attr.parse_meta()? { - syn::Meta::Path(ref name) => { + syn::Meta::Path(name) => { if name.is_ident("new") || name.is_ident("__new__") { set_ty!(MethodTypeAttribute::New, name); } else if name.is_ident("init") || name.is_ident("__init__") { @@ -373,11 +371,7 @@ fn parse_method_attributes( new_attrs.push(attr.clone()) } } - syn::Meta::List(syn::MetaList { - ref path, - ref nested, - .. - }) => { + syn::Meta::List(syn::MetaList { path, nested, .. }) => { if path.is_ident("new") { set_ty!(MethodTypeAttribute::New, path); } else if path.is_ident("init") { @@ -408,11 +402,11 @@ fn parse_method_attributes( }; property_name = match nested.first().unwrap() { - syn::NestedMeta::Meta(syn::Meta::Path(ref w)) if w.segments.len() == 1 => { + syn::NestedMeta::Meta(syn::Meta::Path(w)) if w.segments.len() == 1 => { Some(w.segments[0].ident.clone()) } - syn::NestedMeta::Lit(ref lit) => match *lit { - syn::Lit::Str(ref s) => Some(s.parse()?), + syn::NestedMeta::Lit(lit) => match lit { + syn::Lit::Str(s) => Some(s.parse()?), _ => { return Err(syn::Error::new_spanned( lit, @@ -428,7 +422,7 @@ fn parse_method_attributes( } }; } else if path.is_ident("args") { - let attrs = PyFunctionAttr::from_meta(nested)?; + let attrs = PyFunctionAttr::from_meta(&nested)?; args.extend(attrs.arguments) } else { new_attrs.push(attr.clone()) diff --git a/pyo3-derive-backend/src/module.rs b/pyo3-derive-backend/src/module.rs index 3959fb81046..f49b7c16891 100644 --- a/pyo3-derive-backend/src/module.rs +++ b/pyo3-derive-backend/src/module.rs @@ -35,7 +35,7 @@ pub fn process_functions_in_module(func: &mut syn::ItemFn) -> syn::Result<()> { let mut stmts: Vec = Vec::new(); for stmt in func.block.stmts.iter_mut() { - if let syn::Stmt::Item(syn::Item::Fn(ref mut func)) = stmt { + if let syn::Stmt::Item(syn::Item::Fn(func)) = stmt { if let Some((module_name, python_name, pyfn_attrs)) = extract_pyfn_attrs(&mut func.attrs)? { @@ -59,8 +59,8 @@ pub fn process_functions_in_module(func: &mut syn::ItemFn) -> syn::Result<()> { /// Transforms a rust fn arg parsed with syn into a method::FnArg fn wrap_fn_argument<'a>(cap: &'a syn::PatType) -> syn::Result> { - let (mutability, by_ref, ident) = match *cap.pat { - syn::Pat::Ident(ref patid) => (&patid.mutability, &patid.by_ref, &patid.ident), + let (mutability, by_ref, ident) = match &*cap.pat { + syn::Pat::Ident(patid) => (&patid.mutability, &patid.by_ref, &patid.ident), _ => return Err(syn::Error::new_spanned(&cap.pat, "Unsupported argument")), }; @@ -85,12 +85,12 @@ fn extract_pyfn_attrs( for attr in attrs.iter() { match attr.parse_meta() { - Ok(syn::Meta::List(ref list)) if list.path.is_ident("pyfn") => { + Ok(syn::Meta::List(list)) if list.path.is_ident("pyfn") => { let meta: Vec<_> = list.nested.iter().cloned().collect(); if meta.len() >= 2 { // read module name - match meta[0] { - syn::NestedMeta::Meta(syn::Meta::Path(ref path)) => { + match &meta[0] { + syn::NestedMeta::Meta(syn::Meta::Path(path)) => { modname = Some(path.clone()) } _ => { @@ -101,8 +101,8 @@ fn extract_pyfn_attrs( } } // read Python function name - match meta[1] { - syn::NestedMeta::Lit(syn::Lit::Str(ref lits)) => { + match &meta[1] { + syn::NestedMeta::Lit(syn::Lit::Str(lits)) => { fnname = Some(syn::Ident::new(&lits.value(), lits.span())); } _ => { @@ -157,7 +157,7 @@ pub fn add_fn_to_module( "Unexpected receiver for #[pyfn]", )) } - syn::FnArg::Typed(ref cap) => { + syn::FnArg::Typed(cap) => { if pyfn_attrs.pass_module && i == 0 { if let syn::Type::Reference(tyref) = cap.ty.as_ref() { if let syn::Type::Path(typath) = tyref.elem.as_ref() { diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index aca7e7d46c7..09eed257800 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -56,8 +56,8 @@ impl PyClassArgs { /// either a single word or an assignment expression fn add_expr(&mut self, expr: &Expr) -> syn::parse::Result<()> { match expr { - syn::Expr::Path(ref exp) if exp.path.segments.len() == 1 => self.add_path(exp), - syn::Expr::Assign(ref assign) => self.add_assign(assign), + syn::Expr::Path(exp) if exp.path.segments.len() == 1 => self.add_path(exp), + syn::Expr::Assign(assign) => self.add_assign(assign), _ => Err(syn::Error::new_spanned(expr, "Failed to parse arguments")), } } @@ -156,7 +156,7 @@ pub fn build_py_class(class: &mut syn::ItemStruct, attr: &PyClassArgs) -> syn::R let mut descriptors = Vec::new(); check_generics(class)?; - if let syn::Fields::Named(ref mut fields) = class.fields { + if let syn::Fields::Named(fields) = &mut class.fields { for field in fields.named.iter_mut() { let field_descs = parse_descriptors(field)?; if !field_descs.is_empty() { @@ -178,10 +178,10 @@ fn parse_descriptors(item: &mut syn::Field) -> syn::Result> { let mut descs = Vec::new(); let mut new_attrs = Vec::new(); for attr in item.attrs.iter() { - if let Ok(syn::Meta::List(ref list)) = attr.parse_meta() { + if let Ok(syn::Meta::List(list)) = attr.parse_meta() { if list.path.is_ident("pyo3") { for meta in list.nested.iter() { - if let syn::NestedMeta::Meta(ref metaitem) = meta { + if let syn::NestedMeta::Meta(metaitem) = meta { if metaitem.path().is_ident("get") { descs.push(FnType::Getter(SelfType::Receiver { mutable: false })); } else if metaitem.path().is_ident("set") { @@ -318,7 +318,7 @@ fn impl_class( let mut has_dict = false; let mut has_gc = false; for f in attr.flags.iter() { - if let syn::Expr::Path(ref epath) = f { + if let syn::Expr::Path(epath) = f { if epath.path == parse_quote! { pyo3::type_flags::WEAKREF } { has_weakref = true; } else if epath.path == parse_quote! { pyo3::type_flags::DICT } { @@ -469,7 +469,7 @@ fn impl_descriptors( ) -> syn::Result { let py_methods: Vec = descriptors .iter() - .flat_map(|&(ref field, ref fns)| { + .flat_map(|(field, fns)| { fns.iter() .map(|desc| { let name = field.ident.as_ref().unwrap().unraw(); diff --git a/pyo3-derive-backend/src/pyfunction.rs b/pyo3-derive-backend/src/pyfunction.rs index bfb943ff687..74d5bef292e 100644 --- a/pyo3-derive-backend/src/pyfunction.rs +++ b/pyo3-derive-backend/src/pyfunction.rs @@ -46,17 +46,17 @@ impl PyFunctionAttr { pub fn add_item(&mut self, item: &NestedMeta) -> syn::Result<()> { match item { - NestedMeta::Meta(syn::Meta::Path(ref ident)) if ident.is_ident("pass_module") => { + NestedMeta::Meta(syn::Meta::Path(ident)) if ident.is_ident("pass_module") => { self.pass_module = true; } - NestedMeta::Meta(syn::Meta::Path(ref ident)) => self.add_work(item, ident)?, - NestedMeta::Meta(syn::Meta::NameValue(ref nv)) => { + NestedMeta::Meta(syn::Meta::Path(ident)) => self.add_work(item, ident)?, + NestedMeta::Meta(syn::Meta::NameValue(nv)) => { self.add_name_value(item, nv)?; } - NestedMeta::Lit(ref lit) => { + NestedMeta::Lit(lit) => { self.add_literal(item, lit)?; } - NestedMeta::Meta(syn::Meta::List(ref list)) => { + NestedMeta::Meta(syn::Meta::List(list)) => { return Err(syn::Error::new_spanned( list, "List is not supported as argument", @@ -68,7 +68,7 @@ impl PyFunctionAttr { fn add_literal(&mut self, item: &NestedMeta, lit: &syn::Lit) -> syn::Result<()> { match lit { - syn::Lit::Str(ref lits) if lits.value() == "*" => { + syn::Lit::Str(lits) if lits.value() == "*" => { // "*" self.vararg_is_ok(item)?; self.has_varargs = true; @@ -137,8 +137,8 @@ impl PyFunctionAttr { } fn add_name_value(&mut self, item: &NestedMeta, nv: &syn::MetaNameValue) -> syn::Result<()> { - match nv.lit { - syn::Lit::Str(ref litstr) => { + match &nv.lit { + syn::Lit::Str(litstr) => { if litstr.value() == "*" { // args="*" self.vararg_is_ok(item)?; @@ -153,10 +153,10 @@ impl PyFunctionAttr { self.add_nv_common(item, &nv.path, litstr.value())?; } } - syn::Lit::Int(ref litint) => { + syn::Lit::Int(litint) => { self.add_nv_common(item, &nv.path, format!("{}", litint))?; } - syn::Lit::Bool(ref litb) => { + syn::Lit::Bool(litb) => { self.add_nv_common(item, &nv.path, format!("{}", litb.value))?; } _ => { @@ -175,32 +175,29 @@ pub fn parse_name_attribute(attrs: &mut Vec) -> syn::Result { - name_attrs.push((nv.lit.clone(), attr.span())); + Ok(syn::Meta::NameValue(nv)) if nv.path.is_ident("name") => { + name_attrs.push((nv.lit, attr.span())); false } _ => true, }); - if 1 < name_attrs.len() { - return Err(syn::Error::new( - name_attrs[0].1, - "#[name] can not be specified multiple times", - )); - } - - match name_attrs.get(0) { - Some((syn::Lit::Str(s), span)) => { + match name_attrs.as_slice() { + [] => Ok(None), + [(syn::Lit::Str(s), span)] => { let mut ident: syn::Ident = s.parse()?; // This span is the whole attribute span, which is nicer for reporting errors. ident.set_span(*span); Ok(Some(ident)) } - Some((_, span)) => Err(syn::Error::new( + [(_, span)] => Err(syn::Error::new( *span, "Expected string literal for #[name] argument", )), - None => Ok(None), + [_first_attr, second_attr, ..] => Err(syn::Error::new( + second_attr.1, + "#[name] can not be specified multiple times", + )), } } diff --git a/pyo3-derive-backend/src/pyimpl.rs b/pyo3-derive-backend/src/pyimpl.rs index e59cb43fb87..58988f7bab7 100644 --- a/pyo3-derive-backend/src/pyimpl.rs +++ b/pyo3-derive-backend/src/pyimpl.rs @@ -5,7 +5,7 @@ use proc_macro2::TokenStream; use quote::quote; pub fn build_py_methods(ast: &mut syn::ItemImpl) -> syn::Result { - if let Some((_, ref path, _)) = ast.trait_ { + if let Some((_, path, _)) = &ast.trait_ { Err(syn::Error::new_spanned( path, "#[pymethods] cannot be used on trait impl blocks", diff --git a/pyo3-derive-backend/src/pymethod.rs b/pyo3-derive-backend/src/pymethod.rs index a3d2f4ad0ed..ddfa4a1831b 100644 --- a/pyo3-derive-backend/src/pymethod.rs +++ b/pyo3-derive-backend/src/pymethod.rs @@ -505,11 +505,10 @@ fn impl_arg_param( // Get Option<&T> from Option> ( quote! { Option<<#tref as pyo3::derive_utils::ExtractExt>::Target> }, - // To support Rustc 1.39.0, we don't use as_deref here... if mut_.is_some() { - quote! { _tmp.as_mut().map(std::ops::DerefMut::deref_mut) } + quote! { _tmp.as_deref_mut() } } else { - quote! { _tmp.as_ref().map(std::ops::Deref::deref) } + quote! { _tmp.as_deref() } }, ) } else { @@ -554,7 +553,7 @@ fn impl_arg_param( fn replace_self(tref: &mut syn::TypeReference, self_path: &syn::Path) { match &mut *tref.elem { syn::Type::Reference(tref_inner) => replace_self(tref_inner, self_path), - syn::Type::Path(ref mut tpath) => { + syn::Type::Path(tpath) => { if let Some(ident) = tpath.path.get_ident() { if ident == "Self" { tpath.path = self_path.to_owned(); @@ -712,13 +711,8 @@ pub(crate) fn impl_py_getter_def( /// 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]) { - if args - .get(0) - .map(|py| utils::is_python(&py.ty)) - .unwrap_or(false) - { - (Some(&args[0]), &args[1..]) - } else { - (None, args) + match args { + [py, args @ ..] if utils::is_python(&py.ty) => (Some(py), args), + args => (None, args), } } diff --git a/pyo3-derive-backend/src/pyproto.rs b/pyo3-derive-backend/src/pyproto.rs index 249301af0cc..e7e2bd64cee 100644 --- a/pyo3-derive-backend/src/pyproto.rs +++ b/pyo3-derive-backend/src/pyproto.rs @@ -10,8 +10,8 @@ use quote::ToTokens; use std::collections::HashSet; pub fn build_py_proto(ast: &mut syn::ItemImpl) -> syn::Result { - if let Some((_, ref mut path, _)) = ast.trait_ { - let proto = if let Some(ref mut segment) = path.segments.last() { + if let Some((_, path, _)) = &mut ast.trait_ { + let proto = if let Some(segment) = path.segments.last() { match segment.ident.to_string().as_str() { "PyObjectProtocol" => &defs::OBJECT, "PyAsyncProtocol" => &defs::ASYNC, @@ -64,7 +64,7 @@ fn impl_proto_impl( let mut method_names = HashSet::new(); for iimpl in impls.iter_mut() { - if let syn::ImplItem::Method(ref mut met) = iimpl { + if let syn::ImplItem::Method(met) = iimpl { // impl Py~Protocol<'p> { type = ... } if let Some(m) = proto.get_proto(&met.sig.ident) { impl_method_proto(ty, &mut met.sig, m)?.to_tokens(&mut trait_impls); diff --git a/pyo3-derive-backend/src/utils.rs b/pyo3-derive-backend/src/utils.rs index 1bfc1a057b3..e5080483c8f 100644 --- a/pyo3-derive-backend/src/utils.rs +++ b/pyo3-derive-backend/src/utils.rs @@ -10,7 +10,7 @@ pub fn print_err(msg: String, t: TokenStream) { /// Check if the given type `ty` is `pyo3::Python`. pub fn is_python(ty: &syn::Type) -> bool { match ty { - syn::Type::Path(ref typath) => typath + syn::Type::Path(typath) => typath .path .segments .last() @@ -125,9 +125,9 @@ pub fn get_doc( let mut first = true; for attr in attrs.iter() { - if let Ok(syn::Meta::NameValue(ref metanv)) = attr.parse_meta() { + if let Ok(syn::Meta::NameValue(metanv)) = attr.parse_meta() { if metanv.path.is_ident("doc") { - if let syn::Lit::Str(ref litstr) = metanv.lit { + if let syn::Lit::Str(litstr) = metanv.lit { if first { first = false; span = litstr.span(); diff --git a/pyo3cls/src/lib.rs b/pyo3cls/src/lib.rs index bade299b750..42606f68071 100644 --- a/pyo3cls/src/lib.rs +++ b/pyo3cls/src/lib.rs @@ -2,7 +2,6 @@ //! This crate declares only the proc macro attributes, as a crate defining proc macro attributes //! must not contain any other public items. -extern crate proc_macro; use proc_macro::TokenStream; use pyo3_derive_backend::{ build_derive_from_pyobject, build_py_class, build_py_function, build_py_methods, diff --git a/src/buffer.rs b/src/buffer.rs index a80f18392cf..7a2d2f5a7b5 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -46,17 +46,12 @@ pub enum ElementType { impl ElementType { pub fn from_format(format: &CStr) -> ElementType { - let slice = format.to_bytes(); - if slice.len() == 1 { - native_element_type_from_type_char(slice[0]) - } else if slice.len() == 2 { - match slice[0] { - b'@' => native_element_type_from_type_char(slice[1]), - b'=' | b'<' | b'>' | b'!' => standard_element_type_from_type_char(slice[1]), - _ => ElementType::Unknown, + match format.to_bytes() { + [char] | [b'@', char] => native_element_type_from_type_char(*char), + [modifier, char] if matches!(modifier, b'=' | b'<' | b'>' | b'!') => { + standard_element_type_from_type_char(*char) } - } else { - ElementType::Unknown + _ => ElementType::Unknown, } } } diff --git a/src/ffi/datetime.rs b/src/ffi/datetime.rs index 8ed85eaa8e4..be8986b8d50 100644 --- a/src/ffi/datetime.rs +++ b/src/ffi/datetime.rs @@ -322,7 +322,7 @@ pub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int { /// Accessor functions #[cfg(not(PyPy))] macro_rules! _access_field { - ($obj:expr, $type: ident, $field:tt) => { + ($obj:expr, $type: ident, $field:ident) => { (*($obj as *mut $type)).$field }; } @@ -504,7 +504,7 @@ pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { // Accessor functions for PyDateTime_Delta #[cfg(not(PyPy))] macro_rules! _access_delta_field { - ($obj:expr, $field:tt) => { + ($obj:expr, $field:ident) => { _access_field!($obj, PyDateTime_Delta, $field) }; } diff --git a/src/lib.rs b/src/lib.rs index 9326700c344..092d4ac839f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -211,7 +211,7 @@ pub mod proc_macro { #[macro_export] macro_rules! wrap_pyfunction { ($function_name: ident) => {{ - &pyo3::paste::expr! { [<__pyo3_get_function_ $function_name>] } + &pyo3::paste::paste! { [<__pyo3_get_function_ $function_name>] } }}; ($function_name: ident, $arg: expr) => { @@ -244,7 +244,7 @@ macro_rules! wrap_pyfunction { #[macro_export] macro_rules! raw_pycfunction { ($function_name: ident) => {{ - pyo3::paste::expr! { [<__pyo3_raw_ $function_name>] } + pyo3::paste::paste! { [<__pyo3_raw_ $function_name>] } }}; } @@ -254,7 +254,7 @@ macro_rules! raw_pycfunction { #[macro_export] macro_rules! wrap_pymodule { ($module_name:ident) => {{ - pyo3::paste::expr! { + pyo3::paste::paste! { &|py| unsafe { pyo3::PyObject::from_owned_ptr(py, []()) } } }}; @@ -349,9 +349,9 @@ macro_rules! py_run_impl { #[doc(hidden)] pub mod doc_test { macro_rules! doc_comment { - ($x:expr, $($tt:tt)*) => { + ($x:expr, $module:item) => { #[doc = $x] - $($tt)* + $module }; } diff --git a/src/pyclass.rs b/src/pyclass.rs index 739e1528d13..d25b17dc9a4 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -317,18 +317,18 @@ fn py_class_method_defs() -> ( let mut new = fallback_new(); for def in T::py_methods() { - match *def { - PyMethodDefType::New(ref def) => { + match def { + PyMethodDefType::New(def) => { new = def.get_new_func(); debug_assert!(new.is_some()); } - PyMethodDefType::Call(ref def) => { + PyMethodDefType::Call(def) => { call = def.get_cfunction_with_keywords(); debug_assert!(call.is_some()); } - PyMethodDefType::Method(ref def) - | PyMethodDefType::Class(ref def) - | PyMethodDefType::Static(ref def) => { + PyMethodDefType::Method(def) + | PyMethodDefType::Class(def) + | PyMethodDefType::Static(def) => { defs.push(def.as_method_def()); } _ => (), @@ -346,15 +346,15 @@ fn py_class_properties() -> Vec { let mut defs = std::collections::HashMap::new(); for def in T::py_methods() { - match *def { - PyMethodDefType::Getter(ref getter) => { + match def { + PyMethodDefType::Getter(getter) => { if !defs.contains_key(getter.name) { let _ = defs.insert(getter.name.to_owned(), ffi::PyGetSetDef_INIT); } let def = defs.get_mut(getter.name).expect("Failed to call get_mut"); getter.copy_to(def); } - PyMethodDefType::Setter(ref setter) => { + PyMethodDefType::Setter(setter) => { if !defs.contains_key(setter.name) { let _ = defs.insert(setter.name.to_owned(), ffi::PyGetSetDef_INIT); } diff --git a/tests/test_compile_error.rs b/tests/test_compile_error.rs index 2473590f553..0b2e495cd2b 100644 --- a/tests/test_compile_error.rs +++ b/tests/test_compile_error.rs @@ -8,18 +8,11 @@ fn test_compile_errors() { t.compile_fail("tests/ui/invalid_pyclass_args.rs"); t.compile_fail("tests/ui/invalid_pymethod_names.rs"); t.compile_fail("tests/ui/reject_generics.rs"); + t.compile_fail("tests/ui/static_ref.rs"); t.compile_fail("tests/ui/wrong_aspyref_lifetimes.rs"); - tests_rust_1_43(&t); tests_rust_1_46(&t); - #[rustversion::since(1.43)] - fn tests_rust_1_43(t: &trybuild::TestCases) { - t.compile_fail("tests/ui/static_ref.rs"); - } - #[rustversion::before(1.43)] - fn tests_rust_1_43(_t: &trybuild::TestCases) {} - #[rustversion::since(1.46)] fn tests_rust_1_46(t: &trybuild::TestCases) { t.compile_fail("tests/ui/invalid_frompy_derive.rs"); diff --git a/tests/test_datetime.rs b/tests/test_datetime.rs index bbdff7faceb..a3867562f99 100644 --- a/tests/test_datetime.rs +++ b/tests/test_datetime.rs @@ -36,7 +36,7 @@ macro_rules! assert_check_exact { unsafe { use pyo3::{AsPyPointer, ffi::*}; assert!($check_func(($obj).as_ptr()) != 0); - assert!(pyo3::paste::expr!([<$check_func Exact>])(($obj).as_ptr()) != 0); + assert!(pyo3::paste::paste!([<$check_func Exact>])(($obj).as_ptr()) != 0); } }; } @@ -46,7 +46,7 @@ macro_rules! assert_check_only { unsafe { use pyo3::{AsPyPointer, ffi::*}; assert!($check_func(($obj).as_ptr()) != 0); - assert!(pyo3::paste::expr!([<$check_func Exact>])(($obj).as_ptr()) == 0); + assert!(pyo3::paste::paste!([<$check_func Exact>])(($obj).as_ptr()) == 0); } }; } diff --git a/tests/test_gc.rs b/tests/test_gc.rs index eb982887b93..559ce39c35c 100644 --- a/tests/test_gc.rs +++ b/tests/test_gc.rs @@ -196,7 +196,7 @@ impl BaseClassWithDrop { impl Drop for BaseClassWithDrop { fn drop(&mut self) { - if let Some(ref mut data) = self.data { + if let Some(data) = &self.data { data.store(true, Ordering::Relaxed); } } @@ -220,7 +220,7 @@ impl SubClassWithDrop { impl Drop for SubClassWithDrop { fn drop(&mut self) { - if let Some(ref mut data) = self.data { + if let Some(data) = &self.data { data.store(true, Ordering::Relaxed); } } diff --git a/tests/test_sequence.rs b/tests/test_sequence.rs index 0a4c4afd1f8..a361c55c6d5 100644 --- a/tests/test_sequence.rs +++ b/tests/test_sequence.rs @@ -59,7 +59,7 @@ impl PySequenceProtocol for ByteSequence { fn __contains__(&self, other: &PyAny) -> bool { match u8::extract(other) { - Ok(ref x) => self.elements.contains(x), + Ok(x) => self.elements.contains(&x), Err(_) => false, } } diff --git a/tests/ui/invalid_pymethod_names.stderr b/tests/ui/invalid_pymethod_names.stderr index 0a56f9e6435..01f81b67cea 100644 --- a/tests/ui/invalid_pymethod_names.stderr +++ b/tests/ui/invalid_pymethod_names.stderr @@ -5,9 +5,9 @@ error: name not allowed with this method type | ^ error: #[name] can not be specified multiple times - --> $DIR/invalid_pymethod_names.rs:17:5 + --> $DIR/invalid_pymethod_names.rs:18:5 | -17 | #[name = "foo"] +18 | #[name = "bar"] | ^ error: name not allowed with this method type