Update MSRV to 1.85 and toolchain to 1.87 (#18126)

This commit is contained in:
Micha Reiser 2025-05-16 09:19:55 +02:00 committed by GitHub
parent 6e39250015
commit 196e4befba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 82 additions and 54 deletions

View file

@ -133,7 +133,7 @@ struct SourceTextInner {
#[derive(Eq, PartialEq)]
enum SourceTextKind {
Text(String),
Notebook(Notebook),
Notebook(Box<Notebook>),
}
impl From<String> for SourceTextKind {
@ -144,7 +144,7 @@ impl From<String> for SourceTextKind {
impl From<Notebook> for SourceTextKind {
fn from(notebook: Notebook) -> Self {
SourceTextKind::Notebook(notebook)
SourceTextKind::Notebook(Box::new(notebook))
}
}

View file

@ -463,17 +463,17 @@ fn not_found() -> std::io::Error {
fn is_a_directory() -> std::io::Error {
// Note: Rust returns `ErrorKind::IsADirectory` for this error but this is a nightly only variant :(.
// So we have to use other for now.
std::io::Error::new(std::io::ErrorKind::Other, "Is a directory")
std::io::Error::other("Is a directory")
}
fn not_a_directory() -> std::io::Error {
// Note: Rust returns `ErrorKind::NotADirectory` for this error but this is a nightly only variant :(.
// So we have to use `Other` for now.
std::io::Error::new(std::io::ErrorKind::Other, "Not a directory")
std::io::Error::other("Not a directory")
}
fn directory_not_empty() -> std::io::Error {
std::io::Error::new(std::io::ErrorKind::Other, "directory not empty")
std::io::Error::other("directory not empty")
}
fn create_dir_all(

View file

@ -1388,7 +1388,7 @@ pub fn soft_space_or_block_indent<Context>(content: &impl Format<Context>) -> Bl
pub fn group<Context>(content: &impl Format<Context>) -> Group<Context> {
Group {
content: Argument::new(content),
group_id: None,
id: None,
should_expand: false,
}
}
@ -1396,14 +1396,14 @@ pub fn group<Context>(content: &impl Format<Context>) -> Group<Context> {
#[derive(Copy, Clone)]
pub struct Group<'a, Context> {
content: Argument<'a, Context>,
group_id: Option<GroupId>,
id: Option<GroupId>,
should_expand: bool,
}
impl<Context> Group<'_, Context> {
#[must_use]
pub fn with_group_id(mut self, group_id: Option<GroupId>) -> Self {
self.group_id = group_id;
pub fn with_id(mut self, group_id: Option<GroupId>) -> Self {
self.id = group_id;
self
}
@ -1429,7 +1429,7 @@ impl<Context> Format<Context> for Group<'_, Context> {
};
f.write_element(FormatElement::Tag(StartGroup(
tag::Group::new().with_id(self.group_id).with_mode(mode),
tag::Group::new().with_id(self.id).with_mode(mode),
)));
Arguments::from(&self.content).fmt(f)?;
@ -1443,7 +1443,7 @@ impl<Context> Format<Context> for Group<'_, Context> {
impl<Context> std::fmt::Debug for Group<'_, Context> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Group")
.field("group_id", &self.group_id)
.field("id", &self.id)
.field("should_expand", &self.should_expand)
.field("content", &"{{content}}")
.finish()
@ -1642,7 +1642,7 @@ impl<Context> std::fmt::Debug for BestFitParenthesize<'_, Context> {
/// soft_line_break(),
/// if_group_breaks(&token(")"))
/// ])
/// .with_group_id(Some(parentheses_id))
/// .with_id(Some(parentheses_id))
/// .fmt(f)
/// });
///
@ -1991,7 +1991,7 @@ impl<Context> IfGroupBreaks<'_, Context> {
/// })),
/// token("]")
/// ],
/// ).with_group_id(Some(group_id))
/// ).with_id(Some(group_id))
/// ])
/// })])?;
///
@ -2046,7 +2046,7 @@ impl<Context> std::fmt::Debug for IfGroupBreaks<'_, Context> {
/// let id = f.group_id("head");
///
/// write!(f, [
/// group(&token("Head")).with_group_id(Some(id)),
/// group(&token("Head")).with_id(Some(id)),
/// if_group_breaks(&indent(&token("indented"))).with_group_id(Some(id)),
/// if_group_fits_on_line(&token("indented")).with_group_id(Some(id))
/// ])
@ -2071,7 +2071,7 @@ impl<Context> std::fmt::Debug for IfGroupBreaks<'_, Context> {
/// let group_id = f.group_id("header");
///
/// write!(f, [
/// group(&token("(aLongHeaderThatBreaksForSomeReason) =>")).with_group_id(Some(group_id)),
/// group(&token("(aLongHeaderThatBreaksForSomeReason) =>")).with_id(Some(group_id)),
/// indent_if_group_breaks(&format_args![hard_line_break(), token("a => b")], group_id)
/// ])
/// });
@ -2101,7 +2101,7 @@ impl<Context> std::fmt::Debug for IfGroupBreaks<'_, Context> {
/// let group_id = f.group_id("header");
///
/// write!(f, [
/// group(&token("(aLongHeaderThatBreaksForSomeReason) =>")).with_group_id(Some(group_id)),
/// group(&token("(aLongHeaderThatBreaksForSomeReason) =>")).with_id(Some(group_id)),
/// indent_if_group_breaks(&format_args![hard_line_break(), token("a => b")], group_id)
/// ])
/// });

View file

@ -2002,7 +2002,7 @@ two lines`,
token("The referenced group breaks."),
hard_line_break()
])
.with_group_id(Some(group_id)),
.with_id(Some(group_id)),
group(&format_args![
token("This group breaks because:"),
soft_line_break_or_space(),
@ -2027,7 +2027,7 @@ two lines`,
write!(
f,
[
group(&token("Group with id-2")).with_group_id(Some(id_2)),
group(&token("Group with id-2")).with_id(Some(id_2)),
hard_line_break()
]
)?;
@ -2035,7 +2035,7 @@ two lines`,
write!(
f,
[
group(&token("Group with id-1 does not fit on the line because it exceeds the line width of 80 characters by")).with_group_id(Some(id_1)),
group(&token("Group with id-1 does not fit on the line because it exceeds the line width of 80 characters by")).with_id(Some(id_1)),
hard_line_break()
]
)?;

View file

@ -940,7 +940,7 @@ mod tests {
#[test_case(Path::new("add_missing_cell_id.ipynb"), true; "add_missing_cell_id")]
fn test_cell_id(path: &Path, has_id: bool) -> Result<()> {
let source_notebook = Notebook::from_path(&notebook_path(path))?;
let source_kind = SourceKind::IpyNotebook(source_notebook);
let source_kind = SourceKind::ipy_notebook(source_notebook);
let (_, transformed) = test_contents(
&source_kind,
path,
@ -1231,7 +1231,7 @@ mod tests {
format!("async_comprehension_in_sync_comprehension_notebook_{python_version}");
let path = Path::new("resources/test/fixtures/syntax_errors/async_comprehension.ipynb");
let messages = test_contents_syntax_errors(
&SourceKind::IpyNotebook(Notebook::from_path(path)?),
&SourceKind::ipy_notebook(Notebook::from_path(path)?),
path,
&LinterSettings {
unresolved_target_version: python_version.into(),

View file

@ -198,7 +198,7 @@ fn is_explicit_concatenation(expr: &Expr) -> Option<bool> {
.iter()
.map(is_explicit_concatenation)
.collect::<Vec<_>>();
if values.iter().any(|v| *v == Some(true)) {
if values.contains(&Some(true)) {
Some(true)
} else if values.iter().all(|v| *v == Some(false)) {
Some(false)

View file

@ -174,7 +174,7 @@ struct StringLiteralDisplay<'a> {
/// The elts from the original AST node representing the display.
/// Each elt is the AST representation of a single string literal
/// element in the display
elts: Cow<'a, Vec<ast::Expr>>,
elts: Cow<'a, [ast::Expr]>,
/// The source-code range of the display as a whole
range: TextRange,
/// What kind of a display is it? A dict, set, list or tuple?

View file

@ -16,15 +16,47 @@ use colored::Colorize;
use crate::fs;
use crate::text_helpers::ShowNonprinting;
#[derive(Clone, Debug, PartialEq, is_macro::Is)]
#[derive(Clone, Debug, PartialEq)]
pub enum SourceKind {
/// The source contains Python source code.
Python(String),
/// The source contains a Jupyter notebook.
IpyNotebook(Notebook),
IpyNotebook(Box<Notebook>),
}
impl SourceKind {
pub fn ipy_notebook(notebook: Notebook) -> Self {
SourceKind::IpyNotebook(Box::new(notebook))
}
pub fn as_ipy_notebook(&self) -> Option<&Notebook> {
match self {
SourceKind::IpyNotebook(notebook) => Some(notebook),
SourceKind::Python(_) => None,
}
}
pub fn as_python(&self) -> Option<&str> {
match self {
SourceKind::Python(code) => Some(code),
SourceKind::IpyNotebook(_) => None,
}
}
pub fn expect_python(self) -> String {
match self {
SourceKind::Python(code) => code,
SourceKind::IpyNotebook(_) => panic!("expected python code"),
}
}
pub fn expect_ipy_notebook(self) -> Notebook {
match self {
SourceKind::IpyNotebook(notebook) => *notebook,
SourceKind::Python(_) => panic!("expected ipy notebook"),
}
}
#[must_use]
pub(crate) fn updated(&self, new_source: String, source_map: &SourceMap) -> Self {
match self {
@ -52,7 +84,7 @@ impl SourceKind {
let notebook = Notebook::from_path(path)?;
Ok(notebook
.is_python_notebook()
.then_some(Self::IpyNotebook(notebook)))
.then_some(Self::IpyNotebook(Box::new(notebook))))
} else {
let contents = std::fs::read_to_string(path)?;
Ok(Some(Self::Python(contents)))
@ -69,7 +101,7 @@ impl SourceKind {
let notebook = Notebook::from_source_code(&source_code)?;
Ok(notebook
.is_python_notebook()
.then_some(Self::IpyNotebook(notebook)))
.then_some(Self::IpyNotebook(Box::new(notebook))))
} else {
Ok(Some(Self::Python(source_code)))
}

View file

@ -60,7 +60,7 @@ pub(crate) fn assert_notebook_path(
) -> Result<TestedNotebook, NotebookError> {
let source_notebook = Notebook::from_path(path.as_ref())?;
let source_kind = SourceKind::IpyNotebook(source_notebook);
let source_kind = SourceKind::ipy_notebook(source_notebook);
let (messages, transformed) = test_contents(&source_kind, path.as_ref(), settings);
let expected_notebook = Notebook::from_path(expected.as_ref())?;
let linted_notebook = transformed.into_owned().expect_ipy_notebook();

View file

@ -255,7 +255,7 @@ impl<'ast> Format<PyFormatContext<'ast>> for FormatOptionalParentheses<'_, 'ast>
soft_line_break(),
if_group_breaks(&token(")"))
])
.with_group_id(Some(parens_id))]
.with_id(Some(parens_id))]
)
}
}

View file

@ -413,7 +413,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
soft_block_indent(&format_args![flat, inline_comments]),
token(")"),
])
.with_group_id(Some(group_id))
.with_id(Some(group_id))
.should_expand(true)
.fmt(f)
});
@ -433,7 +433,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
token(")"),
inline_comments,
])
.with_group_id(Some(group_id))
.with_id(Some(group_id))
.should_expand(true)
.fmt(f)
});
@ -501,7 +501,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
soft_block_indent(&format_args![f_string_flat, inline_comments]),
token(")"),
])
.with_group_id(Some(group_id))
.with_id(Some(group_id))
.should_expand(true)
.fmt(f)
});
@ -817,7 +817,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
space(),
token("("),
group(&soft_block_indent(&format_expanded))
.with_group_id(Some(group_id))
.with_id(Some(group_id))
.should_expand(true),
token(")"),
inline_comments
@ -875,7 +875,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
space(),
token("("),
group(&soft_block_indent(&format_expanded))
.with_group_id(Some(group_id))
.with_id(Some(group_id))
.should_expand(true),
token(")"),
inline_comments

View file

@ -252,9 +252,7 @@ pub fn is_immutable_annotation(
.is_some_and(|qualified_name| {
is_immutable_non_generic_type(qualified_name.segments())
|| is_immutable_generic_type(qualified_name.segments())
|| extend_immutable_calls
.iter()
.any(|target| qualified_name == *target)
|| extend_immutable_calls.contains(&qualified_name)
})
}
Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => semantic
@ -308,9 +306,7 @@ pub fn is_immutable_func(
.resolve_qualified_name(map_subscript(func))
.is_some_and(|qualified_name| {
is_immutable_return_type(qualified_name.segments())
|| extend_immutable_calls
.iter()
.any(|target| qualified_name == *target)
|| extend_immutable_calls.contains(&qualified_name)
})
}

View file

@ -559,7 +559,7 @@ impl DocumentQuery {
ruff_linter::source_kind::SourceKind::Python(document.contents().to_string())
}
Self::Notebook { notebook, .. } => {
ruff_linter::source_kind::SourceKind::IpyNotebook(notebook.make_ruff_notebook())
ruff_linter::source_kind::SourceKind::ipy_notebook(notebook.make_ruff_notebook())
}
}
}

View file

@ -462,7 +462,7 @@ impl ConfigurationTransformer for EditorConfigurationTransformer<'_> {
tracing::debug!(
"Combining settings from editor-specified inline configuration"
);
match Configuration::from_options(options, None, project_root) {
match Configuration::from_options(*options, None, project_root) {
Ok(configuration) => editor_configuration.combine(configuration),
Err(err) => {
tracing::error!(
@ -516,10 +516,10 @@ mod tests {
#[test]
fn inline_settings() {
let editor_settings = ResolvedEditorSettings {
configuration: Some(ResolvedConfiguration::Inline(Options {
configuration: Some(ResolvedConfiguration::Inline(Box::new(Options {
line_length: Some(LineLength::try_from(120).unwrap()),
..Default::default()
})),
}))),
..Default::default()
};
@ -534,10 +534,10 @@ mod tests {
#[test]
fn inline_and_specific_settings_resolution_order() {
let editor_settings = ResolvedEditorSettings {
configuration: Some(ResolvedConfiguration::Inline(Options {
configuration: Some(ResolvedConfiguration::Inline(Box::new(Options {
line_length: Some(LineLength::try_from(120).unwrap()),
..Default::default()
})),
}))),
line_length: Some(LineLength::try_from(100).unwrap()),
..Default::default()
};

View file

@ -52,7 +52,7 @@ pub(crate) struct ResolvedEditorSettings {
#[cfg_attr(test, derive(PartialEq, Eq))]
pub(crate) enum ResolvedConfiguration {
FilePath(PathBuf),
Inline(Options),
Inline(Box<Options>),
}
impl TryFrom<&ClientConfiguration> for ResolvedConfiguration {
@ -68,7 +68,7 @@ impl TryFrom<&ClientConfiguration> for ResolvedConfiguration {
if options.extend.is_some() {
Err(ResolvedConfigurationError::ExtendNotSupported)
} else {
Ok(ResolvedConfiguration::Inline(options))
Ok(ResolvedConfiguration::Inline(Box::new(options)))
}
}
}
@ -991,7 +991,7 @@ mod tests {
fix_violation_enable: true,
show_syntax_errors: true,
editor_settings: ResolvedEditorSettings {
configuration: Some(ResolvedConfiguration::Inline(Options {
configuration: Some(ResolvedConfiguration::Inline(Box::new(Options {
line_length: Some(LineLength::try_from(100).unwrap()),
lint: Some(LintOptions {
common: LintCommonOptions {
@ -1005,7 +1005,7 @@ mod tests {
..Default::default()
}),
..Default::default()
})),
}))),
extend_select: Some(vec![RuleSelector::from_str("RUF001").unwrap()]),
..Default::default()
}

View file

@ -594,7 +594,7 @@ impl PythonHomePath {
system
.is_directory(&canonicalized)
.then_some(Self(canonicalized))
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "not a directory"))
.ok_or_else(|| io::Error::other("not a directory"))
}
}

View file

@ -5034,7 +5034,6 @@ impl<'db> Type<'db> {
/// Note that this does not specialize generic classes, functions, or type aliases! That is a
/// different operation that is performed explicitly (via a subscript operation), or implicitly
/// via a call to the generic object.
#[must_use]
#[salsa::tracked]
pub fn apply_specialization(
self,