Propagate TraitImplHeader to hir

This commit is contained in:
Cameron Steffen 2025-07-24 09:32:58 -05:00
parent 7fe9a40b6b
commit 9f98857714
29 changed files with 64 additions and 60 deletions

View file

@ -534,6 +534,7 @@ fn get_item_name(item: &Item<'_>) -> Option<String> {
if let Some(of_trait) = im.of_trait {
let mut trait_segs: Vec<String> = of_trait
.trait_ref
.path
.segments
.iter()

View file

@ -37,12 +37,12 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]);
impl<'tcx> LateLintPass<'tcx> for CopyIterator {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
..
}) = item.kind
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& is_copy(cx, ty)
&& let Some(trait_id) = trait_ref.trait_def_id()
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
&& cx.tcx.is_diagnostic_item(sym::Iterator, trait_id)
{
span_lint_and_note(

View file

@ -183,14 +183,14 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex
impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
items: [child],
self_ty,
..
}) = item.kind
&& !cx.tcx.is_automatically_derived(item.owner_id.to_def_id())
&& !item.span.from_expansion()
&& let Some(def_id) = trait_ref.trait_def_id()
&& let Some(def_id) = of_trait.trait_ref.trait_def_id()
&& cx.tcx.is_diagnostic_item(sym::Default, def_id)
&& let impl_item_hir = child.hir_id()
&& let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)

View file

@ -201,10 +201,11 @@ declare_lint_pass!(Derive => [
impl<'tcx> LateLintPass<'tcx> for Derive {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
..
}) = item.kind
{
let trait_ref = &of_trait.trait_ref;
let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
let is_automatically_derived = cx.tcx.is_automatically_derived(item.owner_id.to_def_id());

View file

@ -36,11 +36,11 @@ declare_lint_pass!(EmptyDrop => [EMPTY_DROP]);
impl LateLintPass<'_> for EmptyDrop {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
items: [child],
..
}) = item.kind
&& trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait()
&& of_trait.trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait()
&& let impl_item_hir = child.hir_id()
&& let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
&& let ImplItemKind::Fn(_, b) = &impl_item.kind

View file

@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
);
},
ItemKind::Impl(imp)
if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id())
if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_ref.trait_def_id())
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
&& error_def_id == trait_def_id
&& let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local)

View file

@ -254,10 +254,10 @@ fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Optio
if impl_item.ident.name == sym::fmt
&& let ImplItemKind::Fn(_, body_id) = impl_item.kind
&& let Some(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
..
}) = get_parent_as_impl(cx.tcx, impl_item.hir_id())
&& let Some(did) = trait_ref.trait_def_id()
&& let Some(did) = of_trait.trait_ref.trait_def_id()
&& let Some(name) = cx.tcx.get_diagnostic_name(did)
&& matches!(name, sym::Debug | sym::Display)
{

View file

@ -67,12 +67,12 @@ impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]);
impl<'tcx> LateLintPass<'tcx> for FromOverInto {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(hir_trait_ref),
of_trait: Some(of_trait),
self_ty,
items: [impl_item_ref],
..
}) = item.kind
&& let Some(into_trait_seg) = hir_trait_ref.path.segments.last()
&& let Some(into_trait_seg) = of_trait.trait_ref.path.segments.last()
// `impl Into<target_ty> for self_ty`
&& let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
&& span_is_local(item.span)

View file

@ -54,8 +54,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
if let ImplItemKind::Fn(_, body_id) = impl_item.kind
&& let hir::Node::Item(item) = cx.tcx.parent_hir_node(impl_item.hir_id())
&& let hir::ItemKind::Impl(impl_) = item.kind
&& let hir::Impl { of_trait, .. } = *impl_
&& of_trait.is_none()
&& let hir::Impl { of_trait: None, .. } = impl_
&& let body = cx.tcx.hir_body(body_id)
&& cx.tcx.visibility(cx.tcx.hir_body_owner_def_id(body.id())).is_public()
&& !is_in_test(cx.tcx, impl_item.hir_id())

View file

