From 39b0411c635cbef7865b4d5f12375a1de3da288d Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 5 Jan 2026 15:35:59 -0800 Subject: [PATCH 1/8] Check required-version before parsing rules --- crates/ruff/tests/cli/lint.rs | 55 +++++++++++++++++++--- crates/ruff_workspace/src/configuration.rs | 12 ++--- crates/ruff_workspace/src/options.rs | 15 ++++++ crates/ruff_workspace/src/pyproject.rs | 34 ++++++++++++- 4 files changed, 99 insertions(+), 17 deletions(-) diff --git a/crates/ruff/tests/cli/lint.rs b/crates/ruff/tests/cli/lint.rs index 04cabca512cf8..9de4c015c16d0 100644 --- a/crates/ruff/tests/cli/lint.rs +++ b/crates/ruff/tests/cli/lint.rs @@ -1137,9 +1137,9 @@ required-version = "0.1.0" "#, )?; - insta::with_settings!({ - filters => vec![(version, "[VERSION]")] - }, { + let mut settings = insta::Settings::clone_current(); + settings.add_filter(version, "[VERSION]"); + settings.bind(|| { assert_cmd_snapshot!(fixture .check_command() .arg("--config") @@ -1154,6 +1154,7 @@ import os ----- stderr ----- ruff failed + Cause: Failed to load configuration `[TMP]/ruff.toml` Cause: Required version `==0.1.0` does not match the running version `[VERSION]` "); }); @@ -1212,9 +1213,50 @@ required-version = ">{version}" ), )?; - insta::with_settings!({ - filters => vec![(version, "[VERSION]")] - }, { + let mut settings = insta::Settings::clone_current(); + settings.add_filter(version, "[VERSION]"); + settings.bind(|| { + assert_cmd_snapshot!(fixture + .check_command() + .arg("--config") + .arg("ruff.toml") + .arg("-") + .pass_stdin(r#" +import os +"#), @" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + ruff failed + Cause: Failed to load configuration `[TMP]/ruff.toml` + Cause: Required version `>[VERSION]` does not match the running version `[VERSION]` + "); + }); + + Ok(()) +} + +#[test] +fn required_version_precedes_rule_validation() -> Result<()> { + let version = env!("CARGO_PKG_VERSION"); + + let fixture = CliTest::with_file( + "ruff.toml", + &format!( + r#" +required-version = ">{version}" + +[lint] +select = ["RUF999"] +"# + ), + )?; + + let mut settings = insta::Settings::clone_current(); + settings.add_filter(version, "[VERSION]"); + settings.bind(|| { assert_cmd_snapshot!(fixture .check_command() .arg("--config") @@ -1229,6 +1271,7 @@ import os ----- stderr ----- ruff failed + Cause: Failed to load configuration `[TMP]/ruff.toml` Cause: Required version `>[VERSION]` does not match the running version `[VERSION]` "); }); diff --git a/crates/ruff_workspace/src/configuration.rs b/crates/ruff_workspace/src/configuration.rs index bf50749a45dc6..12bb62b2f8e7a 100644 --- a/crates/ruff_workspace/src/configuration.rs +++ b/crates/ruff_workspace/src/configuration.rs @@ -7,7 +7,6 @@ use std::collections::BTreeMap; use std::env::VarError; use std::num::{NonZeroU8, NonZeroU16}; use std::path::{Path, PathBuf}; -use std::str::FromStr; use anyhow::{Context, Result, anyhow}; use glob::{GlobError, Paths, PatternError, glob}; @@ -36,7 +35,7 @@ use ruff_linter::settings::{ DEFAULT_SELECTORS, DUMMY_VARIABLE_RGX, LinterSettings, TASK_TAGS, TargetVersion, }; use ruff_linter::{ - RUFF_PKG_VERSION, RuleSelector, fs, warn_user_once, warn_user_once_by_id, + RuleSelector, fs, warn_user_once, warn_user_once_by_id, warn_user_once_by_message, }; use ruff_python_ast as ast; @@ -53,6 +52,7 @@ use crate::options::{ Flake8UnusedArgumentsOptions, FormatOptions, IsortOptions, LintCommonOptions, LintOptions, McCabeOptions, Options, Pep8NamingOptions, PyUpgradeOptions, PycodestyleOptions, PydoclintOptions, PydocstyleOptions, PyflakesOptions, PylintOptions, RuffOptions, + validate_required_version, }; use crate::settings::{ EXCLUDE, FileResolverSettings, FormatterSettings, INCLUDE, INCLUDE_PREVIEW, LineEnding, @@ -155,13 +155,7 @@ pub struct Configuration { impl Configuration { pub fn into_settings(self, project_root: &Path) -> Result { if let Some(required_version) = &self.required_version { - let ruff_pkg_version = pep440_rs::Version::from_str(RUFF_PKG_VERSION) - .expect("RUFF_PKG_VERSION is not a valid PEP 440 version specifier"); - if !required_version.contains(&ruff_pkg_version) { - return Err(anyhow!( - "Required version `{required_version}` does not match the running version `{RUFF_PKG_VERSION}`" - )); - } + validate_required_version(required_version)?; } let linter_target_version = TargetVersion(self.target_version); diff --git a/crates/ruff_workspace/src/options.rs b/crates/ruff_workspace/src/options.rs index 087914d8f8cc4..457e17752117e 100644 --- a/crates/ruff_workspace/src/options.rs +++ b/crates/ruff_workspace/src/options.rs @@ -6,10 +6,14 @@ use std::collections::{BTreeMap, BTreeSet}; use std::path::PathBuf; use strum::IntoEnumIterator; use unicode_normalization::UnicodeNormalization; +use anyhow::Result; +use std::str::FromStr; use crate::settings::LineEnding; use ruff_formatter::IndentStyle; use ruff_graph::Direction; +use ruff_linter::RUFF_PKG_VERSION; + use ruff_linter::line_width::{IndentWidth, LineLength}; use ruff_linter::rules::flake8_import_conventions::settings::BannedAliases; use ruff_linter::rules::flake8_pytest_style::settings::SettingsError; @@ -556,6 +560,17 @@ pub struct LintOptions { pub future_annotations: Option, } +pub fn validate_required_version(required_version: &RequiredVersion) -> anyhow::Result<()> { + let ruff_pkg_version = pep440_rs::Version::from_str(RUFF_PKG_VERSION) + .expect("RUFF_PKG_VERSION is not a valid PEP 440 version specifier"); + if !required_version.contains(&ruff_pkg_version) { + return Err(anyhow::anyhow!( + "Required version `{required_version}` does not match the running version `{RUFF_PKG_VERSION}`" + )); + } + Ok(()) +} + /// Newtype wrapper for [`LintCommonOptions`] that allows customizing the JSON schema and omitting the fields from the [`OptionsMetadata`]. #[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize)] #[serde(transparent)] diff --git a/crates/ruff_workspace/src/pyproject.rs b/crates/ruff_workspace/src/pyproject.rs index 53649a31e800a..13147fd92c4da 100644 --- a/crates/ruff_workspace/src/pyproject.rs +++ b/crates/ruff_workspace/src/pyproject.rs @@ -8,9 +8,9 @@ use pep440_rs::{Operator, Version, VersionSpecifiers}; use serde::{Deserialize, Serialize}; use strum::IntoEnumIterator; -use ruff_linter::settings::types::PythonVersion; +use ruff_linter::settings::types::{PythonVersion, RequiredVersion}; -use crate::options::Options; +use crate::options::{Options, validate_required_version}; #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] struct Tools { @@ -45,6 +45,7 @@ fn parse_ruff_toml>(path: P) -> Result { let path = path.as_ref(); let contents = std::fs::read_to_string(path) .with_context(|| format!("Failed to read {}", path.display()))?; + check_required_version(&contents, path, &[])?; toml::from_str(&contents).with_context(|| format!("Failed to parse {}", path.display())) } @@ -53,6 +54,7 @@ fn parse_pyproject_toml>(path: P) -> Result { let path = path.as_ref(); let contents = std::fs::read_to_string(path) .with_context(|| format!("Failed to read {}", path.display()))?; + check_required_version(&contents, path, &["tool", "ruff"])?; toml::from_str(&contents).with_context(|| format!("Failed to parse {}", path.display())) } @@ -98,6 +100,34 @@ pub fn find_settings_toml>(path: P) -> Result> { Ok(None) } +fn check_required_version(contents: &str, path: &Path, table_path: &[&str]) -> Result<()> { + let value: toml::Value = + toml::from_str(contents).with_context(|| format!("Failed to parse {}", path.display()))?; + let mut current = &value; + for key in table_path { + match current.get(*key) { + Some(next) => { + current = next; + } + None => return Ok(()), + } + } + + let required_version = current + .get("required-version") + .or_else(|| current.get("required_version")) + .and_then(|value| value.as_str()); + + let Some(required_version) = required_version else { + return Ok(()); + }; + + let required_version = RequiredVersion::try_from(required_version.to_string()) + .with_context(|| format!("Failed to parse {}", path.display()))?; + validate_required_version(&required_version)?; + Ok(()) +} + /// Derive target version from `required-version` in `pyproject.toml`, if /// such a file exists in an ancestor directory. pub fn find_fallback_target_version>(path: P) -> Option { From 8771a6eb73e10aea0caf0b8ab3a724ccefa7f42d Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 6 Jan 2026 09:19:42 -0800 Subject: [PATCH 2/8] try --- crates/ruff_workspace/src/pyproject.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/ruff_workspace/src/pyproject.rs b/crates/ruff_workspace/src/pyproject.rs index 13147fd92c4da..4e57c82fb4dbc 100644 --- a/crates/ruff_workspace/src/pyproject.rs +++ b/crates/ruff_workspace/src/pyproject.rs @@ -40,22 +40,27 @@ impl Pyproject { } } -/// Parse a `ruff.toml` file. -fn parse_ruff_toml>(path: P) -> Result { +fn parse_toml>(path: P) -> Result { let path = path.as_ref(); let contents = std::fs::read_to_string(path) .with_context(|| format!("Failed to read {}", path.display()))?; - check_required_version(&contents, path, &[])?; toml::from_str(&contents).with_context(|| format!("Failed to parse {}", path.display())) } +/// Parse a `ruff.toml` file. +fn parse_ruff_toml>(path: P) -> Result { + let path = path.as_ref(); + let toml = parse_toml(path)?; + check_required_version(&toml, path, &[])?; + toml.try_into().with_context(|| format!("Failed to parse {}", path.display())) +} + /// Parse a `pyproject.toml` file. fn parse_pyproject_toml>(path: P) -> Result { let path = path.as_ref(); - let contents = std::fs::read_to_string(path) - .with_context(|| format!("Failed to read {}", path.display()))?; - check_required_version(&contents, path, &["tool", "ruff"])?; - toml::from_str(&contents).with_context(|| format!("Failed to parse {}", path.display())) + let toml = parse_toml(path)?; + check_required_version(&toml, path, &["tool", "ruff"])?; + toml.try_into().with_context(|| format!("Failed to parse {}", path.display())) } /// Return `true` if a `pyproject.toml` contains a `[tool.ruff]` section. @@ -100,10 +105,8 @@ pub fn find_settings_toml>(path: P) -> Result> { Ok(None) } -fn check_required_version(contents: &str, path: &Path, table_path: &[&str]) -> Result<()> { - let value: toml::Value = - toml::from_str(contents).with_context(|| format!("Failed to parse {}", path.display()))?; - let mut current = &value; +fn check_required_version(value: &toml::Value, path: &Path, table_path: &[&str]) -> Result<()> { + let mut current = value; for key in table_path { match current.get(*key) { Some(next) => { From 38e95ac79af1a9441d532a0ecdb82ac8a3c2c7e5 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 6 Jan 2026 10:36:39 -0800 Subject: [PATCH 3/8] codex fixed it --- crates/ruff_workspace/src/pyproject.rs | 52 +++++++++++++++++--------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/crates/ruff_workspace/src/pyproject.rs b/crates/ruff_workspace/src/pyproject.rs index 4e57c82fb4dbc..aca7480f2b29d 100644 --- a/crates/ruff_workspace/src/pyproject.rs +++ b/crates/ruff_workspace/src/pyproject.rs @@ -5,6 +5,7 @@ use std::path::{Path, PathBuf}; use anyhow::{Context, Result}; use log::debug; use pep440_rs::{Operator, Version, VersionSpecifiers}; +use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use strum::IntoEnumIterator; @@ -40,27 +41,38 @@ impl Pyproject { } } -fn parse_toml>(path: P) -> Result { +fn parse_toml, T: DeserializeOwned>(path: P, table_path: &[&str]) -> Result { let path = path.as_ref(); let contents = std::fs::read_to_string(path) .with_context(|| format!("Failed to read {}", path.display()))?; - toml::from_str(&contents).with_context(|| format!("Failed to parse {}", path.display())) + + // Parse the TOML document once into a spanned representation so we can: + // - Inspect `required-version` without triggering strict deserialization errors. + // - Deserialize with precise spans (line/column and excerpt) on errors. + let root = toml::de::DeTable::parse(&contents) + .with_context(|| format!("Failed to parse {}", path.display()))?; + + check_required_version(root.get_ref(), path, table_path)?; + + let deserializer = toml::de::Deserializer::from(root); + T::deserialize(deserializer) + .map_err(|mut err| { + // `Deserializer::from` doesn't have access to the original input, but we do. + // Attach it so TOML errors include line/column and a source excerpt. + err.set_input(Some(&contents)); + err + }) + .with_context(|| format!("Failed to parse {}", path.display())) } /// Parse a `ruff.toml` file. fn parse_ruff_toml>(path: P) -> Result { - let path = path.as_ref(); - let toml = parse_toml(path)?; - check_required_version(&toml, path, &[])?; - toml.try_into().with_context(|| format!("Failed to parse {}", path.display())) + parse_toml(path, &[]) } /// Parse a `pyproject.toml` file. fn parse_pyproject_toml>(path: P) -> Result { - let path = path.as_ref(); - let toml = parse_toml(path)?; - check_required_version(&toml, path, &["tool", "ruff"])?; - toml.try_into().with_context(|| format!("Failed to parse {}", path.display())) + parse_toml(path, &["tool", "ruff"]) } /// Return `true` if a `pyproject.toml` contains a `[tool.ruff]` section. @@ -105,21 +117,25 @@ pub fn find_settings_toml>(path: P) -> Result> { Ok(None) } -fn check_required_version(value: &toml::Value, path: &Path, table_path: &[&str]) -> Result<()> { +fn check_required_version(value: &toml::de::DeTable, path: &Path, table_path: &[&str]) -> Result<()> { let mut current = value; for key in table_path { - match current.get(*key) { - Some(next) => { - current = next; - } - None => return Ok(()), - } + let Some(next) = current.get(*key) else { + return Ok(()); + }; + let toml::de::DeValue::Table(next) = next.get_ref() else { + return Ok(()); + }; + current = next; } let required_version = current .get("required-version") .or_else(|| current.get("required_version")) - .and_then(|value| value.as_str()); + .and_then(|value| match value.get_ref() { + toml::de::DeValue::String(value) => Some(value.as_ref()), + _ => None, + }); let Some(required_version) = required_version else { return Ok(()); From 31a295b194d851155c07402f4d42f3adadaf358d Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 6 Jan 2026 13:36:23 -0800 Subject: [PATCH 4/8] format --- crates/ruff/tests/cli/lint.rs | 6 +++--- crates/ruff_workspace/src/configuration.rs | 3 +-- crates/ruff_workspace/src/options.rs | 4 ++-- crates/ruff_workspace/src/pyproject.rs | 6 +++++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/ruff/tests/cli/lint.rs b/crates/ruff/tests/cli/lint.rs index 9de4c015c16d0..3ae67109a87f2 100644 --- a/crates/ruff/tests/cli/lint.rs +++ b/crates/ruff/tests/cli/lint.rs @@ -1140,7 +1140,7 @@ required-version = "0.1.0" let mut settings = insta::Settings::clone_current(); settings.add_filter(version, "[VERSION]"); settings.bind(|| { - assert_cmd_snapshot!(fixture + assert_cmd_snapshot!(fixture .check_command() .arg("--config") .arg("ruff.toml") @@ -1216,7 +1216,7 @@ required-version = ">{version}" let mut settings = insta::Settings::clone_current(); settings.add_filter(version, "[VERSION]"); settings.bind(|| { - assert_cmd_snapshot!(fixture + assert_cmd_snapshot!(fixture .check_command() .arg("--config") .arg("ruff.toml") @@ -1257,7 +1257,7 @@ select = ["RUF999"] let mut settings = insta::Settings::clone_current(); settings.add_filter(version, "[VERSION]"); settings.bind(|| { - assert_cmd_snapshot!(fixture + assert_cmd_snapshot!(fixture .check_command() .arg("--config") .arg("ruff.toml") diff --git a/crates/ruff_workspace/src/configuration.rs b/crates/ruff_workspace/src/configuration.rs index 12bb62b2f8e7a..77d64a3f66517 100644 --- a/crates/ruff_workspace/src/configuration.rs +++ b/crates/ruff_workspace/src/configuration.rs @@ -35,8 +35,7 @@ use ruff_linter::settings::{ DEFAULT_SELECTORS, DUMMY_VARIABLE_RGX, LinterSettings, TASK_TAGS, TargetVersion, }; use ruff_linter::{ - RuleSelector, fs, warn_user_once, warn_user_once_by_id, - warn_user_once_by_message, + RuleSelector, fs, warn_user_once, warn_user_once_by_id, warn_user_once_by_message, }; use ruff_python_ast as ast; use ruff_python_formatter::{ diff --git a/crates/ruff_workspace/src/options.rs b/crates/ruff_workspace/src/options.rs index 457e17752117e..f2c15755c170a 100644 --- a/crates/ruff_workspace/src/options.rs +++ b/crates/ruff_workspace/src/options.rs @@ -1,13 +1,13 @@ +use anyhow::Result; use regex::Regex; use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; use serde::de::{self}; use serde::{Deserialize, Deserializer, Serialize}; use std::collections::{BTreeMap, BTreeSet}; use std::path::PathBuf; +use std::str::FromStr; use strum::IntoEnumIterator; use unicode_normalization::UnicodeNormalization; -use anyhow::Result; -use std::str::FromStr; use crate::settings::LineEnding; use ruff_formatter::IndentStyle; diff --git a/crates/ruff_workspace/src/pyproject.rs b/crates/ruff_workspace/src/pyproject.rs index aca7480f2b29d..cbf5518d8cf6e 100644 --- a/crates/ruff_workspace/src/pyproject.rs +++ b/crates/ruff_workspace/src/pyproject.rs @@ -117,7 +117,11 @@ pub fn find_settings_toml>(path: P) -> Result> { Ok(None) } -fn check_required_version(value: &toml::de::DeTable, path: &Path, table_path: &[&str]) -> Result<()> { +fn check_required_version( + value: &toml::de::DeTable, + path: &Path, + table_path: &[&str], +) -> Result<()> { let mut current = value; for key in table_path { let Some(next) = current.get(*key) else { From 24b281392cec5666551a9dad49ffe43b4a01d063 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Wed, 7 Jan 2026 09:35:28 +0100 Subject: [PATCH 5/8] nits --- crates/ruff_linter/src/settings/types.rs | 10 +++++++++- crates/ruff_workspace/src/pyproject.rs | 8 +++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index 05cd13909b69b..8b77ffdd7e0cd 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -604,8 +604,16 @@ impl TryFrom for RequiredVersion { type Error = pep440_rs::VersionSpecifiersParseError; fn try_from(value: String) -> Result { + value.parse() + } +} + +impl FromStr for RequiredVersion { + type Err = pep440_rs::VersionSpecifiersParseError; + + fn from_str(value: &str) -> Result { // Treat `0.3.1` as `==0.3.1`, for backwards compatibility. - if let Ok(version) = pep440_rs::Version::from_str(&value) { + if let Ok(version) = pep440_rs::Version::from_str(value) { Ok(Self(VersionSpecifiers::from( VersionSpecifier::equals_version(version), ))) diff --git a/crates/ruff_workspace/src/pyproject.rs b/crates/ruff_workspace/src/pyproject.rs index cbf5518d8cf6e..25d8cfd271096 100644 --- a/crates/ruff_workspace/src/pyproject.rs +++ b/crates/ruff_workspace/src/pyproject.rs @@ -136,16 +136,14 @@ fn check_required_version( let required_version = current .get("required-version") .or_else(|| current.get("required_version")) - .and_then(|value| match value.get_ref() { - toml::de::DeValue::String(value) => Some(value.as_ref()), - _ => None, - }); + .and_then(|value| value.get_ref().as_str()); let Some(required_version) = required_version else { return Ok(()); }; - let required_version = RequiredVersion::try_from(required_version.to_string()) + let required_version: RequiredVersion = required_version + .parse() .with_context(|| format!("Failed to parse {}", path.display()))?; validate_required_version(&required_version)?; Ok(()) From 03eb405b5f949b5f48c17e93d09c08d2a6b20693 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Wed, 7 Jan 2026 08:54:15 -0800 Subject: [PATCH 6/8] Feedback from Micha --- crates/ruff/tests/cli/lint.rs | 29 ++++++++++++++++++++++++++ crates/ruff_workspace/src/pyproject.rs | 9 ++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/crates/ruff/tests/cli/lint.rs b/crates/ruff/tests/cli/lint.rs index 3ae67109a87f2..ec0bbc4f477b2 100644 --- a/crates/ruff/tests/cli/lint.rs +++ b/crates/ruff/tests/cli/lint.rs @@ -1126,6 +1126,35 @@ import os Ok(()) } +#[test] +fn required_version_fails_to_parse() -> Result<()> { + let fixture = CliTest::with_file( + "ruff.toml", + r#" +required-version = "pikachu" +"#, + )?; + assert_cmd_snapshot!(fixture + .check_command(), @r#" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + ruff failed + Cause: Failed to load configuration `[TMP]/ruff.toml` + Cause: Failed to parse [TMP]/ruff.toml + Cause: TOML parse error at line 2, column 20 + | + 2 | required-version = "pikachu" + | ^^^^^^^^^ + Failed to parse version: Unexpected end of version specifier, expected operator: + pikachu + ^^^^^^^ + "#); + Ok(()) +} + #[test] fn required_version_exact_mismatch() -> Result<()> { let version = env!("CARGO_PKG_VERSION"); diff --git a/crates/ruff_workspace/src/pyproject.rs b/crates/ruff_workspace/src/pyproject.rs index 25d8cfd271096..c08556d84b3f0 100644 --- a/crates/ruff_workspace/src/pyproject.rs +++ b/crates/ruff_workspace/src/pyproject.rs @@ -135,17 +135,16 @@ fn check_required_version( let required_version = current .get("required-version") - .or_else(|| current.get("required_version")) .and_then(|value| value.get_ref().as_str()); let Some(required_version) = required_version else { return Ok(()); }; - let required_version: RequiredVersion = required_version - .parse() - .with_context(|| format!("Failed to parse {}", path.display()))?; - validate_required_version(&required_version)?; + // If it doesn't parse, we just fall through to normal parsing; it will give a nicer error message. + if let Ok(required_version) = required_version.parse::() { + validate_required_version(&required_version)?; + } Ok(()) } From 7bc15a3fa51a87ccb8484ab4881a6e185a8b4cd1 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Wed, 7 Jan 2026 18:06:38 +0100 Subject: [PATCH 7/8] Clippy --- crates/ruff_linter/src/settings/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index 8b77ffdd7e0cd..50793cd761253 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -618,7 +618,7 @@ impl FromStr for RequiredVersion { VersionSpecifier::equals_version(version), ))) } else { - Ok(Self(VersionSpecifiers::from_str(&value)?)) + Ok(Self(VersionSpecifiers::from_str(value)?)) } } } From 2761beace0a47c670f4355a0bfefc3789fb9d3f4 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Wed, 7 Jan 2026 18:25:00 +0100 Subject: [PATCH 8/8] More clippy --- crates/ruff_workspace/src/pyproject.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/ruff_workspace/src/pyproject.rs b/crates/ruff_workspace/src/pyproject.rs index c08556d84b3f0..95c0893986f1c 100644 --- a/crates/ruff_workspace/src/pyproject.rs +++ b/crates/ruff_workspace/src/pyproject.rs @@ -52,7 +52,7 @@ fn parse_toml, T: DeserializeOwned>(path: P, table_path: &[&str]) let root = toml::de::DeTable::parse(&contents) .with_context(|| format!("Failed to parse {}", path.display()))?; - check_required_version(root.get_ref(), path, table_path)?; + check_required_version(root.get_ref(), table_path)?; let deserializer = toml::de::Deserializer::from(root); T::deserialize(deserializer) @@ -117,11 +117,7 @@ pub fn find_settings_toml>(path: P) -> Result> { Ok(None) } -fn check_required_version( - value: &toml::de::DeTable, - path: &Path, - table_path: &[&str], -) -> Result<()> { +fn check_required_version(value: &toml::de::DeTable, table_path: &[&str]) -> Result<()> { let mut current = value; for key in table_path { let Some(next) = current.get(*key) else {