diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index b07326c524cc..dff6fb932b25 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::ty::{get_type_diagnostic_name, implements_trait_with_env, is_type_diagnostic_item}; use clippy_utils::visitors::Visitable; -use clippy_utils::{is_doc_hidden, method_chain_args, return_ty}; +use clippy_utils::{fulfill_or_allowed, is_doc_hidden, method_chain_args, return_ty}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AnonConst, BodyId, Expr, FnSig, OwnerId, Safety}; use rustc_lint::LateContext; @@ -129,6 +129,7 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { Some(sym::assert_macro | sym::assert_eq_macro | sym::assert_ne_macro) )) && !self.cx.tcx.hir_is_inside_const_context(expr.hir_id) + && !fulfill_or_allowed(self.cx, MISSING_PANICS_DOC, [expr.hir_id]) { self.panic_span = Some(macro_call.span); } @@ -140,7 +141,8 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { if matches!( get_type_diagnostic_name(self.cx, receiver_ty), Some(sym::Option | sym::Result) - ) { + ) && !fulfill_or_allowed(self.cx, MISSING_PANICS_DOC, [expr.hir_id]) + { self.panic_span = Some(expr.span); } } diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index ce0e3cae51c6..ab77edf1147c 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -188,6 +188,19 @@ declare_clippy_lint! { /// } /// } /// ``` + /// + /// Individual panics within a function can be ignored with `#[expect]` or + /// `#[allow]`: + /// + /// ```no_run + /// # use std::num::NonZeroUsize; + /// pub fn will_not_panic(x: usize) { + /// #[expect(clippy::missing_panics_doc, reason = "infallible")] + /// let y = NonZeroUsize::new(1).unwrap(); + /// + /// // If any panics are added in the future the lint will still catch them + /// } + /// ``` #[clippy::version = "1.51.0"] pub MISSING_PANICS_DOC, pedantic, diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 95236d33fd8b..ac6431b5452b 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -161,6 +161,26 @@ pub fn partially_const(n: usize) { assert!(N > n); } +pub fn expect_allow(i: Option) { + #[expect(clippy::missing_panics_doc)] + i.unwrap(); + + #[allow(clippy::missing_panics_doc)] + i.unwrap(); +} + +pub fn expect_allow_with_error(i: Option) { + //~^ missing_panics_doc + + #[expect(clippy::missing_panics_doc)] + i.unwrap(); + + #[allow(clippy::missing_panics_doc)] + i.unwrap(); + + i.unwrap(); +} + // all function must be triggered the lint. // `pub` is required, because the lint does not consider unreachable items pub mod issue10240 { diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index 80ab5b064730..dbacd15865df 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -85,76 +85,88 @@ LL | assert!(N > n); | ^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:167:5 + --> tests/ui/missing_panics_doc.rs:172:1 + | +LL | pub fn expect_allow_with_error(i: Option) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:181:5 + | +LL | i.unwrap(); + | ^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:187:5 | LL | pub fn option_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:170:9 + --> tests/ui/missing_panics_doc.rs:190:9 | LL | o.unwrap() | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:173:5 + --> tests/ui/missing_panics_doc.rs:193:5 | LL | pub fn option_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:176:9 + --> tests/ui/missing_panics_doc.rs:196:9 | LL | o.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:179:5 + --> tests/ui/missing_panics_doc.rs:199:5 | LL | pub fn result_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:182:9 + --> tests/ui/missing_panics_doc.rs:202:9 | LL | res.unwrap() | ^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:185:5 + --> tests/ui/missing_panics_doc.rs:205:5 | LL | pub fn result_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:188:9 + --> tests/ui/missing_panics_doc.rs:208:9 | LL | res.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:191:5 + --> tests/ui/missing_panics_doc.rs:211:5 | LL | pub fn last_unwrap(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:193:10 + --> tests/ui/missing_panics_doc.rs:213:10 | LL | *v.last().unwrap() | ^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:196:5 + --> tests/ui/missing_panics_doc.rs:216:5 | LL | pub fn last_expect(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:198:10 + --> tests/ui/missing_panics_doc.rs:218:10 | LL | *v.last().expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors