From d793c0abfa7997d65b8b52df7c8a15532c5b49df Mon Sep 17 00:00:00 2001 From: Jan Verbeek Date: Wed, 19 Mar 2025 09:16:58 +0100 Subject: [PATCH] Add MSRV check for `question_mark` --- book/src/lint_configuration.md | 1 + clippy_config/src/conf.rs | 1 + clippy_lints/src/question_mark.rs | 10 +++++++--- clippy_utils/src/msrvs.rs | 1 + tests/ui/question_mark.fixed | 21 +++++++++++++++++++++ tests/ui/question_mark.rs | 28 ++++++++++++++++++++++++++++ tests/ui/question_mark.stderr | 22 +++++++++++++++++++++- 7 files changed, 80 insertions(+), 4 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 3cd70ed18b59..3726d6e8a869 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -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) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 75f68d0dc5f9..798f8b3aa5a9 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -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, diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 2c9d3c1ba1fc..a80e1f79bbc7 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -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); diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 523e7e5aaa69..ef0f1fd40be9 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -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 diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 41e3910ad486..fff41f578284 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -409,3 +409,24 @@ fn issue_13417_weirder(foo: &mut StructWithOptionString, mut bar: Option) -> Option { + 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) -> Option { + arg?; + let val = arg?; + println!("{}", val); + Some(val) +} diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index e570788bfdf1..c71c8ee984ed 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -496,3 +496,31 @@ fn issue_13417_weirder(foo: &mut StructWithOptionString, mut bar: Option) -> Option { + 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) -> Option { + if arg.is_none() { + //~^ question_mark + return None; + } + let val = match arg { + //~^ question_mark + Some(val) => val, + None => return None, + }; + println!("{}", val); + Some(val) +} diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 7c80878fe817..183b8866a748 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -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