forked from rust-lang/rust
-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master' into rustup
- Loading branch information
Showing
12 changed files
with
289 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
use crate::utils::{is_expn_of, is_type_diagnostic_item, return_ty, span_lint_and_then}; | ||
use rustc_hir as hir; | ||
use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor}; | ||
use rustc_hir::Expr; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_middle::hir::map::Map; | ||
use rustc_session::{declare_lint_pass, declare_tool_lint}; | ||
use rustc_span::Span; | ||
|
||
declare_clippy_lint! { | ||
/// **What it does:** Checks for usage of `panic!`, `unimplemented!`, `todo!` or `unreachable!` in a function of type result. | ||
/// | ||
/// **Why is this bad?** For some codebases, it is desirable for functions of type result to return an error instead of crashing. Hence unimplemented, panic and unreachable should be avoided. | ||
/// | ||
/// **Known problems:** None. | ||
/// | ||
/// **Example:** | ||
/// | ||
/// ```rust | ||
/// fn result_with_panic() -> Result<bool, String> | ||
/// { | ||
/// panic!("error"); | ||
/// } | ||
/// ``` | ||
pub PANIC_IN_RESULT_FN, | ||
restriction, | ||
"functions of type `Result<..>` that contain `panic!()`, `todo!()` or `unreachable()` or `unimplemented()` " | ||
} | ||
|
||
declare_lint_pass!(PanicInResultFn => [PANIC_IN_RESULT_FN]); | ||
|
||
impl<'tcx> LateLintPass<'tcx> for PanicInResultFn { | ||
fn check_fn( | ||
&mut self, | ||
cx: &LateContext<'tcx>, | ||
fn_kind: FnKind<'tcx>, | ||
_: &'tcx hir::FnDecl<'tcx>, | ||
body: &'tcx hir::Body<'tcx>, | ||
span: Span, | ||
hir_id: hir::HirId, | ||
) { | ||
if !matches!(fn_kind, FnKind::Closure(_)) | ||
&& is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(result_type)) | ||
{ | ||
lint_impl_body(cx, span, body); | ||
} | ||
} | ||
} | ||
|
||
struct FindPanicUnimplementedUnreachable { | ||
result: Vec<Span>, | ||
} | ||
|
||
impl<'tcx> Visitor<'tcx> for FindPanicUnimplementedUnreachable { | ||
type Map = Map<'tcx>; | ||
|
||
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { | ||
if ["unimplemented", "unreachable", "panic", "todo"] | ||
.iter() | ||
.any(|fun| is_expn_of(expr.span, fun).is_some()) | ||
{ | ||
self.result.push(expr.span); | ||
} | ||
// and check sub-expressions | ||
intravisit::walk_expr(self, expr); | ||
} | ||
|
||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { | ||
NestedVisitorMap::None | ||
} | ||
} | ||
|
||
fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) { | ||
let mut panics = FindPanicUnimplementedUnreachable { result: Vec::new() }; | ||
panics.visit_expr(&body.value); | ||
if !panics.result.is_empty() { | ||
span_lint_and_then( | ||
cx, | ||
PANIC_IN_RESULT_FN, | ||
impl_span, | ||
"used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`", | ||
move |diag| { | ||
diag.help( | ||
"`unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing", | ||
); | ||
diag.span_note(panics.result, "return Err() instead of panicking"); | ||
}, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#![warn(clippy::panic_in_result_fn)] | ||
|
||
struct A; | ||
|
||
impl A { | ||
fn result_with_panic() -> Result<bool, String> // should emit lint | ||
{ | ||
panic!("error"); | ||
} | ||
|
||
fn result_with_unimplemented() -> Result<bool, String> // should emit lint | ||
{ | ||
unimplemented!(); | ||
} | ||
|
||
fn result_with_unreachable() -> Result<bool, String> // should emit lint | ||
{ | ||
unreachable!(); | ||
} | ||
|
||
fn result_with_todo() -> Result<bool, String> // should emit lint | ||
{ | ||
todo!("Finish this"); | ||
} | ||
|
||
fn other_with_panic() // should not emit lint | ||
{ | ||
panic!(""); | ||
} | ||
|
||
fn other_with_unreachable() // should not emit lint | ||
{ | ||
unreachable!(); | ||
} | ||
|
||
fn other_with_unimplemented() // should not emit lint | ||
{ | ||
unimplemented!(); | ||
} | ||
|
||
fn other_with_todo() // should not emit lint | ||
{ | ||
todo!("finish this") | ||
} | ||
|
||
fn result_without_banned_functions() -> Result<bool, String> // should not emit lint | ||
{ | ||
Ok(true) | ||
} | ||
} | ||
|
||
fn function_result_with_panic() -> Result<bool, String> // should emit lint | ||
{ | ||
panic!("error"); | ||
} | ||
|
||
fn todo() { | ||
println!("something"); | ||
} | ||
|
||
fn function_result_with_custom_todo() -> Result<bool, String> // should not emit lint | ||
{ | ||
todo(); | ||
Ok(true) | ||
} | ||
|
||
fn main() -> Result<(), String> { | ||
todo!("finish main method"); | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result` | ||
--> $DIR/panic_in_result_fn.rs:6:5 | ||
| | ||
LL | / fn result_with_panic() -> Result<bool, String> // should emit lint | ||
LL | | { | ||
LL | | panic!("error"); | ||
LL | | } | ||
| |_____^ | ||
| | ||
= note: `-D clippy::panic-in-result-fn` implied by `-D warnings` | ||
= help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing | ||
note: return Err() instead of panicking | ||
--> $DIR/panic_in_result_fn.rs:8:9 | ||
| | ||
LL | panic!("error"); | ||
| ^^^^^^^^^^^^^^^^ | ||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result` | ||
--> $DIR/panic_in_result_fn.rs:11:5 | ||
| | ||
LL | / fn result_with_unimplemented() -> Result<bool, String> // should emit lint | ||
LL | | { | ||
LL | | unimplemented!(); | ||
LL | | } | ||
| |_____^ | ||
| | ||
= help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing | ||
note: return Err() instead of panicking | ||
--> $DIR/panic_in_result_fn.rs:13:9 | ||
| | ||
LL | unimplemented!(); | ||
| ^^^^^^^^^^^^^^^^^ | ||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result` | ||
--> $DIR/panic_in_result_fn.rs:16:5 | ||
| | ||
LL | / fn result_with_unreachable() -> Result<bool, String> // should emit lint | ||
LL | | { | ||
LL | | unreachable!(); | ||
LL | | } | ||
| |_____^ | ||
| | ||
= help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing | ||
note: return Err() instead of panicking | ||
--> $DIR/panic_in_result_fn.rs:18:9 | ||
| | ||
LL | unreachable!(); | ||
| ^^^^^^^^^^^^^^^ | ||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result` | ||
--> $DIR/panic_in_result_fn.rs:21:5 | ||
| | ||
LL | / fn result_with_todo() -> Result<bool, String> // should emit lint | ||
LL | | { | ||
LL | | todo!("Finish this"); | ||
LL | | } | ||
| |_____^ | ||
| | ||
= help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing | ||
note: return Err() instead of panicking | ||
--> $DIR/panic_in_result_fn.rs:23:9 | ||
| | ||
LL | todo!("Finish this"); | ||
| ^^^^^^^^^^^^^^^^^^^^^ | ||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result` | ||
--> $DIR/panic_in_result_fn.rs:52:1 | ||
| | ||
LL | / fn function_result_with_panic() -> Result<bool, String> // should emit lint | ||
LL | | { | ||
LL | | panic!("error"); | ||
LL | | } | ||
| |_^ | ||
| | ||
= help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing | ||
note: return Err() instead of panicking | ||
--> $DIR/panic_in_result_fn.rs:54:5 | ||
| | ||
LL | panic!("error"); | ||
| ^^^^^^^^^^^^^^^^ | ||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error: used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result` | ||
--> $DIR/panic_in_result_fn.rs:67:1 | ||
| | ||
LL | / fn main() -> Result<(), String> { | ||
LL | | todo!("finish main method"); | ||
LL | | Ok(()) | ||
LL | | } | ||
| |_^ | ||
| | ||
= help: `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing | ||
note: return Err() instead of panicking | ||
--> $DIR/panic_in_result_fn.rs:68:5 | ||
| | ||
LL | todo!("finish main method"); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error: aborting due to 6 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
#![warn(clippy::temporary_assignment)] | ||
#![allow(const_item_mutation)] | ||
|
||
use std::ops::{Deref, DerefMut}; | ||
|
||
|
Oops, something went wrong.