diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51044c292c5..1ba7bcdb118 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,8 +64,8 @@ jobs: # macos-14 for M1 runners - macos-14 - windows-latest - # 1.75 is the MSRV - rust-version: ["1.75", stable] + # 1.81 is the MSRV + rust-version: ["1.81", stable] fail-fast: false steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 diff --git a/Cargo.toml b/Cargo.toml index f52f5b56bf0..c81d63eb35c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ members = [ ] [workspace.package] -rust-version = "1.75" +rust-version = "1.81" edition = "2021" license = "MIT OR Apache-2.0" diff --git a/cargo-nextest/src/cargo_cli.rs b/cargo-nextest/src/cargo_cli.rs index 337d32d4476..773d9966ac5 100644 --- a/cargo-nextest/src/cargo_cli.rs +++ b/cargo-nextest/src/cargo_cli.rs @@ -228,7 +228,6 @@ impl<'a> CargoCli<'a> { } } - #[allow(dead_code)] pub(crate) fn add_arg(&mut self, arg: &'a str) -> &mut Self { self.args.push(Cow::Borrowed(arg)); self diff --git a/cargo-nextest/src/dispatch.rs b/cargo-nextest/src/dispatch.rs index 8ad476c46b3..4f3bfb348b7 100644 --- a/cargo-nextest/src/dispatch.rs +++ b/cargo-nextest/src/dispatch.rs @@ -602,7 +602,7 @@ struct TestBuildFilter { } impl TestBuildFilter { - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn compute_test_list<'g>( &self, ctx: &TestExecuteContext<'_>, @@ -2000,7 +2000,7 @@ enum SetupSource { } impl SelfCommand { - #[allow(unused_variables)] + #[cfg_attr(not(feature = "self-update"), expect(unused_variables))] fn exec(self, output: OutputOpts) -> Result { let output = output.init(); diff --git a/cargo-nextest/src/errors.rs b/cargo-nextest/src/errors.rs index ce3cc13b93a..56dbb383011 100644 --- a/cargo-nextest/src/errors.rs +++ b/cargo-nextest/src/errors.rs @@ -336,7 +336,7 @@ impl ExpectedError { } } - #[allow(dead_code)] + #[expect(dead_code)] pub(crate) fn experimental_feature_error(name: &'static str, var_name: &'static str) -> Self { Self::ExperimentalFeatureNotEnabled { name, var_name } } diff --git a/integration-tests/tests/integration/fixtures.rs b/integration-tests/tests/integration/fixtures.rs index 1c3217dc791..2f2fbc741e1 100644 --- a/integration-tests/tests/integration/fixtures.rs +++ b/integration-tests/tests/integration/fixtures.rs @@ -48,7 +48,7 @@ impl CargoNextestCli { } } - #[allow(dead_code)] + #[expect(dead_code)] pub fn arg(&mut self, arg: impl Into) -> &mut Self { self.args.push(arg.into()); self @@ -64,7 +64,7 @@ impl CargoNextestCli { self } - #[allow(dead_code)] + #[expect(dead_code)] pub fn envs( &mut self, envs: impl IntoIterator, impl Into)>, diff --git a/integration-tests/tests/integration/temp_project.rs b/integration-tests/tests/integration/temp_project.rs index e70228a60d7..d4aed868c62 100644 --- a/integration-tests/tests/integration/temp_project.rs +++ b/integration-tests/tests/integration/temp_project.rs @@ -79,14 +79,13 @@ impl TempProject { }) } - #[allow(dead_code)] + #[expect(dead_code)] pub fn persist(&mut self) { if let Some(dir) = self.temp_dir.take() { _ = dir.into_path(); } } - #[allow(dead_code)] pub fn temp_root(&self) -> &Utf8Path { &self.temp_root } @@ -168,7 +167,7 @@ pub(crate) use windows::*; #[derive(Clone, Copy, Debug, PartialEq)] #[must_use] -#[allow(dead_code)] +#[expect(dead_code)] pub(crate) enum UdsStatus { Created, NotCreated, diff --git a/nextest-filtering/src/parsing.rs b/nextest-filtering/src/parsing.rs index 73e765b44eb..d2fdad88e63 100644 --- a/nextest-filtering/src/parsing.rs +++ b/nextest-filtering/src/parsing.rs @@ -61,6 +61,7 @@ pub enum SetDef { } impl SetDef { + #[cfg(test)] fn drop_source_span(self) -> SetDef<()> { match self { Self::Package(matcher, _) => SetDef::Package(matcher, ()), @@ -154,7 +155,7 @@ impl ParsedExpr { ParsedExpr::Set(SetDef::None) } - #[allow(unused)] + #[cfg(test)] fn drop_source_span(self) -> ParsedExpr<()> { match self { Self::Not(op, expr) => ParsedExpr::Not(op, Box::new(expr.drop_source_span())), diff --git a/nextest-filtering/src/proptest_helpers.rs b/nextest-filtering/src/proptest_helpers.rs index ee2abf7ae66..191d5be2b31 100644 --- a/nextest-filtering/src/proptest_helpers.rs +++ b/nextest-filtering/src/proptest_helpers.rs @@ -1,10 +1,6 @@ // Copyright (c) The nextest Contributors // SPDX-License-Identifier: MIT OR Apache-2.0 -// https://github.com/proptest-rs/proptest/pull/363, can be removed once that is in a released -// version of proptest. -#![allow(clippy::arc_with_non_send_sync)] - use crate::{ parsing::{ AndOperator, DifferenceOperator, GenericGlob, NotOperator, OrOperator, ParsedExpr, SetDef, diff --git a/nextest-filtering/tests/match.rs b/nextest-filtering/tests/match.rs index 6b0497f537d..3cd6b69c12b 100644 --- a/nextest-filtering/tests/match.rs +++ b/nextest-filtering/tests/match.rs @@ -1,9 +1,6 @@ // Copyright (c) The nextest Contributors // SPDX-License-Identifier: MIT OR Apache-2.0 -// test_case causes clippy warnings with Rust 1.71. -#![allow(clippy::items_after_test_module)] - use guppy::{ graph::{cargo::BuildPlatform, PackageGraph}, PackageId, diff --git a/nextest-runner/src/cargo_config/env.rs b/nextest-runner/src/cargo_config/env.rs index 7c4b45e4b5d..36997276f39 100644 --- a/nextest-runner/src/cargo_config/env.rs +++ b/nextest-runner/src/cargo_config/env.rs @@ -40,8 +40,7 @@ impl EnvironmentMap { let mut map = BTreeMap::::new(); for (source, name, value) in env_configs { - #[allow(clippy::useless_conversion)] - match map.entry(OsString::from(name.clone()).into()) { + match map.entry(imp::EnvKey::from(name.clone())) { Entry::Occupied(mut entry) => { // Ignore the value lower in precedence, but do look at force and relative if // they haven't been set already. @@ -79,7 +78,7 @@ impl EnvironmentMap { } pub(crate) fn apply_env(&self, command: &mut Command) { - #[allow(clippy::useless_conversion)] + #[cfg_attr(not(windows), expect(clippy::useless_conversion))] let existing_keys: BTreeSet = std::env::vars_os().map(|(k, _v)| k.into()).collect(); @@ -250,6 +249,12 @@ mod imp { } } + impl From for EnvKey { + fn from(k: String) -> Self { + OsString::from(k).into() + } + } + impl From for OsString { fn from(k: EnvKey) -> Self { k.os_string diff --git a/nextest-runner/src/config/config_impl.rs b/nextest-runner/src/config/config_impl.rs index fa50d858c46..41d57a1f537 100644 --- a/nextest-runner/src/config/config_impl.rs +++ b/nextest-runner/src/config/config_impl.rs @@ -278,7 +278,7 @@ impl NextestConfig { Ok((config.into_config_impl(), compiled)) } - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn deserialize_individual_config( graph: &PackageGraph, workspace_root: &Utf8Path, @@ -814,7 +814,7 @@ impl<'cfg> EvaluatableProfile<'cfg> { }) } - #[allow(dead_code)] + #[cfg(test)] pub(super) fn custom_profile(&self) -> Option<&'cfg CustomProfileImpl> { self.custom_profile } @@ -899,10 +899,10 @@ struct NextestConfigDeserialize { // These are parsed as part of NextestConfigVersionOnly. They're re-parsed here to avoid // printing an "unknown key" message. - #[allow(unused)] + #[expect(unused)] #[serde(default)] nextest_version: Option, - #[allow(unused)] + #[expect(unused)] #[serde(default)] experimental: BTreeSet, @@ -1067,8 +1067,8 @@ pub(super) struct CustomProfileImpl { archive: Option, } -#[allow(dead_code)] impl CustomProfileImpl { + #[cfg(test)] pub(super) fn test_threads(&self) -> Option { self.test_threads } diff --git a/nextest-runner/src/config/overrides.rs b/nextest-runner/src/config/overrides.rs index 4e8069b6155..b91dd9a4c3c 100644 --- a/nextest-runner/src/config/overrides.rs +++ b/nextest-runner/src/config/overrides.rs @@ -118,7 +118,7 @@ impl TestSettings { } } -#[allow(dead_code)] +#[expect(dead_code)] impl TestSettings { pub(super) fn new<'p>(profile: &'p EvaluatableProfile<'_>, query: &TestQuery<'_>) -> Self where @@ -932,7 +932,7 @@ mod tests { assert_eq!(overrides.success_output(), TestOutputDisplay::Never); assert_eq!(overrides.failure_output(), TestOutputDisplay::Final); // For clarity. - #[allow(clippy::bool_assert_comparison)] + #[expect(clippy::bool_assert_comparison)] { assert_eq!(overrides.junit_store_success_output(), false); assert_eq!(overrides.junit_store_failure_output(), false); @@ -978,7 +978,7 @@ mod tests { ); assert_eq!(overrides.failure_output(), TestOutputDisplay::Final); // For clarity. - #[allow(clippy::bool_assert_comparison)] + #[expect(clippy::bool_assert_comparison)] { assert_eq!(overrides.junit_store_success_output(), true); assert_eq!(overrides.junit_store_failure_output(), false); diff --git a/nextest-runner/src/double_spawn.rs b/nextest-runner/src/double_spawn.rs index 88a3dcffb51..565e13a3e4b 100644 --- a/nextest-runner/src/double_spawn.rs +++ b/nextest-runner/src/double_spawn.rs @@ -77,7 +77,7 @@ impl DoubleSpawnInfo { #[derive(Debug)] pub struct DoubleSpawnContext { // Only used for the Drop impl. - #[allow(dead_code)] + #[expect(dead_code)] inner: imp::DoubleSpawnContext, } diff --git a/nextest-runner/src/helpers.rs b/nextest-runner/src/helpers.rs index 8939d47dbb0..e7b5b0918bc 100644 --- a/nextest-runner/src/helpers.rs +++ b/nextest-runner/src/helpers.rs @@ -373,7 +373,7 @@ extern "C" { } #[inline] -#[allow(dead_code)] +#[expect(dead_code)] pub(crate) fn statically_unreachable() -> ! { unsafe { __nextest_external_symbol_that_does_not_exist(); diff --git a/nextest-runner/src/indenter.rs b/nextest-runner/src/indenter.rs index 5f165ffd303..2e9dab3e3eb 100644 --- a/nextest-runner/src/indenter.rs +++ b/nextest-runner/src/indenter.rs @@ -20,7 +20,7 @@ use crate::write_str::WriteStr; use std::io; /// The set of supported formats for indentation -#[allow(missing_debug_implementations)] +#[expect(missing_debug_implementations)] pub enum Format<'a> { /// Insert uniform indentation before every line /// @@ -55,7 +55,7 @@ pub enum Format<'a> { /// lets it intercept each piece of output as its being written to the output buffer. It then /// splits on newlines giving slices into the original string. Finally we alternate writing these /// lines and the specified indentation to the output buffer. -#[allow(missing_debug_implementations)] +#[expect(missing_debug_implementations)] pub struct Indented<'a, D: ?Sized> { inner: &'a mut D, needs_indent: bool, diff --git a/nextest-runner/src/list/output_format.rs b/nextest-runner/src/list/output_format.rs index 2fb9ac96ae7..a62de0b937d 100644 --- a/nextest-runner/src/list/output_format.rs +++ b/nextest-runner/src/list/output_format.rs @@ -1,9 +1,6 @@ // Copyright (c) The nextest Contributors // SPDX-License-Identifier: MIT OR Apache-2.0 -// clippy complains about the Arbitrary impl for OutputFormat -#![allow(clippy::unit_arg)] - use crate::{errors::WriteTestListError, write_str::WriteStr}; use owo_colors::Style; use serde::Serialize; diff --git a/nextest-runner/src/list/test_list.rs b/nextest-runner/src/list/test_list.rs index 254b15a048e..991d3fab1ab 100644 --- a/nextest-runner/src/list/test_list.rs +++ b/nextest-runner/src/list/test_list.rs @@ -220,7 +220,7 @@ pub struct TestList<'g> { impl<'g> TestList<'g> { /// Creates a new test list by running the given command and applying the specified filter. - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] pub fn new( ctx: &TestExecuteContext<'_>, test_artifacts: I, diff --git a/nextest-runner/src/reporter/aggregator.rs b/nextest-runner/src/reporter/aggregator.rs index e3fe2101b41..33e4e87abf9 100644 --- a/nextest-runner/src/reporter/aggregator.rs +++ b/nextest-runner/src/reporter/aggregator.rs @@ -20,7 +20,7 @@ use quick_junit::{ use std::{borrow::Cow, collections::HashMap, fs::File}; #[derive(Clone, Debug)] -#[allow(dead_code)] +#[expect(dead_code)] pub(crate) struct EventAggregator<'cfg> { store_dir: Utf8PathBuf, // TODO: log information in a JSONable report (converting that to XML later) instead of directly diff --git a/nextest-runner/src/reporter/displayer.rs b/nextest-runner/src/reporter/displayer.rs index cb52809969e..d632c27f799 100644 --- a/nextest-runner/src/reporter/displayer.rs +++ b/nextest-runner/src/reporter/displayer.rs @@ -562,7 +562,7 @@ fn write_summary_str(run_stats: &RunStats, styles: &Styles, out: &mut String) { #[derive(Debug)] enum FinalOutput { - Skipped(#[allow(dead_code)] MismatchReason), + Skipped(#[expect(dead_code)] MismatchReason), Executed { run_statuses: ExecutionStatuses, display_output: bool, @@ -1068,7 +1068,7 @@ impl<'a> TestReporterImpl<'a> { Ok(()) } - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn write_setup_script_status_line( &self, script_id: &ScriptId, diff --git a/nextest-runner/src/reuse_build/archiver.rs b/nextest-runner/src/reuse_build/archiver.rs index 3de79ef6c68..96bf205e308 100644 --- a/nextest-runner/src/reuse_build/archiver.rs +++ b/nextest-runner/src/reuse_build/archiver.rs @@ -56,7 +56,7 @@ impl ArchiveFormat { /// Archives test binaries along with metadata to the given file. /// /// The output file is a Zstandard-compressed tarball (`.tar.zst`). -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments)] pub fn archive_to_file<'a, F>( profile: EvaluatableProfile<'a>, binary_list: &'a BinaryList, @@ -195,7 +195,7 @@ struct Archiver<'a, W: Write> { } impl<'a, W: Write> Archiver<'a, W> { - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn new( config: &'a ArchiveConfig, binary_list: &'a BinaryList, diff --git a/nextest-runner/src/runner.rs b/nextest-runner/src/runner.rs index dcc3b5a82b6..58953a65b4e 100644 --- a/nextest-runner/src/runner.rs +++ b/nextest-runner/src/runner.rs @@ -1233,14 +1233,16 @@ fn drain_req_rx(mut receiver: UnboundedReceiver) { // It would be nice to fix this function to not have so many arguments, but this // code is actively being refactored right now and imposing too much structure // can cause more harm than good. -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments)] async fn handle_signal_request( child: &mut Child, child_acc: &mut ChildAccumulator, req: SignalRequest, // These annotations are needed to silence lints on non-Unix platforms. stopwatch: &mut StopwatchStart, - #[allow(unused_mut, unused_variables)] mut interval_sleep: Pin<&mut PausableSleep>, + #[cfg_attr(not(unix), expect(unused_mut, unused_variables))] mut interval_sleep: Pin< + &mut PausableSleep, + >, req_rx: &mut UnboundedReceiver, job: Option<&imp::Job>, grace_period: Duration, @@ -1334,7 +1336,7 @@ pub struct ExecutionStatuses { statuses: Vec, } -#[allow(clippy::len_without_is_empty)] // RunStatuses is never empty +#[expect(clippy::len_without_is_empty)] // RunStatuses is never empty impl ExecutionStatuses { fn new(statuses: Vec) -> Self { Self { statuses } @@ -1852,7 +1854,7 @@ impl<'a> SetupScriptPacket<'a> { /// The return result of `handle_event`. #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum HandleEventResponse { - #[cfg_attr(not(unix), allow(dead_code))] + #[cfg_attr(not(unix), expect(dead_code))] JobControl(JobControlEvent), } @@ -2302,11 +2304,11 @@ where struct ContextSetupScript<'a> { id: ScriptId, // Store these details primarily for debugging. - #[allow(dead_code)] + #[expect(dead_code)] config: &'a ScriptConfig, - #[allow(dead_code)] + #[expect(dead_code)] index: usize, - #[allow(dead_code)] + #[expect(dead_code)] total: usize, req_tx: UnboundedSender, } @@ -2314,7 +2316,7 @@ struct ContextSetupScript<'a> { #[derive(Debug)] struct ContextTestInstance<'a> { // Store the instance primarily for debugging. - #[allow(dead_code)] + #[expect(dead_code)] instance: TestInstance<'a>, past_attempts: Vec, req_tx: UnboundedSender, @@ -2332,7 +2334,6 @@ impl ContextTestInstance<'_> { } } -#[allow(clippy::large_enum_variant)] #[derive(Debug)] enum InternalEvent<'a> { Test(InternalTestEvent<'a>), diff --git a/nextest-runner/src/test_command/unix.rs b/nextest-runner/src/test_command/unix.rs index 7a23a8940e7..237cc516409 100644 --- a/nextest-runner/src/test_command/unix.rs +++ b/nextest-runner/src/test_command/unix.rs @@ -9,7 +9,7 @@ use std::{ pub(super) struct State { pub(super) ours: OwnedFd, - #[allow(dead_code)] + #[expect(dead_code)] theirs: OwnedFd, } diff --git a/nextest-runner/src/test_filter.rs b/nextest-runner/src/test_filter.rs index 2206383d4cd..98eb8a56081 100644 --- a/nextest-runner/src/test_filter.rs +++ b/nextest-runner/src/test_filter.rs @@ -5,10 +5,6 @@ //! //! The main structure in this module is [`TestFilter`], which is created by a [`TestFilterBuilder`]. -#![allow(clippy::nonminimal_bool)] -// nonminimal_bool fires on one of the conditions below and appears to suggest an incorrect -// result - use crate::{ errors::TestFilterBuilderError, list::RustTestArtifact, @@ -780,7 +776,7 @@ mod tests { // Test that dropping a character from a string doesn't match. #[proptest(cases = 50)] fn proptest_no_match(substring: String, prefix: String, suffix: String) { - prop_assume!(!substring.is_empty() && !(prefix.is_empty() && suffix.is_empty())); + prop_assume!(!substring.is_empty() && !prefix.is_empty() && !suffix.is_empty()); let pattern = prefix + &substring + &suffix; let patterns = TestFilterPatterns::new(vec![pattern]); let test_filter = diff --git a/nextest-runner/src/time/mod.rs b/nextest-runner/src/time/mod.rs index 60775f05c02..b8d35c99a18 100644 --- a/nextest-runner/src/time/mod.rs +++ b/nextest-runner/src/time/mod.rs @@ -1,7 +1,7 @@ // Copyright (c) The nextest Contributors // SPDX-License-Identifier: MIT OR Apache-2.0 -#![cfg_attr(not(unix), allow(dead_code))] +#![cfg_attr(not(unix), expect(dead_code))] mod pausable_sleep; mod stopwatch; diff --git a/nextest-runner/src/time/stopwatch.rs b/nextest-runner/src/time/stopwatch.rs index d446582036a..8222af3f4b1 100644 --- a/nextest-runner/src/time/stopwatch.rs +++ b/nextest-runner/src/time/stopwatch.rs @@ -85,7 +85,7 @@ pub(crate) struct StopwatchSnapshot { pub(crate) active: Duration, /// The amount of time spent while the stopwatch was paused. - #[allow(dead_code)] + #[expect(dead_code)] pub(crate) paused: Duration, } diff --git a/nextest-runner/src/update.rs b/nextest-runner/src/update.rs index 536e37bc77b..067d8939235 100644 --- a/nextest-runner/src/update.rs +++ b/nextest-runner/src/update.rs @@ -312,7 +312,7 @@ impl MuktiUpdateContext<'_> { )) })?; let tmp_backup_dir_prefix = format!("__{}_backup", self.context.package_name); - #[allow(clippy::redundant_clone)] + #[expect(clippy::redundant_clone)] let tmp_backup_filename = tmp_backup_dir_prefix.clone(); if cfg!(windows) { diff --git a/nextest-runner/tests/integration/basic.rs b/nextest-runner/tests/integration/basic.rs index a3bbdcaf6c8..117fafa924e 100644 --- a/nextest-runner/tests/integration/basic.rs +++ b/nextest-runner/tests/integration/basic.rs @@ -160,7 +160,7 @@ fn test_run() -> Result<()> { false } else { // Extracting descriptions works for segfaults on Unix but not on Windows. - #[allow(unused_mut)] + #[cfg_attr(not(unix), expect(unused_mut))] let mut can_extract_description = fixture.status == TestCaseFixtureStatus::Fail || fixture.status == TestCaseFixtureStatus::IgnoredFail; diff --git a/nextest-runner/tests/integration/fixtures.rs b/nextest-runner/tests/integration/fixtures.rs index 614612fe042..5ae5ce7347c 100644 --- a/nextest-runner/tests/integration/fixtures.rs +++ b/nextest-runner/tests/integration/fixtures.rs @@ -276,7 +276,7 @@ impl FixtureTargets { } #[derive(Clone, Debug)] -#[allow(dead_code)] +#[expect(dead_code)] pub(crate) struct InstanceValue<'a> { pub(crate) binary_id: &'a str, pub(crate) cwd: &'a Utf8Path, diff --git a/nextest-runner/tests/integration/target_runner.rs b/nextest-runner/tests/integration/target_runner.rs index aa0fba9a363..ee5c5f9759d 100644 --- a/nextest-runner/tests/integration/target_runner.rs +++ b/nextest-runner/tests/integration/target_runner.rs @@ -271,7 +271,7 @@ fn test_run_with_target_runner() -> Result<()> { ); let run_status = run_statuses.last_status(); - #[allow(unused_mut)] + #[cfg_attr(not(unix), expect(unused_mut))] let mut expected_status = make_execution_result(fixture.status, 1); // On Unix, segfaults aren't passed through by the passthrough runner. cfg_if::cfg_if! {