Skip to content

Commit 6165ccc

Browse files
committed
Added detailled suggs for new case
1 parent e0e51e4 commit 6165ccc

File tree

2 files changed

+97
-65
lines changed

2 files changed

+97
-65
lines changed

clippy_lints/src/unnecessary_wraps.rs

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::utils::{
2-
contains_return, in_macro, is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_sugg,
3-
span_lint_and_then, visitors::find_all_ret_expressions,
2+
contains_return, in_macro, match_qpath, paths, return_ty, snippet, span_lint_and_then,
3+
visitors::find_all_ret_expressions,
44
};
55
use if_chain::if_chain;
66
use rustc_errors::Applicability;
77
use rustc_hir::intravisit::FnKind;
88
use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node};
99
use rustc_lint::{LateContext, LateLintPass};
10-
use rustc_middle::ty::subst::GenericArgKind;
10+
use rustc_middle::ty;
1111
use rustc_session::{declare_lint_pass, declare_tool_lint};
1212
use rustc_span::symbol::sym;
1313
use rustc_span::Span;
@@ -85,46 +85,44 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
8585
}
8686
}
8787

88-
// Check if return type is Option or Result. If neither, abort.
89-
let return_ty = return_ty(cx, hir_id);
90-
let (return_type_label, path) = if is_type_diagnostic_item(cx, return_ty, sym::option_type) {
91-
("Option", &paths::OPTION_SOME)
92-
} else if is_type_diagnostic_item(cx, return_ty, sym::result_type) {
93-
("Result", &paths::RESULT_OK)
94-
} else {
95-
return;
96-
};
97-
98-
// Take the first inner type of the Option or Result. If can't, abort.
99-
let inner_ty = if_chain! {
100-
// Skip Option or Result and take the first outermost inner type.
101-
if let Some(inner_ty) = return_ty.walk().nth(1);
102-
if let GenericArgKind::Type(inner_ty) = inner_ty.unpack();
103-
then {
104-
inner_ty
88+
// Get the wrapper and inner types, if can't, abort.
89+
let (return_type_label, path, inner_type) = if let ty::Adt(adt_def, subst) = return_ty(cx, hir_id).kind() {
90+
if cx.tcx.is_diagnostic_item(sym::option_type, adt_def.did) {
91+
("Option", &paths::OPTION_SOME, subst.type_at(0))
92+
} else if cx.tcx.is_diagnostic_item(sym::result_type, adt_def.did) {
93+
("Result", &paths::RESULT_OK, subst.type_at(0))
10594
} else {
10695
return;
10796
}
97+
} else {
98+
return;
10899
};
109100

110101
// Check if all return expression respect the following condition and collect them.
111102
let mut suggs = Vec::new();
112103
let can_sugg = find_all_ret_expressions(cx, &body.value, |ret_expr| {
113104
if_chain! {
114-
// Abort if in macro.
115105
if !in_macro(ret_expr.span);
116106
// Check if a function call.
117107
if let ExprKind::Call(ref func, ref args) = ret_expr.kind;
118108
// Get the Path of the function call.
119109
if let ExprKind::Path(ref qpath) = func.kind;
120110
// Check if OPTION_SOME or RESULT_OK, depending on return type.
121111
if match_qpath(qpath, path);
122-
// Make sure the function call has only one argument.
123112
if args.len() == 1;
124113
// Make sure the function argument does not contain a return expression.
125114
if !contains_return(&args[0]);
126115
then {
127-
suggs.push((ret_expr.span, snippet(cx, args[0].span.source_callsite(), "..").to_string()));
116+
suggs.push(
117+
(
118+
ret_expr.span,
119+
if inner_type.is_unit() {
120+
"".to_string()
121+
} else {
122+
snippet(cx, args[0].span.source_callsite(), "..").to_string()
123+
}
124+
)
125+
);
128126
true
129127
} else {
130128
false
@@ -133,42 +131,36 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
133131
});
134132

135133
if can_sugg && !suggs.is_empty() {
136-
// Issue 6640: If the inner type is Unit, emit lint similar to clippy::unused_unit.
137-
if inner_ty.is_unit() {
138-
span_lint_and_sugg(
139-
cx,
140-
UNNECESSARY_WRAPS,
141-
fn_decl.output.span(),
142-
"unneeded wrapped unit return type",
143-
format!("remove the `-> {}<[...]>`", return_type_label).as_str(),
144-
String::new(),
145-
Applicability::MaybeIncorrect,
146-
);
134+
let (lint_msg, return_type_suggestion_msg, return_type_suggestion) = if inner_type.is_unit() {
135+
(
136+
"this function's return value is unnecessary".to_string(),
137+
"remove the return type...".to_string(),
138+
snippet(cx, fn_decl.output.span(), "..").to_string(),
139+
)
147140
} else {
148-
span_lint_and_then(
149-
cx,
150-
UNNECESSARY_WRAPS,
151-
span,
141+
(
152142
format!(
153143
"this function's return value is unnecessarily wrapped by `{}`",
154144
return_type_label
155-
)
156-
.as_str(),
157-
|diag| {
158-
diag.span_suggestion(
159-
fn_decl.output.span(),
160-
format!("remove `{}` from the return type...", return_type_label).as_str(),
161-
inner_ty.to_string(),
162-
Applicability::MaybeIncorrect,
163-
);
164-
diag.multipart_suggestion(
165-
"...and change the returning expressions",
166-
suggs,
167-
Applicability::MaybeIncorrect,
168-
);
169-
},
145+
),
146+
format!("remove `{}` from the return type...", return_type_label),
147+
inner_type.to_string(),
148+
)
149+
};
150+
151+
span_lint_and_then(cx, UNNECESSARY_WRAPS, span, lint_msg.as_str(), |diag| {
152+
diag.span_suggestion(
153+
fn_decl.output.span(),
154+
return_type_suggestion_msg.as_str(),
155+
return_type_suggestion,
156+
Applicability::MaybeIncorrect,
170157
);
171-
}
158+
diag.multipart_suggestion(
159+
"...and then change the returning expressions",
160+
suggs,
161+
Applicability::MaybeIncorrect,
162+
);
163+
});
172164
}
173165
}
174166
}

tests/ui/unnecessary_wraps.stderr

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ help: remove `Option` from the return type...
1515
|
1616
LL | fn func1(a: bool, b: bool) -> i32 {
1717
| ^^^
18-
help: ...and change the returning expressions
18+
help: ...and then change the returning expressions
1919
|
2020
LL | return 42;
2121
LL | }
@@ -41,7 +41,7 @@ help: remove `Option` from the return type...
4141
|
4242
LL | fn func2(a: bool, b: bool) -> i32 {
4343
| ^^^
44-
help: ...and change the returning expressions
44+
help: ...and then change the returning expressions
4545
|
4646
LL | return 10;
4747
LL | }
@@ -63,7 +63,7 @@ help: remove `Option` from the return type...
6363
|
6464
LL | fn func5() -> i32 {
6565
| ^^^
66-
help: ...and change the returning expressions
66+
help: ...and then change the returning expressions
6767
|
6868
LL | 1
6969
|
@@ -80,7 +80,7 @@ help: remove `Result` from the return type...
8080
|
8181
LL | fn func7() -> i32 {
8282
| ^^^
83-
help: ...and change the returning expressions
83+
help: ...and then change the returning expressions
8484
|
8585
LL | 1
8686
|
@@ -97,22 +97,62 @@ help: remove `Option` from the return type...
9797
|
9898
LL | fn func12() -> i32 {
9999
| ^^^
100-
help: ...and change the returning expressions
100+
help: ...and then change the returning expressions
101101
|
102102
LL | 1
103103
|
104104

105-
error: unneeded wrapped unit return type
106-
--> $DIR/unnecessary_wraps.rs:120:38
105+
error: this function's return value is unnecessary
106+
--> $DIR/unnecessary_wraps.rs:120:1
107+
|
108+
LL | / fn issue_6640_1(a: bool, b: bool) -> Option<()> {
109+
LL | | if a && b {
110+
LL | | return Some(());
111+
LL | | }
112+
... |
113+
LL | | }
114+
LL | | }
115+
| |_^
116+
|
117+
help: remove the return type...
107118
|
108119
LL | fn issue_6640_1(a: bool, b: bool) -> Option<()> {
109-
| ^^^^^^^^^^ help: remove the `-> Option<[...]>`
120+
| ^^^^^^^^^^
121+
help: ...and then change the returning expressions
122+
|
123+
LL | return ;
124+
LL | }
125+
LL | if a {
126+
LL | Some(());
127+
LL |
128+
LL | } else {
129+
...
110130

111-
error: unneeded wrapped unit return type
112-
--> $DIR/unnecessary_wraps.rs:133:38
131+
error: this function's return value is unnecessary
132+
--> $DIR/unnecessary_wraps.rs:133:1
133+
|
134+
LL | / fn issue_6640_2(a: bool, b: bool) -> Result<(), i32> {
135+
LL | | if a && b {
136+
LL | | return Ok(());
137+
LL | | }
138+
... |
139+
LL | | }
140+
LL | | }
141+
| |_^
142+
|
143+
help: remove the return type...
113144
|
114145
LL | fn issue_6640_2(a: bool, b: bool) -> Result<(), i32> {
115-
| ^^^^^^^^^^^^^^^ help: remove the `-> Result<[...]>`
146+
| ^^^^^^^^^^^^^^^
147+
help: ...and then change the returning expressions
148+
|
149+
LL | return ;
150+
LL | }
151+
LL | if a {
152+
LL |
153+
LL | } else {
154+
LL | return ;
155+
|
116156

117157
error: aborting due to 7 previous errors
118158

0 commit comments

Comments
 (0)