Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4370,11 +4370,10 @@ declare_clippy_lint! {

declare_clippy_lint! {
/// ### What it does
///
/// Detect functions that end with `Option::and_then` or `Result::and_then`, and suggest using a question mark (`?`) instead.
/// Detect functions that end with `Option::and_then` or `Result::and_then`, and suggest using
/// the `?` operator instead.
///
/// ### Why is this bad?
///
/// The `and_then` method is used to chain a computation that returns an `Option` or a `Result`.
/// This can be replaced with the `?` operator, which is more concise and idiomatic.
///
Expand Down
11 changes: 9 additions & 2 deletions clippy_lints/src/methods/return_and_then.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,20 @@ pub(super) fn check<'tcx>(
None => &body_snip,
};

let msg = "use the question mark operator instead of an `and_then` call";
let sugg = format!(
"let {} = {}?;\n{}",
arg_snip,
recv_snip,
reindent_multiline(inner, false, indent_of(cx, expr.span))
);

span_lint_and_sugg(cx, RETURN_AND_THEN, expr.span, msg, "try", sugg, applicability);
span_lint_and_sugg(
cx,
RETURN_AND_THEN,
expr.span,
"use the `?` operator instead of an `and_then` call",
"try",
sugg,
applicability,
);
}
8 changes: 4 additions & 4 deletions clippy_lints/src/question_mark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ use rustc_span::symbol::Symbol;

declare_clippy_lint! {
/// ### What it does
/// Checks for expressions that could be replaced by the question mark operator.
/// Checks for expressions that could be replaced by the `?` operator.
///
/// ### Why is this bad?
/// Question mark usage is more idiomatic.
/// Using the `?` operator is shorter and more idiomatic.
///
/// ### Example
/// ```ignore
Expand All @@ -47,7 +47,7 @@ declare_clippy_lint! {
#[clippy::version = "pre 1.29.0"]
pub QUESTION_MARK,
style,
"checks for expressions that could be replaced by the question mark operator"
"checks for expressions that could be replaced by the `?` operator"
}

pub struct QuestionMark {
Expand Down Expand Up @@ -280,7 +280,7 @@ fn expr_return_none_or_err(
/// }
/// ```
///
/// If it matches, it will suggest to use the question mark operator instead
/// If it matches, it will suggest to use the `?` operator instead
fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
&& !is_else_clause(cx.tcx, expr)
Expand Down
18 changes: 6 additions & 12 deletions clippy_lints/src/question_mark_used.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use rustc_session::declare_lint_pass;

declare_clippy_lint! {
/// ### What it does
/// Checks for expressions that use the question mark operator and rejects them.
/// Checks for expressions that use the `?` operator and rejects them.
///
/// ### Why restrict this?
/// Sometimes code wants to avoid the question mark operator because for instance a local
/// Sometimes code wants to avoid the `?` operator because for instance a local
/// block requires a macro to re-throw errors to attach additional information to the
/// error.
///
Expand All @@ -27,7 +27,7 @@ declare_clippy_lint! {
#[clippy::version = "1.69.0"]
pub QUESTION_MARK_USED,
restriction,
"complains if the question mark operator is used"
"checks if the `?` operator is used"
}

declare_lint_pass!(QuestionMarkUsed => [QUESTION_MARK_USED]);
Expand All @@ -40,15 +40,9 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
}

#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(
cx,
QUESTION_MARK_USED,
expr.span,
"question mark operator was used",
|diag| {
diag.help("consider using a custom macro or match expression");
},
);
span_lint_and_then(cx, QUESTION_MARK_USED, expr.span, "the `?` operator was used", |diag| {
diag.help("consider using a custom macro or match expression");
});
}
}
}
5 changes: 2 additions & 3 deletions clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3101,7 +3101,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
sm.span_take_while(span, |&ch| ch == ' ' || ch == ';')
}

/// Returns whether the given let pattern and else body can be turned into a question mark
/// Returns whether the given let pattern and else body can be turned into the `?` operator
///
/// For this example:
/// ```ignore
Expand All @@ -3124,8 +3124,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
/// ```
///
/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because
/// the question mark operator is applicable here. Callers have to check whether we are in a
/// constant or not.
/// the `?` operator is applicable here. Callers have to check whether we are in a constant or not.
pub fn pat_and_expr_can_be_question_mark<'a, 'hir>(
cx: &LateContext<'_>,
pat: &'a Pat<'hir>,
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/question_mark_used.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: question mark operator was used
error: the `?` operator was used
--> tests/ui/question_mark_used.rs:11:5
|
LL | other_function()?;
Expand Down
14 changes: 7 additions & 7 deletions tests/ui/return_and_then.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: use the question mark operator instead of an `and_then` call
error: use the `?` operator instead of an `and_then` call
--> tests/ui/return_and_then.rs:5:9
|
LL | / opt.and_then(|n| {
Expand All @@ -20,7 +20,7 @@ LL + ret += n;
LL + if n > 1 { Some(ret) } else { None }
|

error: use the question mark operator instead of an `and_then` call
error: use the `?` operator instead of an `and_then` call
--> tests/ui/return_and_then.rs:14:9
|
LL | opt.and_then(|n| test_opt_block(Some(n)))
Expand All @@ -32,7 +32,7 @@ LL ~ let n = opt?;
LL + test_opt_block(Some(n))
|

error: use the question mark operator instead of an `and_then` call
error: use the `?` operator instead of an `and_then` call
--> tests/ui/return_and_then.rs:19:9
|
LL | gen_option(1).and_then(|n| test_opt_block(Some(n)))
Expand All @@ -44,7 +44,7 @@ LL ~ let n = gen_option(1)?;
LL + test_opt_block(Some(n))
|

error: use the question mark operator instead of an `and_then` call
error: use the `?` operator instead of an `and_then` call
--> tests/ui/return_and_then.rs:24:9
|
LL | opt.and_then(|n| if n > 1 { Ok(n + 1) } else { Err(n) })
Expand All @@ -56,7 +56,7 @@ LL ~ let n = opt?;
LL + if n > 1 { Ok(n + 1) } else { Err(n) }
|

error: use the question mark operator instead of an `and_then` call
error: use the `?` operator instead of an `and_then` call
--> tests/ui/return_and_then.rs:29:9
|
LL | opt.and_then(|n| test_res_block(Ok(n)))
Expand All @@ -68,7 +68,7 @@ LL ~ let n = opt?;
LL + test_res_block(Ok(n))
|

error: use the question mark operator instead of an `and_then` call
error: use the `?` operator instead of an `and_then` call
--> tests/ui/return_and_then.rs:35:9
|
LL | Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None })
Expand All @@ -80,7 +80,7 @@ LL ~ let x = Some("")?;
LL + if x.len() > 2 { Some(3) } else { None }
|

error: use the question mark operator instead of an `and_then` call
error: use the `?` operator instead of an `and_then` call
--> tests/ui/return_and_then.rs:41:9
|
LL | / Some(match (vec![1, 2, 3], vec![1, 2, 4]) {
Expand Down