From cf055ac06c7b72f572882ce15d6a60da92ad60a0 Mon Sep 17 00:00:00 2001 From: tyranron Date: Fri, 20 May 2022 12:21:27 +0200 Subject: [PATCH] Upgrade to 1.61 Rust and bump up MSRV - simplify codegen due to better const evaluation - tune up lints --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 2 +- Cargo.toml | 2 +- README.md | 2 +- codegen/CHANGELOG.md | 2 +- codegen/Cargo.toml | 2 +- codegen/README.md | 2 +- codegen/src/attribute.rs | 54 ++++++++---------------------- codegen/src/lib.rs | 3 ++ src/cli.rs | 1 + src/cucumber.rs | 6 +++- src/lib.rs | 3 ++ src/runner/basic.rs | 5 ++- src/step.rs | 3 +- src/writer/basic.rs | 3 +- src/writer/fail_on_skipped.rs | 5 ++- src/writer/json.rs | 62 +++++++++++++++++++++-------------- src/writer/normalize.rs | 2 +- 18 files changed, 82 insertions(+), 79 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17b300b9..efaae7c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,7 +100,7 @@ jobs: strategy: fail-fast: false matrix: - msrv: ["1.60.0"] + msrv: ["1.61.0"] crate: - cucumber-codegen - cucumber diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ce4bd3a..d3a2742a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ All user visible changes to `cucumber` crate will be documented in this file. Th ### BC Breaks -- Bump up [MSRV] to 1.60 for more clever support of [Cargo feature]s. +- Bump up [MSRV] to 1.61 for more clever support of [Cargo feature]s and simplified codegen. diff --git a/Cargo.toml b/Cargo.toml index 6e03092f..051e63c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "cucumber" version = "0.14.0-dev" edition = "2021" -rust-version = "1.60" +rust-version = "1.61" description = """\ Cucumber testing framework for Rust, with async support. \ Fully native, no external test runners or dependencies.\ diff --git a/README.md b/README.md index d56f4c6c..b06dea3c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Cucumber testing framework for Rust [![Crates.io](https://img.shields.io/crates/v/cucumber.svg?maxAge=2592000)](https://crates.io/crates/cucumber) [![Documentation](https://docs.rs/cucumber/badge.svg)](https://docs.rs/cucumber) [![CI](https://github.com/cucumber-rs/cucumber/workflows/CI/badge.svg?branch=main "CI")](https://github.com/cucumber-rs/cucumber/actions?query=workflow%3ACI+branch%3Amain) -[![Rust 1.60+](https://img.shields.io/badge/rustc-1.60+-lightgray.svg "Rust 1.60+")](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html) +[![Rust 1.61+](https://img.shields.io/badge/rustc-1.61+-lightgray.svg "Rust 1.61+")](https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html) [![Unsafe Forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance) An implementation of the [Cucumber] testing framework for Rust. Fully native, no external test runners or dependencies. diff --git a/codegen/CHANGELOG.md b/codegen/CHANGELOG.md index e9d1e1ef..fcd9f56b 100644 --- a/codegen/CHANGELOG.md +++ b/codegen/CHANGELOG.md @@ -13,7 +13,7 @@ All user visible changes to `cucumber-codegen` crate will be documented in this ### BC Breaks -- Bump up [MSRV] to 1.60 for more clever support of [Cargo feature]s. +- Bump up [MSRV] to 1.61 for more clever support of [Cargo feature]s and simplified codegen. diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 96009469..68123a04 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -2,7 +2,7 @@ name = "cucumber-codegen" version = "0.14.0-dev" # should be the same as main crate version edition = "2021" -rust-version = "1.60" +rust-version = "1.61" description = "Code generation for `cucumber` crate." license = "MIT OR Apache-2.0" authors = [ diff --git a/codegen/README.md b/codegen/README.md index ed118488..5780e375 100644 --- a/codegen/README.md +++ b/codegen/README.md @@ -4,7 +4,7 @@ [![Crates.io](https://img.shields.io/crates/v/cucumber-codegen.svg?maxAge=2592000)](https://crates.io/crates/cucumber-codegen) [![Documentation](https://docs.rs/cucumber-codegen/badge.svg)](https://docs.rs/cucumber-codegen) [![CI](https://github.com/cucumber-rs/cucumber/workflows/CI/badge.svg?branch=main "CI")](https://github.com/cucumber-rs/cucumber/actions?query=workflow%3ACI+branch%3Amain) -[![Rust 1.60+](https://img.shields.io/badge/rustc-1.60+-lightgray.svg "Rust 1.60+")](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html) +[![Rust 1.61+](https://img.shields.io/badge/rustc-1.61+-lightgray.svg "Rust 1.61+")](https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html) [![Unsafe Forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance) - [Changelog](https://github.com/cucumber-rs/cucumber/blob/main/codegen/CHANGELOG.md) diff --git a/codegen/src/attribute.rs b/codegen/src/attribute.rs index d39541cf..194304ec 100644 --- a/codegen/src/attribute.rs +++ b/codegen/src/attribute.rs @@ -113,31 +113,9 @@ impl Step { let regex = self.gen_regex()?; - let caller_name = - format_ident!("__cucumber_{}_{func_name}", self.attr_name); let awaiting = func.sig.asyncness.map(|_| quote! { .await }); let unwrapping = (!self.returns_unit()) .then(|| quote! { .unwrap_or_else(|e| panic!("{}", e)) }); - let step_caller = quote! { - { - #[automatically_derived] - fn #caller_name<'w>( - __cucumber_world: &'w mut #world, - __cucumber_ctx: ::cucumber::step::Context, - ) -> ::cucumber::codegen::LocalBoxFuture<'w, ()> { - let f = async move { - #addon_parsing - let _ = #func_name(__cucumber_world, #func_args) - #awaiting - #unwrapping; - }; - ::std::boxed::Box::pin(f) - } - - let f: ::cucumber::Step<#world> = #caller_name; - f - } - }; Ok(quote! { #func @@ -156,26 +134,20 @@ impl Step { line: ::std::line!(), column: ::std::column!(), }, - regex: { - // This hack exists, as `fn item` to `fn pointer` - // coercion can be done inside `const`, but not - // `const fn`. - let lazy: ::cucumber::codegen::LazyRegex = || { - static LAZY: ::cucumber::codegen::Lazy< - ::cucumber::codegen::Regex - > = ::cucumber::codegen::Lazy::new(|| { - #regex - }); - LAZY.clone() - }; - lazy + regex: || { + static LAZY: ::cucumber::codegen::Lazy< + ::cucumber::codegen::Regex + > = ::cucumber::codegen::Lazy::new(|| { #regex }); + LAZY.clone() }, - func: { - // This hack exists, as `fn item` to `fn pointer` - // coercion can be done inside `const`, but not - // `const fn`. - const F: ::cucumber::Step<#world> = #step_caller; - F + func: |__cucumber_world, __cucumber_ctx| { + let f = async move { + #addon_parsing + let _ = #func_name(__cucumber_world, #func_args) + #awaiting + #unwrapping; + }; + ::std::boxed::Box::pin(f) }, } }); diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index a045abe7..87e63928 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -44,6 +44,7 @@ clippy::if_then_some_else_none, clippy::imprecise_flops, clippy::index_refutable_slice, + clippy::iter_with_drain, clippy::let_underscore_must_use, clippy::lossy_float_literal, clippy::map_err_ignore, @@ -54,6 +55,7 @@ clippy::mutex_atomic, clippy::mutex_integer, clippy::nonstandard_macro_braces, + clippy::only_used_in_recursion, clippy::option_if_let_else, clippy::panic_in_result_fn, clippy::pedantic, @@ -75,6 +77,7 @@ clippy::trailing_empty_array, clippy::transmute_undefined_repr, clippy::trivial_regex, + clippy::try_err, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_self_imports, diff --git a/src/cli.rs b/src/cli.rs index 860db971..cb24eca7 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -277,6 +277,7 @@ pub struct Compose { impl Compose { /// Unpacks this [`Compose`] into the underlying CLIs. + #[allow(clippy::missing_const_for_fn)] // false positive: drop in const #[must_use] pub fn into_inner(self) -> (L, R) { let Compose { left, right } = self; diff --git a/src/cucumber.rs b/src/cucumber.rs index c11322f4..2ba3edb4 100644 --- a/src/cucumber.rs +++ b/src/cucumber.rs @@ -92,7 +92,7 @@ where /// Creates a custom [`Cucumber`] executor with the provided [`Parser`], /// [`Runner`] and [`Writer`]. #[must_use] - pub fn custom(parser: P, runner: R, writer: Wr) -> Self { + pub const fn custom(parser: P, runner: R, writer: Wr) -> Self { Self { parser, runner, @@ -104,6 +104,7 @@ where } /// Replaces [`Parser`]. + #[allow(clippy::missing_const_for_fn)] // false positive: drop in const #[must_use] pub fn with_parser( self, @@ -124,6 +125,7 @@ where } /// Replaces [`Runner`]. + #[allow(clippy::missing_const_for_fn)] // false positive: drop in const #[must_use] pub fn with_runner( self, @@ -144,6 +146,7 @@ where } /// Replaces [`Writer`]. + #[allow(clippy::missing_const_for_fn)] // false positive: drop in const #[must_use] pub fn with_writer( self, @@ -716,6 +719,7 @@ where /// Also, specifying `--help` flag will describe `--before-time` now. /// /// [`Feature`]: gherkin::Feature + #[allow(clippy::missing_const_for_fn)] // false positive: drop in const pub fn with_cli( self, cli: cli::Opts, diff --git a/src/lib.rs b/src/lib.rs index eed34cfa..d8d28170 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,6 +46,7 @@ clippy::if_then_some_else_none, clippy::imprecise_flops, clippy::index_refutable_slice, + clippy::iter_with_drain, clippy::let_underscore_must_use, clippy::lossy_float_literal, clippy::map_err_ignore, @@ -56,6 +57,7 @@ clippy::mutex_atomic, clippy::mutex_integer, clippy::nonstandard_macro_braces, + clippy::only_used_in_recursion, clippy::option_if_let_else, clippy::panic_in_result_fn, clippy::pedantic, @@ -77,6 +79,7 @@ clippy::trailing_empty_array, clippy::transmute_undefined_repr, clippy::trivial_regex, + clippy::try_err, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_self_imports, diff --git a/src/runner/basic.rs b/src/runner/basic.rs index 2138391e..38ff2acd 100644 --- a/src/runner/basic.rs +++ b/src/runner/basic.rs @@ -241,6 +241,7 @@ impl Basic { /// [`Concurrent`]: ScenarioType::Concurrent /// [`Serial`]: ScenarioType::Serial /// [`Scenario`]: gherkin::Scenario + #[allow(clippy::missing_const_for_fn)] // false positive: drop in const #[must_use] pub fn which_scenario(self, func: F) -> Basic where @@ -275,6 +276,7 @@ impl Basic { /// [`Background`]: gherkin::Background /// [`Scenario`]: gherkin::Scenario /// [`Step`]: gherkin::Step + #[allow(clippy::missing_const_for_fn)] // false positive: drop in const #[must_use] pub fn before(self, func: Func) -> Basic where @@ -314,6 +316,7 @@ impl Basic { /// [`Scenario`]: gherkin::Scenario /// [`Skipped`]: event::Step::Skipped /// [`Step`]: gherkin::Step + #[allow(clippy::missing_const_for_fn)] // false positive: drop in const #[must_use] pub fn after(self, func: Func) -> Basic where @@ -678,7 +681,7 @@ where ) -> LocalBoxFuture<'a, ()>, { /// Creates a new [`Executor`]. - fn new( + const fn new( collection: step::Collection, before_hook: Option, after_hook: Option, diff --git a/src/step.rs b/src/step.rs index b1d91377..09ca06e0 100644 --- a/src/step.rs +++ b/src/step.rs @@ -186,7 +186,8 @@ impl Collection { } }; - // All indices here are obtained from the source string. + // PANIC: Slicing is OK here, as all indices are obtained from the + // source string. #[allow(clippy::string_slice)] let matches = names .map(|opt| opt.map(str::to_owned)) diff --git a/src/writer/basic.rs b/src/writer/basic.rs index da8f6f1e..f3632a2c 100644 --- a/src/writer/basic.rs +++ b/src/writer/basic.rs @@ -949,7 +949,8 @@ where D: for<'a> Fn(&'a str) -> Cow<'a, str>, A: for<'a> Fn(&'a str) -> Cow<'a, str>, { - // All indices here are obtained from the source string. + // PANIC: Slicing is OK here, as all indices are obtained from the source + // string. #![allow(clippy::string_slice)] let value = value.as_ref(); diff --git a/src/writer/fail_on_skipped.rs b/src/writer/fail_on_skipped.rs index f3f53458..9f38261f 100644 --- a/src/writer/fail_on_skipped.rs +++ b/src/writer/fail_on_skipped.rs @@ -189,7 +189,10 @@ impl FailOnSkipped { /// [`Skipped`]: event::Step::Skipped /// [`Step`]: gherkin::Step #[must_use] - pub fn with

