bump MSRV to 1.83 (#16294)

According to our new MSRV policy (see
https://github.com/astral-sh/ruff/issues/16370 ), bump our MSRV to 1.83
(N - 2), and autofix some new clippy lints.
This commit is contained in:
Carl Meyer 2025-02-26 06:12:43 -08:00 committed by GitHub
parent bf2c9a41cd
commit dd6f6233bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 85 additions and 93 deletions

View file

@ -4,7 +4,7 @@ resolver = "2"
[workspace.package]
edition = "2021"
rust-version = "1.80"
rust-version = "1.83"
homepage = "https://docs.astral.sh/ruff"
documentation = "https://docs.astral.sh/ruff"
repository = "https://github.com/astral-sh/ruff"

View file

@ -77,10 +77,10 @@ impl ProjectMetadata {
// If the `options` don't specify a python version but the `project.requires-python` field is set,
// use that as a lower bound instead.
if let Some(project) = project {
if !options
if options
.environment
.as_ref()
.is_some_and(|env| env.python_version.is_some())
.is_none_or(|env| env.python_version.is_none())
{
if let Some(requires_python) = project.resolve_requires_python_lower_bound()? {
let mut environment = options.environment.unwrap_or_default();

View file

@ -283,12 +283,12 @@ impl Matcher {
let position = unmatched.iter().position(|diagnostic| {
!error.rule.is_some_and(|rule| {
!(diagnostic.id().is_lint_named(rule) || diagnostic.id().matches(rule))
}) && !error
}) && error
.column
.is_some_and(|col| col != self.column(*diagnostic))
&& !error
.is_none_or(|col| col == self.column(*diagnostic))
&& error
.message_contains
.is_some_and(|needle| !diagnostic.message().contains(needle))
.is_none_or(|needle| diagnostic.message().contains(needle))
});
if let Some(position) = position {
unmatched.swap_remove(position);

View file

@ -470,13 +470,13 @@ impl Printed {
for marker in self.sourcemap {
// Take the closest start marker, but skip over start_markers that have the same start.
if marker.source <= source_range.start()
&& !start_marker.is_some_and(|existing| existing.source >= marker.source)
&& start_marker.is_none_or(|existing| existing.source < marker.source)
{
start_marker = Some(marker);
}
if marker.source >= source_range.end()
&& !end_marker.is_some_and(|existing| existing.source <= marker.source)
&& end_marker.is_none_or(|existing| existing.source > marker.source)
{
end_marker = Some(marker);
}

View file

@ -177,10 +177,10 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
}
// If the bindings are in different forks, abort.
if shadowed.source.map_or(true, |left| {
if shadowed.source.is_none_or(|left| {
binding
.source
.map_or(true, |right| !checker.semantic.same_branch(left, right))
.is_none_or(|right| !checker.semantic.same_branch(left, right))
}) {
continue;
}
@ -269,10 +269,10 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
}
// If the bindings are in different forks, abort.
if shadowed.source.map_or(true, |left| {
if shadowed.source.is_none_or(|left| {
binding
.source
.map_or(true, |right| !checker.semantic.same_branch(left, right))
.is_none_or(|right| !checker.semantic.same_branch(left, right))
}) {
continue;
}

View file

@ -453,7 +453,7 @@ fn is_docstring_section(
}
// Determine whether the previous line looks like the end of a paragraph.
let previous_line_looks_like_end_of_paragraph = previous_line.map_or(true, |previous_line| {
let previous_line_looks_like_end_of_paragraph = previous_line.is_none_or(|previous_line| {
let previous_line = previous_line.trim();
let previous_line_ends_with_punctuation = [',', ';', '.', '-', '\\', '/', ']', '}', ')']
.into_iter()

View file

@ -20,7 +20,7 @@ pub(super) fn matches_password_name(string: &str) -> bool {
}
pub(super) fn is_untyped_exception(type_: Option<&Expr>, semantic: &SemanticModel) -> bool {
type_.map_or(true, |type_| {
type_.is_none_or(|type_| {
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_ {
elts.iter().any(|type_| {
semantic

View file

@ -62,10 +62,10 @@ pub(crate) fn hardcoded_sql_expression(checker: &Checker, expr: &Expr) {
op: Operator::Add, ..
}) => {
// Only evaluate the full BinOp, not the nested components.
if !checker
if checker
.semantic()
.current_expression_parent()
.map_or(true, |parent| !parent.is_bin_op_expr())
.is_some_and(ruff_python_ast::Expr::is_bin_op_expr)
{
return;
}

View file

@ -199,7 +199,7 @@ fn detect_insecure_crypt_calls(checker: &Checker, call: &ast::ExprCall) {
fn is_used_for_security(arguments: &Arguments) -> bool {
arguments
.find_keyword("usedforsecurity")
.map_or(true, |keyword| !is_const_false(&keyword.value))
.is_none_or(|keyword| !is_const_false(&keyword.value))
}
#[derive(Debug, Copy, Clone)]

View file

@ -53,10 +53,10 @@ pub(crate) fn tarfile_unsafe_members(checker: &Checker, call: &ast::ExprCall) {
return;
}
if !call
if call
.func
.as_attribute_expr()
.is_some_and(|attr| attr.attr.as_str() == "extractall")
.is_none_or(|attr| attr.attr.as_str() != "extractall")
{
return;
}

View file

@ -66,17 +66,17 @@ pub(crate) fn implicit_namespace_package(
// Ignore non-`.py` files, which don't require an `__init__.py`.
&& PySourceType::try_from_path(path).is_some_and(PySourceType::is_py_file)
// Ignore any files that are direct children of the project root.
&& !path
&& path
.parent()
.is_some_and( |parent| parent == project_root)
.is_none_or( |parent| parent != project_root)
// Ignore any files that are direct children of a source directory (e.g., `src/manage.py`).
&& !path
.parent()
.is_some_and( |parent| src.iter().any(|src| src == parent))
// Ignore files that contain a shebang.
&& !comment_ranges
&& comment_ranges
.first().filter(|range| range.start() == TextSize::from(0))
.is_some_and(|range| ShebangDirective::try_extract(locator.slice(*range)).is_some())
.is_none_or(|range| ShebangDirective::try_extract(locator.slice(*range)).is_none())
// Ignore PEP 723 scripts.
&& ScriptTag::parse(locator.contents().as_bytes()).is_none()
{

View file

@ -109,8 +109,7 @@ pub(crate) fn print_call(checker: &Checker, call: &ast::ExprCall) {
// or `"sys.stderr"`), don't trigger T201.
if let Some(keyword) = call.arguments.find_keyword("file") {
if !keyword.value.is_none_literal_expr() {
if semantic.resolve_qualified_name(&keyword.value).map_or(
true,
if semantic.resolve_qualified_name(&keyword.value).is_none_or(
|qualified_name| {
!matches!(qualified_name.segments(), ["sys", "stdout" | "stderr"])
},

View file

@ -294,7 +294,7 @@ fn check_positional_args_for_overloaded_method(
predicate: impl FnOnce(&Expr) -> bool,
semantic: &SemanticModel,
) -> bool {
parameter.annotation().map_or(true, |annotation| {
parameter.annotation().is_none_or(|annotation| {
predicate(annotation) || is_object_or_unused(annotation, semantic)
})
}

View file

@ -63,7 +63,7 @@ pub(crate) fn fail_call(checker: &Checker, call: &ast::ExprCall) {
.arguments
.find_argument_value("reason", 0)
.or_else(|| call.arguments.find_argument_value("msg", 0))
.map_or(true, is_empty_or_null_string)
.is_none_or(is_empty_or_null_string)
{
checker.report_diagnostic(Diagnostic::new(PytestFailWithoutMessage, call.func.range()));
}

View file

@ -188,7 +188,7 @@ pub(crate) fn raises_call(checker: &Checker, call: &ast::ExprCall) {
if call
.arguments
.find_keyword("match")
.map_or(true, |k| is_empty_or_null_string(&k.value))
.is_none_or(|k| is_empty_or_null_string(&k.value))
{
exception_needs_match(checker, exception);
}

View file

@ -187,7 +187,7 @@ pub(crate) fn warns_call(checker: &Checker, call: &ast::ExprCall) {
if call
.arguments
.find_keyword("match")
.map_or(true, |k| is_empty_or_null_string(&k.value))
.is_none_or(|k| is_empty_or_null_string(&k.value))
{
warning_needs_match(checker, warning);
}

View file

@ -817,7 +817,7 @@ pub(crate) fn function(checker: &Checker, function_def: &ast::StmtFunctionDef) {
} else {
if checker.enabled(Rule::UnnecessaryReturnNone) {
// Skip functions that have a return annotation that is not `None`.
if returns.as_deref().map_or(true, Expr::is_none_literal_expr) {
if returns.as_deref().is_none_or(Expr::is_none_literal_expr) {
unnecessary_return_none(checker, decorator_list, &stack);
}
}

View file

@ -177,7 +177,7 @@ pub(crate) fn multiple_with_statements(
with_stmt,
) {
Ok(edit) => {
if edit.content().map_or(true, |content| {
if edit.content().is_none_or(|content| {
fits(
content,
with_stmt.into(),

View file

@ -120,7 +120,7 @@ pub(crate) fn nested_if_statements(
diagnostic.try_set_optional_fix(|| {
match collapse_nested_if(checker.locator(), checker.stylist(), nested_if) {
Ok(edit) => {
if edit.content().map_or(true, |content| {
if edit.content().is_none_or(|content| {
fits(
content,
(&nested_if).into(),

View file

@ -53,10 +53,9 @@ pub(crate) fn normalize_imports<'a>(
} => {
// Whether to track each member of the import as a separate entry.
let isolate_aliases = settings.force_single_line
&& module.map_or(true, |module| {
!settings.single_line_exclusions.contains(module)
})
&& !names.first().is_some_and(|alias| alias.name == "*");
&& module
.is_none_or(|module| !settings.single_line_exclusions.contains(module))
&& names.first().is_none_or(|alias| alias.name != "*");
// Insert comments on the statement itself.
if isolate_aliases {

View file

@ -102,7 +102,7 @@ impl IgnoreNames {
) -> Result<Self, SettingsError> {
// If the user is not customizing the set of ignored names, use the default matcher,
// which is hard-coded to avoid expensive regex matching.
if ignore_names.is_none() && extend_ignore_names.as_ref().map_or(true, Vec::is_empty) {
if ignore_names.is_none() && extend_ignore_names.as_ref().is_none_or(Vec::is_empty) {
return Ok(IgnoreNames::Default);
}

View file

@ -93,7 +93,7 @@ pub(crate) fn manual_list_copy(checker: &Checker, for_stmt: &ast::StmtFor) {
}
// Only flag direct list copies (e.g., `for x in y: filtered.append(x)`).
if !arg.as_name_expr().is_some_and(|arg| arg.id == *id) {
if arg.as_name_expr().is_none_or(|arg| arg.id != *id) {
return;
}

View file

@ -245,9 +245,9 @@ pub(crate) fn missing_whitespace_around_operator(
let has_leading_trivia =
prev_token.end() < token.start() || is_non_logical_token(prev_token.kind());
let has_trailing_trivia = tokens.peek().map_or(true, |next| {
token.end() < next.start() || is_non_logical_token(next.kind())
});
let has_trailing_trivia = tokens
.peek()
.is_none_or(|next| token.end() < next.start() || is_non_logical_token(next.kind()));
match (has_leading_trivia, has_trailing_trivia) {
// Operator with trailing but no leading space, enforce consistent spacing.

View file

@ -794,7 +794,7 @@ impl<'a> GeneratorOrIteratorArguments<'a> {
match self {
Self::Unparameterized => true,
Self::Single(_) => true,
Self::Several(elements) => elements.get(2).map_or(true, Expr::is_none_literal_expr),
Self::Several(elements) => elements.get(2).is_none_or(Expr::is_none_literal_expr),
}
}
}
@ -947,7 +947,7 @@ pub(crate) fn check_docstring(
match function_def.returns.as_deref() {
Some(returns)
if !generator_annotation_arguments(returns, semantic).is_some_and(
|arguments| arguments.first().map_or(true, Expr::is_none_literal_expr),
|arguments| arguments.first().is_none_or(Expr::is_none_literal_expr),
) =>
{
diagnostics

View file

@ -71,7 +71,7 @@ pub(crate) fn no_signature(checker: &Checker, docstring: &Docstring) {
let preceded_by_word_boundary = first_line[..index]
.chars()
.next_back()
.map_or(true, |c| matches!(c, ' ' | '\t' | ';' | ','));
.is_none_or(|c| matches!(c, ' ' | '\t' | ';' | ','));
if !preceded_by_word_boundary {
return false;
}

View file

@ -1871,7 +1871,7 @@ fn args_section(context: &SectionContext) -> FxHashSet<String> {
// Reformat each section.
let mut args_sections: Vec<String> = vec![];
for line in args_content.trim().lines() {
if line.chars().next().map_or(true, char::is_whitespace) {
if line.chars().next().is_none_or(char::is_whitespace) {
// This is a continuation of the documentation for the previous parameter,
// because it starts with whitespace.
if let Some(last) = args_sections.last_mut() {

View file

@ -65,7 +65,7 @@ pub(crate) fn potential_index_error(checker: &Checker, value: &Expr, slice: &Exp
// Emit a diagnostic if the index is out of bounds. If the index can't be represented as an
// `i64`, but the length _can_, then the index is definitely out of bounds.
if index.map_or(true, |index| index >= length || index < -length) {
if index.is_none_or(|index| index >= length || index < -length) {
checker.report_diagnostic(Diagnostic::new(PotentialIndexError, slice.range()));
}
}

View file

@ -140,9 +140,9 @@ pub(crate) fn type_name_incorrect_variance(checker: &Checker, value: &Expr) {
/// Returns `true` if the parameter name does not match its type variance.
fn mismatch(param_name: &str, covariant: Option<&Expr>, contravariant: Option<&Expr>) -> bool {
if param_name.ends_with("_co") {
covariant.map_or(true, |covariant| !is_const_true(covariant))
covariant.is_none_or(|covariant| !is_const_true(covariant))
} else if param_name.ends_with("_contra") {
contravariant.map_or(true, |contravariant| !is_const_true(contravariant))
contravariant.is_none_or(|contravariant| !is_const_true(contravariant))
} else {
covariant.is_some_and(is_const_true) || contravariant.is_some_and(is_const_true)
}

View file

@ -154,7 +154,7 @@ fn enumerate_items<'a>(
// If the `enumerate` call has a non-zero `start`, don't omit.
if !arguments
.find_argument_value("start", 1)
.map_or(true, |expr| {
.is_none_or(|expr| {
matches!(
expr,
Expr::NumberLiteral(ast::ExprNumberLiteral {

View file

@ -50,7 +50,7 @@ pub(crate) fn useless_return(
returns: Option<&Expr>,
) {
// Skip functions that have a return annotation that is not `None`.
if !returns.map_or(true, Expr::is_none_literal_expr) {
if !returns.is_none_or(Expr::is_none_literal_expr) {
return;
}
@ -82,7 +82,7 @@ pub(crate) fn useless_return(
// Verify that the return statement is either bare or returns `None`.
if !value
.as_ref()
.map_or(true, |expr| expr.is_none_literal_expr())
.is_none_or(|expr| expr.is_none_literal_expr())
{
return;
};

View file

@ -106,12 +106,12 @@ pub(crate) fn int_on_sliced_str(checker: &Checker, call: &ExprCall) {
if expr_slice.upper.is_some() || expr_slice.step.is_some() {
return;
}
if !expr_slice
if expr_slice
.lower
.as_ref()
.and_then(|expr| expr.as_number_literal_expr())
.and_then(|expr| expr.value.as_int())
.is_some_and(|expr| expr.as_u8() == Some(2))
.is_none_or(|expr| expr.as_u8() != Some(2))
{
return;
}

View file

@ -119,7 +119,7 @@ fn peel_lists(expr: &Expr) -> &Expr {
return expr;
}
if !func.as_name_expr().is_some_and(|name| name.id == "list") {
if func.as_name_expr().is_none_or(|name| name.id != "list") {
return expr;
}
@ -175,11 +175,11 @@ fn extract_name_from_sliced_reversed(expr: &Expr) -> Option<&ExprName> {
else {
return None;
};
if !operand
if operand
.as_number_literal_expr()
.and_then(|num| num.value.as_int())
.and_then(Int::as_u8)
.is_some_and(|value| value == 1)
.is_none_or(|value| value != 1)
{
return None;
};

View file

@ -179,7 +179,7 @@ pub(crate) fn unnecessary_enumerate(checker: &Checker, stmt_for: &ast::StmtFor)
// If the `start` argument is set to something other than the `range` default,
// there's no clear fix.
let start = arguments.find_argument_value("start", 1);
if start.map_or(true, |start| {
if start.is_none_or(|start| {
matches!(
start,
Expr::NumberLiteral(ast::ExprNumberLiteral {

View file

@ -224,7 +224,7 @@ fn should_be_fstring(
semantic.scope_id,
TypingOnlyBindingsStatus::Disallowed,
)
.map_or(true, |id| semantic.binding(id).kind.is_builtin())
.is_none_or(|id| semantic.binding(id).kind.is_builtin())
{
return false;
}

View file

@ -513,7 +513,7 @@ impl<'a> MultilineStringSequenceValue<'a> {
// we'll end up with two commas after the final item, which would be invalid syntax)
let needs_trailing_comma = self.ends_with_trailing_comma
&& first_non_trivia_token(TextSize::new(0), &postlude)
.map_or(true, |tok| tok.kind() != SimpleTokenKind::Comma);
.is_none_or(|tok| tok.kind() != SimpleTokenKind::Comma);
self.items
.sort_by(|a, b| sorting_style.compare(a.value, b.value));
@ -979,7 +979,7 @@ fn multiline_string_sequence_postlude<'a>(
if postlude.len() <= 2 {
let mut reversed_postlude_chars = postlude.chars().rev();
if let Some(closing_paren @ (')' | '}' | ']')) = reversed_postlude_chars.next() {
if reversed_postlude_chars.next().map_or(true, |c| c == ',') {
if reversed_postlude_chars.next().is_none_or(|c| c == ',') {
return Cow::Owned(format!(",{newline}{leading_indent}{closing_paren}"));
}
}

View file

@ -59,7 +59,7 @@ where
fn can_skip(&mut self, node_end: TextSize) -> bool {
self.comments
.peek()
.map_or(true, |next| next.range.start() >= node_end)
.is_none_or(|next| next.range.start() >= node_end)
}
}

View file

@ -178,25 +178,20 @@ impl<'a> TypingTarget<'a> {
TypingTarget::Union(slice) => slice.is_some_and(|slice| {
resolve_slice_value(slice).any(|element| {
TypingTarget::try_from_expr(element, checker, version)
.map_or(true, |new_target| {
new_target.contains_none(checker, version)
})
.is_none_or(|new_target| new_target.contains_none(checker, version))
})
}),
TypingTarget::PEP604Union(left, right) => [left, right].iter().any(|element| {
TypingTarget::try_from_expr(element, checker, version).map_or(true, |new_target| {
new_target.contains_none(checker, version)
})
TypingTarget::try_from_expr(element, checker, version)
.is_none_or(|new_target| new_target.contains_none(checker, version))
}),
TypingTarget::Annotated(expr) => expr.is_some_and(|expr| {
TypingTarget::try_from_expr(expr, checker, version).map_or(true, |new_target| {
new_target.contains_none(checker, version)
})
TypingTarget::try_from_expr(expr, checker, version)
.is_none_or(|new_target| new_target.contains_none(checker, version))
}),
TypingTarget::ForwardReference(expr) => {
TypingTarget::try_from_expr(expr, checker, version).map_or(true, |new_target| {
new_target.contains_none(checker, version)
})
TypingTarget::try_from_expr(expr, checker, version)
.is_none_or(|new_target| new_target.contains_none(checker, version))
}
}
}
@ -215,22 +210,22 @@ impl<'a> TypingTarget<'a> {
TypingTarget::Union(slice) => slice.is_some_and(|slice| {
resolve_slice_value(slice).any(|element| {
TypingTarget::try_from_expr(element, checker, version)
.map_or(true, |new_target| new_target.contains_any(checker, version))
.is_none_or(|new_target| new_target.contains_any(checker, version))
})
}),
TypingTarget::PEP604Union(left, right) => [left, right].iter().any(|element| {
TypingTarget::try_from_expr(element, checker, version)
.map_or(true, |new_target| new_target.contains_any(checker, version))
.is_none_or(|new_target| new_target.contains_any(checker, version))
}),
TypingTarget::Annotated(expr) | TypingTarget::Optional(expr) => {
expr.is_some_and(|expr| {
TypingTarget::try_from_expr(expr, checker, version)
.map_or(true, |new_target| new_target.contains_any(checker, version))
.is_none_or(|new_target| new_target.contains_any(checker, version))
})
}
TypingTarget::ForwardReference(expr) => {
TypingTarget::try_from_expr(expr, checker, version)
.map_or(true, |new_target| new_target.contains_any(checker, version))
.is_none_or(|new_target| new_target.contains_any(checker, version))
}
}
}

View file

@ -66,7 +66,7 @@ impl Cell {
.metadata
.vscode
.as_ref()
.map_or(true, |vscode| vscode.language_id == "python") =>
.is_none_or(|vscode| vscode.language_id == "python") =>
{
&cell.source
}

View file

@ -2800,7 +2800,7 @@ impl Pattern {
pub fn is_wildcard(&self) -> bool {
match self {
Pattern::MatchAs(PatternMatchAs { pattern, .. }) => {
pattern.as_deref().map_or(true, Pattern::is_wildcard)
pattern.as_deref().is_none_or(Pattern::is_wildcard)
}
Pattern::MatchOr(PatternMatchOr { patterns, .. }) => {
patterns.iter().all(Pattern::is_wildcard)

View file

@ -67,7 +67,7 @@ impl ScriptTag {
let mut lines = contents.lines();
// Ensure that the first line is exactly `# /// script`.
if !lines.next().is_some_and(|line| line == "# /// script") {
if lines.next().is_none_or(|line| line != "# /// script") {
return None;
}

View file

@ -65,7 +65,7 @@ impl<'a, 'builder> CommentsVisitor<'a, 'builder> {
fn can_skip(&mut self, node_end: TextSize) -> bool {
self.comment_ranges
.peek()
.map_or(true, |next_comment| next_comment.start() >= node_end)
.is_none_or(|next_comment| next_comment.start() >= node_end)
}
}

View file

@ -60,9 +60,9 @@ impl FormatNodeRule<ExprSlice> for FormatExprSlice {
// Handle spacing around the colon(s)
// https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#slices
let lower_simple = lower.as_ref().map_or(true, |expr| is_simple_expr(expr));
let upper_simple = upper.as_ref().map_or(true, |expr| is_simple_expr(expr));
let step_simple = step.as_ref().map_or(true, |expr| is_simple_expr(expr));
let lower_simple = lower.as_ref().is_none_or(|expr| is_simple_expr(expr));
let upper_simple = upper.as_ref().is_none_or(|expr| is_simple_expr(expr));
let step_simple = step.as_ref().is_none_or(|expr| is_simple_expr(expr));
let all_simple = lower_simple && upper_simple && step_simple;
// lower

View file

@ -49,8 +49,7 @@ impl FormatNodeRule<ParameterWithDefault> for FormatParameterWithDefault {
debug_assert!(equals.is_some_and(|token| token.kind == SimpleTokenKind::Equals));
let lparens = tokenizer.next();
debug_assert!(lparens
.as_ref()
.map_or(true, |token| token.kind == SimpleTokenKind::LParen));
.as_ref().is_none_or(|token| token.kind == SimpleTokenKind::LParen));
lparens.is_none()
});
let needs_line_break = needs_line_break_trailing || needs_line_break_leading;

View file

@ -1256,7 +1256,7 @@ impl<'src> Lexer<'src> {
// `IpyEscapeKind::Magic` and `IpyEscapeKind::Help` because of the initial `%` and `??`
// tokens.
if question_count > 2
|| value.chars().last().map_or(true, is_python_whitespace)
|| value.chars().last().is_none_or(is_python_whitespace)
|| !matches!(self.cursor.first(), '\n' | '\r' | EOF_CHAR)
{
// Not a help end escape command, so continue with the lexing.

View file

@ -55,7 +55,7 @@ impl ImplicitImports {
// Always prefer stub files over non-stub files.
if submodules
.get(name)
.map_or(true, |implicit_import| !implicit_import.is_stub_file)
.is_none_or(|implicit_import| !implicit_import.is_stub_file)
{
submodules.insert(
name.to_string(),

View file

@ -344,14 +344,14 @@ impl<'a> SemanticModel<'a> {
pub fn is_available_in_scope(&self, member: &str, scope_id: ScopeId) -> bool {
self.lookup_symbol_in_scope(member, scope_id, false)
.map(|binding_id| &self.bindings[binding_id])
.map_or(true, |binding| binding.kind.is_builtin())
.is_none_or(|binding| binding.kind.is_builtin())
}
/// Resolve a `del` reference to `symbol` at `range`.
pub fn resolve_del(&mut self, symbol: &str, range: TextRange) {
let is_unbound = self.scopes[self.scope_id]
.get(symbol)
.map_or(true, |binding_id| {
.is_none_or(|binding_id| {
// Treat the deletion of a name as a reference to that name.
self.add_local_reference(binding_id, ExprContext::Del, range);
self.bindings[binding_id].is_unbound()
@ -1508,7 +1508,7 @@ impl<'a> SemanticModel<'a> {
if self
.global_scope()
.get(name)
.map_or(true, |binding_id| self.bindings[binding_id].is_unbound())
.is_none_or(|binding_id| self.bindings[binding_id].is_unbound())
{
let id = self.bindings.push(Binding {
kind: BindingKind::Assignment,

View file

@ -588,7 +588,7 @@ impl ParallelVisitor for PythonFilesVisitor<'_, '_> {
match result {
Ok(entry) => {
// Ignore directories
let resolved = if entry.file_type().map_or(true, |ft| ft.is_dir()) {
let resolved = if entry.file_type().is_none_or(|ft| ft.is_dir()) {
None
} else if entry.depth() == 0 {
// Accept all files that are passed-in directly.