Add MSRV check for question_mark (#14436)

changelog: [`question_mark`]: Now respects the [`msrv`] configuration
This commit is contained in:
Manish Goregaokar 2025-03-19 15:56:45 +00:00 committed by GitHub
commit 48ce25ea0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 80 additions and 4 deletions

View file

@ -819,6 +819,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref)
* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or)
* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr)
* [`question_mark`](https://rust-lang.github.io/rust-clippy/master/index.html#question_mark)
* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names)
* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes)
* [`repeat_vec_with_capacity`](https://rust-lang.github.io/rust-clippy/master/index.html#repeat_vec_with_capacity)

View file

@ -668,6 +668,7 @@ define_Conf! {
option_as_ref_deref,
option_map_unwrap_or,
ptr_as_ptr,
question_mark,
redundant_field_names,
redundant_static_lifetimes,
repeat_vec_with_capacity,

View file

@ -3,7 +3,7 @@ use crate::question_mark_used::QUESTION_MARK_USED;
use clippy_config::Conf;
use clippy_config::types::MatchLintBehaviour;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::Msrv;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{
@ -524,7 +524,8 @@ fn is_inferred_ret_closure(expr: &Expr<'_>) -> bool {
impl<'tcx> LateLintPass<'tcx> for QuestionMark {
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
if !is_lint_allowed(cx, QUESTION_MARK_USED, stmt.hir_id) {
if !is_lint_allowed(cx, QUESTION_MARK_USED, stmt.hir_id) || !self.msrv.meets(cx, msrvs::QUESTION_MARK_OPERATOR)
{
return;
}
@ -540,7 +541,10 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
return;
}
if !self.inside_try_block() && !is_in_const_context(cx) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id)
if !self.inside_try_block()
&& !is_in_const_context(cx)
&& is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id)
&& self.msrv.meets(cx, msrvs::QUESTION_MARK_OPERATOR)
{
check_is_none_or_err_and_early_return(cx, expr);
check_if_let_some_or_err_and_early_return(cx, expr);

View file

@ -74,6 +74,7 @@ msrv_aliases! {
1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
1,16,0 { STR_REPEAT }
1,15,0 { MAYBE_BOUND_IN_WHERE }
1,13,0 { QUESTION_MARK_OPERATOR }
}
/// `#[clippy::msrv]` attributes are rarely used outside of Clippy's test suite, as a basic

View file

@ -409,3 +409,24 @@ fn issue_13417_weirder(foo: &mut StructWithOptionString, mut bar: Option<Wrapper
//~^^^ question_mark
Some(())
}
#[clippy::msrv = "1.12"]
fn msrv_1_12(arg: Option<i32>) -> Option<i32> {
if arg.is_none() {
return None;
}
let val = match arg {
Some(val) => val,
None => return None,
};
println!("{}", val);
Some(val)
}
#[clippy::msrv = "1.13"]
fn msrv_1_13(arg: Option<i32>) -> Option<i32> {
arg?;
let val = arg?;
println!("{}", val);
Some(val)
}

View file

@ -496,3 +496,31 @@ fn issue_13417_weirder(foo: &mut StructWithOptionString, mut bar: Option<Wrapper
//~^^^ question_mark
Some(())
}
#[clippy::msrv = "1.12"]
fn msrv_1_12(arg: Option<i32>) -> Option<i32> {
if arg.is_none() {
return None;
}
let val = match arg {
Some(val) => val,
None => return None,
};
println!("{}", val);
Some(val)
}
#[clippy::msrv = "1.13"]
fn msrv_1_13(arg: Option<i32>) -> Option<i32> {
if arg.is_none() {
//~^ question_mark
return None;
}
let val = match arg {
//~^ question_mark
Some(val) => val,
None => return None,
};
println!("{}", val);
Some(val)
}

View file

@ -255,5 +255,25 @@ LL | | return None;
LL | | };
| |______^ help: replace it with: `let x @ &mut WrapperStructWithString(_) = bar.as_mut()?;`
error: aborting due to 27 previous errors
error: this block may be rewritten with the `?` operator
--> tests/ui/question_mark.rs:515:5
|
LL | / if arg.is_none() {
LL | |
LL | | return None;
LL | | }
| |_____^ help: replace it with: `arg?;`
error: this `match` expression can be replaced with `?`
--> tests/ui/question_mark.rs:519:15
|
LL | let val = match arg {
| _______________^
LL | |
LL | | Some(val) => val,
LL | | None => return None,
LL | | };
| |_____^ help: try instead: `arg?`
error: aborting due to 29 previous errors