]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/implicit_return.rs
modify code
[rust.git] / clippy_lints / src / implicit_return.rs
index f2f830ca5c09e51a6dec78fd166f515801d8c377..d650d6e9a85871881a680e755c6fc7def02fb345 100644 (file)
@@ -2,10 +2,10 @@
     diagnostics::span_lint_and_sugg,
     get_async_fn_body, is_async_fn,
     source::{snippet_with_applicability, snippet_with_context, walk_span_to_context},
-    visitors::visit_break_exprs,
+    visitors::expr_visitor_no_bodies,
 };
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::FnKind;
+use rustc_hir::intravisit::{FnKind, Visitor};
 use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_span::{Span, SyntaxContext};
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for missing return statements at the end of a block.
+    /// ### What it does
+    /// Checks for missing return statements at the end of a block.
     ///
-    /// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers
+    /// ### Why is this bad?
+    /// Actually omitting the return keyword is idiomatic Rust code. Programmers
     /// coming from other languages might prefer the expressiveness of `return`. It's possible to miss
     /// the last returning statement because the only difference is a missing `;`. Especially in bigger
     /// code with multiple return paths having a `return` keyword makes it easier to find the
     /// corresponding statements.
     ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
+    /// ### Example
     /// ```rust
     /// fn foo(x: usize) -> usize {
     ///     x
@@ -35,6 +35,7 @@
     ///     return x;
     /// }
     /// ```
+    #[clippy::version = "1.33.0"]
     pub IMPLICIT_RETURN,
     restriction,
     "use a return statement like `return expr` instead of an expression"
@@ -93,8 +94,8 @@ fn get_call_site(span: Span, ctxt: SyntaxContext) -> Option<Span> {
 }
 
 fn lint_implicit_returns(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx Expr<'_>,
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
     // The context of the function body.
     ctxt: SyntaxContext,
     // Whether the expression is from a macro expansion.
@@ -144,20 +145,24 @@ fn lint_implicit_returns(
 
         ExprKind::Loop(block, ..) => {
             let mut add_return = false;
-            visit_break_exprs(block, |break_expr, dest, sub_expr| {
-                if dest.target_id.ok() == Some(expr.hir_id) {
-                    if call_site_span.is_none() && break_expr.span.ctxt() == ctxt {
-                        // At this point sub_expr can be `None` in async functions which either diverge, or return the
-                        // unit type.
-                        if let Some(sub_expr) = sub_expr {
-                            lint_break(cx, break_expr.span, sub_expr.span);
+            expr_visitor_no_bodies(|e| {
+                if let ExprKind::Break(dest, sub_expr) = e.kind {
+                    if dest.target_id.ok() == Some(expr.hir_id) {
+                        if call_site_span.is_none() && e.span.ctxt() == ctxt {
+                            // At this point sub_expr can be `None` in async functions which either diverge, or return
+                            // the unit type.
+                            if let Some(sub_expr) = sub_expr {
+                                lint_break(cx, e.span, sub_expr.span);
+                            }
+                        } else {
+                            // the break expression is from a macro call, add a return to the loop
+                            add_return = true;
                         }
-                    } else {
-                        // the break expression is from a macro call, add a return to the loop
-                        add_return = true;
                     }
                 }
-            });
+                true
+            })
+            .visit_block(block);
             if add_return {
                 #[allow(clippy::option_if_let_else)]
                 if let Some(span) = call_site_span {