diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 256231441..ee559d45d 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -35,6 +35,7 @@ struct FmtContext { } // the "main" function of cargo dev fmt +#[allow(clippy::missing_panics_doc)] pub fn run(check: bool, verbose: bool) { fn try_run(context: &FmtContext) -> Result { let mut success = true; diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 56a269288..8aaa029f7 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -29,6 +29,10 @@ static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; /// Returns the path to the `cargo-clippy` binary +/// +/// # Panics +/// +/// Panics if the path of current executable could not be retrieved. #[must_use] pub fn cargo_clippy_path() -> PathBuf { let mut path = std::env::current_exe().expect("failed to get current executable name"); @@ -61,6 +65,8 @@ pub fn clippy_project_root() -> PathBuf { panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); } +/// # Panics +/// Panics if given command result was failed. pub fn exit_if_err(status: io::Result) { match status.expect("failed to run command").code() { Some(0) => {}, diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index f970a3272..f0ccdb0fe 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -36,6 +36,7 @@ impl Context for io::Result { /// # Errors /// /// This function errors out if the files couldn't be created or written to. +#[allow(clippy::missing_panics_doc)] pub fn create( pass: &String, lint_name: Option<&String>, diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 0617c3ea5..815495a7b 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -916,8 +916,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { } } - // check for `unwrap` - if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + // check for `unwrap` and `expect` for both `Option` and `Result` + if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) { let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result) diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 10aa436d6..d544a0b1a 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -151,3 +151,35 @@ pub fn debug_assertions() { debug_assert_eq!(1, 2); debug_assert_ne!(1, 2); } + +// all function must be triggered the lint. +// `pub` is required, because the lint does not consider unreachable items +pub mod issue10240 { + pub fn option_unwrap(v: &[T]) -> &T { + let o: Option<&T> = v.last(); + o.unwrap() + } + + pub fn option_expect(v: &[T]) -> &T { + let o: Option<&T> = v.last(); + o.expect("passed an empty thing") + } + + pub fn result_unwrap(v: &[T]) -> &T { + let res: Result<&T, &str> = v.last().ok_or("oh noes"); + res.unwrap() + } + + pub fn result_expect(v: &[T]) -> &T { + let res: Result<&T, &str> = v.last().ok_or("oh noes"); + res.expect("passed an empty thing") + } + + pub fn last_unwrap(v: &[u32]) -> u32 { + *v.last().unwrap() + } + + pub fn last_expect(v: &[u32]) -> u32 { + *v.last().expect("passed an empty thing") + } +} diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index 183c262ce..39d97f083 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -83,5 +83,77 @@ note: first possible panic found here LL | assert_ne!(x, 0); | ^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:158:5 + | +LL | pub fn option_unwrap(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:160:9 + | +LL | o.unwrap() + | ^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:163:5 + | +LL | pub fn option_expect(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:165:9 + | +LL | o.expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:168:5 + | +LL | pub fn result_unwrap(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:170:9 + | +LL | res.unwrap() + | ^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:173:5 + | +LL | pub fn result_expect(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:175:9 + | +LL | res.expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:178:5 + | +LL | pub fn last_unwrap(v: &[u32]) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:179:10 + | +LL | *v.last().unwrap() + | ^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:182:5 + | +LL | pub fn last_expect(v: &[u32]) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:183:10 + | +LL | *v.last().expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 13 previous errors