use crate::utils::{
- in_macro_or_desugar, match_def_path,
+ match_def_path,
paths::{BEGIN_PANIC, BEGIN_PANIC_FMT},
- resolve_node, snippet_opt, span_lint_and_then,
+ snippet_opt, span_lint_and_then,
};
use if_chain::if_chain;
-use rustc::{
- declare_lint_pass, declare_tool_lint,
- hir::{intravisit::FnKind, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind},
- lint::{LateContext, LateLintPass, LintArray, LintPass},
-};
use rustc_errors::Applicability;
-use syntax_pos::Span;
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::source_map::Span;
declare_clippy_lint! {
/// **What it does:** Checks for missing return statements at the end of a block.
static LINT_RETURN: &str = "add `return` as shown";
fn lint(cx: &LateContext<'_, '_>, outer_span: Span, inner_span: Span, msg: &str) {
- let outer_span = span_to_outer_expn(outer_span);
- let inner_span = span_to_outer_expn(inner_span);
+ let outer_span = outer_span.source_callsite();
+ let inner_span = inner_span.source_callsite();
- span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| {
+ span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing `return` statement", |db| {
if let Some(snippet) = snippet_opt(cx, inner_span) {
db.span_suggestion(
outer_span,
});
}
-fn span_to_outer_expn(span: Span) -> Span {
- if let Some(expr) = span.ctxt().outer_expn_info() {
- span_to_outer_expn(expr.call_site)
- } else {
- span
- }
-}
-
-fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr) {
- match &expr.node {
+fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
+ match expr.kind {
// loops could be using `break` instead of `return`
ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => {
if let Some(expr) = &block.expr {
// only needed in the case of `break` with `;` at the end
else if let Some(stmt) = block.stmts.last() {
if_chain! {
- if let StmtKind::Semi(expr, ..) = &stmt.node;
+ if let StmtKind::Semi(expr, ..) = &stmt.kind;
// make sure it's a break, otherwise we want to skip
- if let ExprKind::Break(.., break_expr) = &expr.node;
+ if let ExprKind::Break(.., break_expr) = &expr.kind;
if let Some(break_expr) = break_expr;
then {
lint(cx, expr.span, break_expr.span, LINT_BREAK);
let check_all_arms = match source {
MatchSource::IfLetDesugar {
contains_else_clause: has_else,
- } => *has_else,
+ } => has_else,
_ => true,
};
expr_match(cx, &arm.body);
}
} else {
- expr_match(cx, &arms.first().expect("if let doesn't have a single arm").body);
+ expr_match(cx, &arms.first().expect("`if let` doesn't have a single arm").body);
}
},
// skip if it already has a return statement
// make sure it's not a call that panics
ExprKind::Call(expr, ..) => {
if_chain! {
- if let ExprKind::Path(qpath) = &expr.node;
- if let Some(path_def_id) = resolve_node(cx, qpath, expr.hir_id).opt_def_id();
+ if let ExprKind::Path(qpath) = &expr.kind;
+ if let Some(path_def_id) = cx.tables.qpath_res(qpath, expr.hir_id).opt_def_id();
if match_def_path(cx, path_def_id, &BEGIN_PANIC) ||
match_def_path(cx, path_def_id, &BEGIN_PANIC_FMT);
then { }
&mut self,
cx: &LateContext<'a, 'tcx>,
_: FnKind<'tcx>,
- _: &'tcx FnDecl,
- body: &'tcx Body,
- span: syntax::source_map::Span,
+ _: &'tcx FnDecl<'_>,
+ body: &'tcx Body<'_>,
+ span: Span,
_: HirId,
) {
let def_id = cx.tcx.hir().body_owner_def_id(body.id());
// checking return type through MIR, HIR is not able to determine inferred closure return types
// make sure it's not a macro
- if !mir.return_ty().is_unit() && !in_macro_or_desugar(span) {
+ if !mir.return_ty().is_unit() && !span.from_expansion() {
expr_match(cx, &body.value);
}
}