• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use clippy_utils::diagnostics::span_lint_and_help;
2 
3 use clippy_utils::macros::span_is_local;
4 use rustc_hir::{Expr, ExprKind, MatchSource};
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7 
8 declare_clippy_lint! {
9     /// ### What it does
10     /// Checks for expressions that use the question mark operator and rejects them.
11     ///
12     /// ### Why is this bad?
13     /// Sometimes code wants to avoid the question mark operator because for instance a local
14     /// block requires a macro to re-throw errors to attach additional information to the
15     /// error.
16     ///
17     /// ### Example
18     /// ```ignore
19     /// let result = expr?;
20     /// ```
21     ///
22     /// Could be written:
23     ///
24     /// ```ignore
25     /// utility_macro!(expr);
26     /// ```
27     #[clippy::version = "1.69.0"]
28     pub QUESTION_MARK_USED,
29     restriction,
30     "complains if the question mark operator is used"
31 }
32 
33 declare_lint_pass!(QuestionMarkUsed => [QUESTION_MARK_USED]);
34 
35 impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)36     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
37         if let ExprKind::Match(_, _, MatchSource::TryDesugar) = expr.kind {
38             if !span_is_local(expr.span) {
39                 return;
40             }
41 
42             span_lint_and_help(
43                 cx,
44                 QUESTION_MARK_USED,
45                 expr.span,
46                 "question mark operator was used",
47                 None,
48                 "consider using a custom macro or match expression",
49             );
50         }
51     }
52 }
53