+ let item_has_safety_comment = item_has_safety_comment(cx, item);
+ match (&item.kind, item_has_safety_comment) {
+ // lint unsafe impl without safety comment
+ (hir::ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.unsafety == hir::Unsafety::Unsafe => {
+ if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id())
+ && !is_unsafe_from_proc_macro(cx, item.span)
+ {
+ let source_map = cx.tcx.sess.source_map();
+ let span = if source_map.is_multiline(item.span) {
+ source_map.span_until_char(item.span, '\n')
+ } else {
+ item.span
+ };
+
+ span_lint_and_help(
+ cx,
+ UNDOCUMENTED_UNSAFE_BLOCKS,
+ span,
+ "unsafe impl missing a safety comment",
+ None,
+ "consider adding a safety comment on the preceding line",
+ );
+ }
+ },
+ // lint safe impl with unnecessary safety comment
+ (hir::ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.unsafety == hir::Unsafety::Normal => {
+ if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
+ let (span, help_span) = mk_spans(pos);
+
+ span_lint_and_help(
+ cx,
+ UNNECESSARY_SAFETY_COMMENT,
+ span,
+ "impl has unnecessary safety comment",
+ Some(help_span),
+ "consider removing the safety comment",
+ );
+ }
+ },
+ (hir::ItemKind::Impl(_), _) => {},
+ // const and static items only need a safety comment if their body is an unsafe block, lint otherwise
+ (&hir::ItemKind::Const(.., body) | &hir::ItemKind::Static(.., body), HasSafetyComment::Yes(pos)) => {
+ if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, body.hir_id) {
+ let body = cx.tcx.hir().body(body);
+ if !matches!(
+ body.value.kind, hir::ExprKind::Block(block, _)
+ if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
+ ) {
+ let (span, help_span) = mk_spans(pos);
+
+ span_lint_and_help(
+ cx,
+ UNNECESSARY_SAFETY_COMMENT,
+ span,
+ &format!("{} has unnecessary safety comment", item.kind.descr()),
+ Some(help_span),
+ "consider removing the safety comment",
+ );
+ }
+ }
+ },
+ // Aside from unsafe impls and consts/statics with an unsafe block, items in general
+ // do not have safety invariants that need to be documented, so lint those.
+ (_, HasSafetyComment::Yes(pos)) => {
+ if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
+ let (span, help_span) = mk_spans(pos);
+
+ span_lint_and_help(
+ cx,
+ UNNECESSARY_SAFETY_COMMENT,
+ span,
+ &format!("{} has unnecessary safety comment", item.kind.descr()),
+ Some(help_span),
+ "consider removing the safety comment",
+ );
+ }
+ },
+ _ => (),