(writer: Writer, predicate: P) -> FailOnSkipped + pub const fn with

( + writer: Writer, + predicate: P, + ) -> FailOnSkipped where P: Fn( &gherkin::Feature, diff --git a/src/writer/json.rs b/src/writer/json.rs index 6a4b5088..38cc20d5 100644 --- a/src/writer/json.rs +++ b/src/writer/json.rs @@ -146,7 +146,7 @@ impl Json { /// [1]: https://github.com/cucumber/cucumber-json-schema /// [2]: crate::event::Cucumber #[must_use] - pub fn raw(output: Out) -> Self { + pub const fn raw(output: Out) -> Self { Self { output, features: Vec::new(), @@ -371,30 +371,42 @@ pub struct Tag { pub line: usize, } -/// Possible statuses of running [`gherkin::Step`]. -#[derive(Clone, Copy, Debug, Serialize)] -pub enum Status { - /// [`event::Step::Passed`]. - Passed, - - /// [`event::Step::Failed`] with an [`event::StepError::Panic`]. - Failed, - - /// [`event::Step::Skipped`]. - Skipped, - - /// [`event::Step::Failed`] with an [`event::StepError::AmbiguousMatch`]. - Ambiguous, - - /// Never constructed and is here only to fully describe [JSON schema][1]. - /// - /// [1]: https://github.com/cucumber/cucumber-json-schema - Undefined, - - /// Never constructed and is here only to fully describe [JSON schema][1]. - /// - /// [1]: https://github.com/cucumber/cucumber-json-schema - Pending, +pub use self::status::Status; + +/// TODO: Only because of [`Serialize`] deriving, try to remove on next +/// [`serde`] update. +#[allow(clippy::use_self, clippy::wildcard_imports)] +mod status { + use super::*; + + /// Possible statuses of running [`gherkin::Step`]. + #[derive(Clone, Copy, Debug, Serialize)] + pub enum Status { + /// [`event::Step::Passed`]. + Passed, + + /// [`event::Step::Failed`] with an [`event::StepError::Panic`]. + Failed, + + /// [`event::Step::Skipped`]. + Skipped, + + /// [`event::Step::Failed`] with an + /// [`event::StepError::AmbiguousMatch`]. + Ambiguous, + + /// Never constructed and is here only to fully describe + /// [JSON schema][1]. + /// + /// [1]: https://github.com/cucumber/cucumber-json-schema + Undefined, + + /// Never constructed and is here only to fully describe + /// [JSON schema][1]. + /// + /// [1]: https://github.com/cucumber/cucumber-json-schema + Pending, + } } /// [`Serialize`]able result of running something. diff --git a/src/writer/normalize.rs b/src/writer/normalize.rs index 37862afb..731289c0 100644 --- a/src/writer/normalize.rs +++ b/src/writer/normalize.rs @@ -318,7 +318,7 @@ impl Queue { /// Checks whether this [`Queue`] transited to [`FinishedAndEmitted`] state. /// /// [`FinishedAndEmitted`]: FinishedState::FinishedAndEmitted - fn is_finished_and_emitted(&self) -> bool { + const fn is_finished_and_emitted(&self) -> bool { matches!(self.state, FinishedState::FinishedAndEmitted) }