Skip to content

Commit 6cbb093

Browse files
committed
Auto merge of #6397 - matsujika:fix-6384, r=flip1995
Fix a false positive in `unnecessary_wraps` Fix #6384 changelog: Fix FP in `unnecessary_wraps` that happens when `Call` expr has `Return` expr inside
2 parents b627731 + 2c26cb1 commit 6cbb093

File tree

4 files changed

+45
-38
lines changed

4 files changed

+45
-38
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ use if_chain::if_chain;
1414
use rustc_ast::ast;
1515
use rustc_errors::Applicability;
1616
use rustc_hir as hir;
17-
use rustc_hir::intravisit::{self, Visitor};
1817
use rustc_hir::{TraitItem, TraitItemKind};
1918
use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
20-
use rustc_middle::hir::map::Map;
2119
use rustc_middle::lint::in_external_macro;
2220
use rustc_middle::ty::{self, TraitRef, Ty, TyS};
2321
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -28,11 +26,12 @@ use crate::consts::{constant, Constant};
2826
use crate::utils::eager_or_lazy::is_lazyness_candidate;
2927
use crate::utils::usage::mutated_variables;
3028
use crate::utils::{
31-
contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro,
32-
is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath,
33-
match_trait_method, match_type, match_var, meets_msrv, method_calls, method_chain_args, paths, remove_blocks,
34-
return_ty, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
35-
span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth, SpanlessEq,
29+
contains_return, contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher,
30+
implements_trait, in_macro, is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment,
31+
match_def_path, match_qpath, match_trait_method, match_type, match_var, meets_msrv, method_calls,
32+
method_chain_args, paths, remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability,
33+
snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg,
34+
walk_ptrs_ty_depth, SpanlessEq,
3635
};
3736
use semver::{Version, VersionReq};
3837

@@ -3877,36 +3876,6 @@ fn is_bool(ty: &hir::Ty<'_>) -> bool {
38773876
}
38783877
}
38793878

3880-
// Returns `true` if `expr` contains a return expression
3881-
fn contains_return(expr: &hir::Expr<'_>) -> bool {
3882-
struct RetCallFinder {
3883-
found: bool,
3884-
}
3885-
3886-
impl<'tcx> intravisit::Visitor<'tcx> for RetCallFinder {
3887-
type Map = Map<'tcx>;
3888-
3889-
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
3890-
if self.found {
3891-
return;
3892-
}
3893-
if let hir::ExprKind::Ret(..) = &expr.kind {
3894-
self.found = true;
3895-
} else {
3896-
intravisit::walk_expr(self, expr);
3897-
}
3898-
}
3899-
3900-
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
3901-
intravisit::NestedVisitorMap::None
3902-
}
3903-
}
3904-
3905-
let mut visitor = RetCallFinder { found: false };
3906-
visitor.visit_expr(expr);
3907-
visitor.found
3908-
}
3909-
39103879
fn check_pointer_offset(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
39113880
if_chain! {
39123881
if args.len() == 2;

clippy_lints/src/unnecessary_wraps.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::utils::{
2-
in_macro, is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_then,
2+
contains_return, in_macro, is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_then,
33
visitors::find_all_ret_expressions,
44
};
55
use if_chain::if_chain;
@@ -95,6 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
9595
if let ExprKind::Path(ref qpath) = func.kind;
9696
if match_qpath(qpath, path);
9797
if args.len() == 1;
98+
if !contains_return(&args[0]);
9899
then {
99100
suggs.push((ret_expr.span, snippet(cx, args[0].span.source_callsite(), "..").to_string()));
100101
true

clippy_lints/src/utils/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,36 @@ pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
572572
cn.result
573573
}
574574

575+
/// Returns `true` if `expr` contains a return expression
576+
pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
577+
struct RetCallFinder {
578+
found: bool,
579+
}
580+
581+
impl<'tcx> hir::intravisit::Visitor<'tcx> for RetCallFinder {
582+
type Map = Map<'tcx>;
583+
584+
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
585+
if self.found {
586+
return;
587+
}
588+
if let hir::ExprKind::Ret(..) = &expr.kind {
589+
self.found = true;
590+
} else {
591+
hir::intravisit::walk_expr(self, expr);
592+
}
593+
}
594+
595+
fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
596+
hir::intravisit::NestedVisitorMap::None
597+
}
598+
}
599+
600+
let mut visitor = RetCallFinder { found: false };
601+
visitor.visit_expr(expr);
602+
visitor.found
603+
}
604+
575605
/// Converts a span to a code snippet if available, otherwise use default.
576606
///
577607
/// This is useful if you want to provide suggestions for your lint or more generally, if you want

tests/ui/unnecessary_wraps.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ impl B for A {
109109
}
110110
}
111111

112+
fn issue_6384(s: &str) -> Option<&str> {
113+
Some(match s {
114+
"a" => "A",
115+
_ => return None,
116+
})
117+
}
118+
112119
fn main() {
113120
// method calls are not linted
114121
func1(true, true);

0 commit comments

Comments
 (0)