@ -15,11 +15,11 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored
&& let parent_node = cx.tcx.parent_hir_node(item.hir_id())
&& let Node::Item(parent_item) = parent_node
&& let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
..
}) = &parent_item.kind
&& let Some(did) = trait_item_def_id_of_impl(cx, item.owner_id)
&& !is_from_ignored_trait(trait_ref, ignored_traits)
&& !is_from_ignored_trait(&of_trait.trait_ref, ignored_traits)
{
let mut param_idents_iter = cx.tcx.hir_body_param_idents(body_id);
let mut default_param_idents_iter = cx.tcx.fn_arg_idents(did).iter().copied();

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::implements_trait;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Item, ItemKind, Path, TraitRef};
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::declare_lint_pass;
@ -76,10 +76,10 @@ impl LateLintPass<'_> for ImplHashWithBorrowStrBytes {
/// three of `Hash`, `Borrow<str>` and `Borrow<[u8]>`.
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
if let ItemKind::Impl(imp) = item.kind
&& let Some(TraitRef {path: Path {span, res, ..}, ..}) = imp.of_trait
&& let Some(of_trait) = imp.of_trait
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& let Some(hash_id) = cx.tcx.get_diagnostic_item(sym::Hash)
&& Res::Def(DefKind::Trait, hash_id) == *res
&& Res::Def(DefKind::Trait, hash_id) == of_trait.trait_ref.path.res
&& let Some(borrow_id) = cx.tcx.get_diagnostic_item(sym::Borrow)
// since we are in the `Hash` impl, we don't need to check for that.
// we need only to check for `Borrow<str>` and `Borrow<[u8]>`
@ -89,7 +89,7 @@ impl LateLintPass<'_> for ImplHashWithBorrowStrBytes {
span_lint_and_then(
cx,
IMPL_HASH_BORROW_WITH_STR_AND_BYTES,
*span,
of_trait.trait_ref.path.span,
"the semantics of `Borrow<T>` around `Hash` can't be satisfied when both `Borrow<str>` and `Borrow<[u8]>` are implemented",
|diag| {
diag.note("the `Borrow` semantics require that `Hash` must behave the same for all implementations of Borrow<T>");

View file

@ -45,8 +45,8 @@ declare_lint_pass!(InfallibleTryFrom => [INFALLIBLE_TRY_FROM]);
impl<'tcx> LateLintPass<'tcx> for InfallibleTryFrom {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
let ItemKind::Impl(imp) = item.kind else { return };
let Some(r#trait) = imp.of_trait else { return };
let Some(trait_def_id) = r#trait.trait_def_id() else {
let Some(of_trait) = imp.of_trait else { return };
let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else {
return;
};
if !cx.tcx.is_diagnostic_item(sym::TryFrom, trait_def_id) {

View file

@ -125,8 +125,9 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
if let ItemKind::Impl(imp) = item.kind
&& let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind
&& let Some(trait_ref) = imp.of_trait
&& trait_ref
&& let Some(of_trait) = imp.of_trait
&& of_trait
.trait_ref
.trait_def_id()
.is_some_and(|did| cx.tcx.is_diagnostic_item(sym::IntoIterator, did))
&& !item.span.in_external_macro(cx.sess().source_map())

View file

@ -150,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
} = item.kind
{
check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv);
} else if let ItemKind::Impl(impl_) = item.kind
} else if let ItemKind::Impl(impl_) = &item.kind
&& !item.span.from_expansion()
{
report_extra_impl_lifetimes(cx, impl_);
@ -712,8 +712,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
let mut checker = LifetimeChecker::<middle_nested_filter::All>::new(cx, impl_.generics);
walk_generics(&mut checker, impl_.generics);
if let Some(ref trait_ref) = impl_.of_trait {
walk_trait_ref(&mut checker, trait_ref);
if let Some(of_trait) = impl_.of_trait {
walk_trait_ref(&mut checker, &of_trait.trait_ref);
}
walk_unambig_ty(&mut checker, impl_.self_ty);
for &item in impl_.items {

View file

@ -198,8 +198,8 @@ fn check_struct<'tcx>(
impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
// is this an `impl Debug for X` block?
if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, .. }) = item.kind
&& let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res
if let ItemKind::Impl(Impl { of_trait: Some(of_trait), self_ty, .. }) = item.kind
&& let Res::Def(DefKind::Trait, trait_def_id) = of_trait.trait_ref.path.res
&& let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind
// make sure that the self type is either a struct, an enum or a union
// this prevents ICEs such as when self is a type parameter or a primitive type

View file

@ -61,10 +61,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
if !is_lint_allowed(cx, MISSING_TRAIT_METHODS, item.hir_id())
&& span_is_local(item.span)
&& let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
..
}) = item.kind
&& let Some(trait_id) = trait_ref.trait_def_id()
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
{
let trait_item_ids: DefIdSet = cx
.tcx

View file

@ -778,7 +778,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
if let Node::Item(parent_item) = cx.tcx.parent_hir_node(item.hir_id())
&& let ItemKind::Impl(impl_block) = parent_item.kind
&& let Some(of_trait) = impl_block.of_trait
&& let Some(trait_id) = of_trait.trait_def_id()
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
{
// Replace all instances of `<Self as Trait>::AssocType` with the
// unit type and check again. If the result is the same then the

View file

@ -83,10 +83,10 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
if !item.span.in_external_macro(cx.tcx.sess.source_map())
&& let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send)
&& let ItemKind::Impl(hir_impl) = &item.kind
&& let Some(trait_ref) = &hir_impl.of_trait
&& let Some(trait_id) = trait_ref.trait_def_id()
&& let Some(of_trait) = &hir_impl.of_trait
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
&& send_trait == trait_id
&& hir_impl.polarity == ImplPolarity::Positive
&& of_trait.polarity == ImplPolarity::Positive
&& let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
&& let self_ty = ty_trait_ref.instantiate_identity().self_ty()
&& let ty::Adt(adt_def, impl_trait_args) = self_ty.kind()

View file

@ -183,7 +183,7 @@ fn in_impl<'tcx>(
&& let item = cx.tcx.hir_expect_item(impl_def_id.expect_local())
&& let ItemKind::Impl(item) = &item.kind
&& let Some(of_trait) = &item.of_trait
&& let Some(seg) = of_trait.path.segments.last()
&& let Some(seg) = of_trait.trait_ref.path.segments.last()
&& let Res::Def(_, trait_id) = seg.res
&& trait_id == bin_op
&& let Some(generic_args) = seg.args

View file

@ -34,15 +34,15 @@ declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]);
impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
items: impl_items,
..
}) = item.kind
&& !cx.tcx.is_automatically_derived(item.owner_id.to_def_id())
&& let Some(eq_trait) = cx.tcx.lang_items().eq_trait()
&& trait_ref.path.res.def_id() == eq_trait
&& of_trait.trait_ref.path.res.def_id() == eq_trait
{
for impl_item in *impl_items {
for impl_item in impl_items {
if cx.tcx.item_name(impl_item.owner_id) == sym::ne {
span_lint_hir(
cx,

View file

@ -68,9 +68,9 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
let existing_name = map.get_mut(res).unwrap();
match of_trait {
Some(trait_ref) => {
Some(of_trait) => {
let mut methods_in_trait: BTreeSet<Symbol> = if let Node::TraitRef(TraitRef { path, .. }) =
cx.tcx.hir_node(trait_ref.hir_ref_id)
cx.tcx.hir_node(of_trait.trait_ref.hir_ref_id)
&& let Res::Def(DefKind::Trait, did) = path.res
{
// FIXME: if

View file

@ -26,16 +26,16 @@ declare_lint_pass!(SerdeApi => [SERDE_API_MISUSE]);
impl<'tcx> LateLintPass<'tcx> for SerdeApi {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
items,
..
}) = item.kind
{
let did = trait_ref.path.res.def_id();
let did = of_trait.trait_ref.path.res.def_id();
if paths::SERDE_DE_VISITOR.matches(cx, did) {
let mut seen_str = None;
let mut seen_string = None;
for item in *items {
for item in items {
match cx.tcx.item_name(item.owner_id) {
sym::visit_str => seen_str = Some(cx.tcx.def_span(item.owner_id)),
sym::visit_string => seen_string = Some(cx.tcx.def_span(item.owner_id)),

View file

@ -48,10 +48,10 @@ declare_lint_pass!(ToStringTraitImpl => [TO_STRING_TRAIT_IMPL]);
impl<'tcx> LateLintPass<'tcx> for ToStringTraitImpl {
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'tcx>) {
if let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
..
}) = it.kind
&& let Some(trait_did) = trait_ref.trait_def_id()
&& let Some(trait_did) = of_trait.trait_ref.trait_def_id()
&& cx.tcx.is_diagnostic_item(sym::ToString, trait_did)
{
span_lint_and_help(

View file

@ -137,9 +137,9 @@ fn get_impl_trait_def_id(cx: &LateContext<'_>, method_def_id: LocalDefId) -> Opt
// We exclude `impl` blocks generated from rustc's proc macros.
&& !cx.tcx.is_automatically_derived(owner_id.to_def_id())
// It is a implementation of a trait.
&& let Some(trait_) = impl_.of_trait
&& let Some(of_trait) = impl_.of_trait
{
trait_.trait_def_id()
of_trait.trait_ref.trait_def_id()
} else {
None
}
@ -242,8 +242,8 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local
// We exclude `impl` blocks generated from rustc's proc macros.
&& !cx.tcx.is_automatically_derived(owner_id.to_def_id())
// It is a implementation of a trait.
&& let Some(trait_) = impl_.of_trait
&& let Some(trait_def_id) = trait_.trait_def_id()
&& let Some(of_trait) = impl_.of_trait
&& let Some(trait_def_id) = of_trait.trait_ref.trait_def_id()
// The trait is `ToString`.
&& cx.tcx.is_diagnostic_item(sym::ToString, trait_def_id)
{

View file

@ -8,7 +8,7 @@ use clippy_utils::source::walk_span_to_context;
use clippy_utils::visitors::{Descend, for_each_expr};
use hir::HirId;
use rustc_hir as hir;
use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
use rustc_hir::{Block, BlockCheckMode, Impl, ItemKind, Node, UnsafeSource};
use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass;
@ -204,7 +204,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
let item_has_safety_comment = item_has_safety_comment(cx, item);
match (&item.kind, item_has_safety_comment) {
// lint unsafe impl without safety comment
(ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety.is_unsafe() => {
(ItemKind::Impl(Impl { of_trait: Some(of_trait), .. }), HasSafetyComment::No) if of_trait.safety.is_unsafe() => {
if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id())
&& !is_unsafe_from_proc_macro(cx, item.span)
{
@ -228,7 +228,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
}
},
// lint safe impl with unnecessary safety comment
(ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety.is_safe() => {
(ItemKind::Impl(Impl { of_trait: Some(of_trait), .. }), HasSafetyComment::Yes(pos)) if of_trait.safety.is_safe() => {
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
let (span, help_span) = mk_spans(pos);

View file

@ -347,10 +347,10 @@ impl<'tcx> LateLintPass<'tcx> for Write {
fn is_debug_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
if let ItemKind::Impl(Impl {
of_trait: Some(trait_ref),
of_trait: Some(of_trait),
..
}) = &item.kind
&& let Some(trait_id) = trait_ref.trait_def_id()
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
{
cx.tcx.is_diagnostic_item(sym::Debug, trait_id)
} else {

View file

@ -19,8 +19,8 @@ use rustc_ast::token::CommentKind;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl,
ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
ImplItem, ImplItemKind, TraitImplHeader, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path,
QPath, Safety, TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
};
use rustc_lint::{EarlyContext, LateContext, LintContext};
use rustc_middle::ty::TyCtxt;
@ -254,7 +254,7 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) {
ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")),
ItemKind::Trait(_, _, Safety::Unsafe, ..)
| ItemKind::Impl(Impl {
safety: Safety::Unsafe, ..
of_trait: Some(TraitImplHeader { safety: Safety::Unsafe, .. }), ..
}) => (Pat::Str("unsafe"), Pat::Str("}")),
ItemKind::Trait(_, IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")),
ItemKind::Trait(..) => (Pat::Str("trait"), Pat::Str("}")),

View file

@ -528,8 +528,9 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>
pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, owner: OwnerId) -> Option<&'tcx TraitRef<'tcx>> {
if let Node::Item(item) = cx.tcx.hir_node(cx.tcx.hir_owner_parent(owner))
&& let ItemKind::Impl(impl_) = &item.kind
&& let Some(of_trait) = impl_.of_trait
{
return impl_.of_trait.as_ref();
return Some(&of_trait.trait_ref);
}
None
}

View file

@ -460,7 +460,8 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
}
fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
if let ItemKind::Impl(i) = &self.cx.tcx.hir_item(id).kind
&& i.safety.is_unsafe()
&& let Some(of_trait) = i.of_trait
&& of_trait.safety.is_unsafe()
{
ControlFlow::Break(())
} else {