mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Propagate TraitImplHeader to hir
This commit is contained in:
@@ -360,75 +360,30 @@ fn lower_item_kind(
|
||||
// lifetime to be added, but rather a reference to a
|
||||
// parent lifetime.
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
let (generics, (of_trait, lowered_ty)) =
|
||||
self.lower_generics(ast_generics, id, itctx, |this| {
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
asyncness: BoundAsyncness::Normal,
|
||||
// we don't use this in bound lowering
|
||||
polarity: BoundPolarity::Positive,
|
||||
};
|
||||
|
||||
let trait_ref = of_trait.as_ref().map(|of_trait| {
|
||||
this.lower_trait_ref(
|
||||
modifiers,
|
||||
&of_trait.trait_ref,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||
)
|
||||
});
|
||||
let of_trait = of_trait
|
||||
.as_deref()
|
||||
.map(|of_trait| this.lower_trait_impl_header(of_trait));
|
||||
|
||||
let lowered_ty = this.lower_ty(
|
||||
ty,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
|
||||
);
|
||||
|
||||
(trait_ref, lowered_ty)
|
||||
(of_trait, lowered_ty)
|
||||
});
|
||||
|
||||
let new_impl_items = self
|
||||
.arena
|
||||
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
|
||||
|
||||
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
||||
// to not cause an assertion failure inside the `lower_defaultness` function.
|
||||
let has_val = true;
|
||||
let (constness, safety, polarity, defaultness, defaultness_span) = match *of_trait {
|
||||
Some(box TraitImplHeader {
|
||||
constness,
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
trait_ref: _,
|
||||
}) => {
|
||||
let constness = self.lower_constness(constness);
|
||||
let safety = self.lower_safety(safety, hir::Safety::Safe);
|
||||
let polarity = match polarity {
|
||||
ImplPolarity::Positive => ImplPolarity::Positive,
|
||||
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
|
||||
};
|
||||
let (defaultness, defaultness_span) =
|
||||
self.lower_defaultness(defaultness, has_val);
|
||||
(constness, safety, polarity, defaultness, defaultness_span)
|
||||
}
|
||||
None => (
|
||||
hir::Constness::NotConst,
|
||||
hir::Safety::Safe,
|
||||
ImplPolarity::Positive,
|
||||
hir::Defaultness::Final,
|
||||
None,
|
||||
),
|
||||
};
|
||||
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
||||
constness,
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
defaultness_span,
|
||||
hir::ItemKind::Impl(hir::Impl {
|
||||
generics,
|
||||
of_trait: trait_ref,
|
||||
of_trait,
|
||||
self_ty: lowered_ty,
|
||||
items: new_impl_items,
|
||||
}))
|
||||
})
|
||||
}
|
||||
ItemKind::Trait(box Trait {
|
||||
constness,
|
||||
@@ -999,6 +954,44 @@ pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Exp
|
||||
self.expr(span, hir::ExprKind::Err(guar))
|
||||
}
|
||||
|
||||
fn lower_trait_impl_header(
|
||||
&mut self,
|
||||
trait_impl_header: &TraitImplHeader,
|
||||
) -> &'hir hir::TraitImplHeader<'hir> {
|
||||
let TraitImplHeader { constness, safety, polarity, defaultness, ref trait_ref } =
|
||||
*trait_impl_header;
|
||||
let constness = self.lower_constness(constness);
|
||||
let safety = self.lower_safety(safety, hir::Safety::Safe);
|
||||
let polarity = match polarity {
|
||||
ImplPolarity::Positive => ImplPolarity::Positive,
|
||||
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
|
||||
};
|
||||
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
||||
// to not cause an assertion failure inside the `lower_defaultness` function.
|
||||
let has_val = true;
|
||||
let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
asyncness: BoundAsyncness::Normal,
|
||||
// we don't use this in bound lowering
|
||||
polarity: BoundPolarity::Positive,
|
||||
};
|
||||
let trait_ref = self.lower_trait_ref(
|
||||
modifiers,
|
||||
trait_ref,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||
);
|
||||
|
||||
self.arena.alloc(hir::TraitImplHeader {
|
||||
constness,
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
defaultness_span,
|
||||
trait_ref,
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_impl_item(
|
||||
&mut self,
|
||||
i: &AssocItem,
|
||||
|
||||
@@ -4194,7 +4194,7 @@ pub fn is_struct_or_union(&self) -> bool {
|
||||
expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
|
||||
ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds);
|
||||
|
||||
expect_impl, &'hir Impl<'hir>, ItemKind::Impl(imp), imp;
|
||||
expect_impl, &Impl<'hir>, ItemKind::Impl(imp), imp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4372,7 +4372,7 @@ pub enum ItemKind<'hir> {
|
||||
TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
|
||||
|
||||
/// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
|
||||
Impl(&'hir Impl<'hir>),
|
||||
Impl(Impl<'hir>),
|
||||
}
|
||||
|
||||
/// Represents an impl block declaration.
|
||||
@@ -4381,6 +4381,14 @@ pub enum ItemKind<'hir> {
|
||||
/// Refer to [`ImplItem`] for an associated item within an impl block.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Impl<'hir> {
|
||||
pub generics: &'hir Generics<'hir>,
|
||||
pub of_trait: Option<&'hir TraitImplHeader<'hir>>,
|
||||
pub self_ty: &'hir Ty<'hir>,
|
||||
pub items: &'hir [ImplItemId],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct TraitImplHeader<'hir> {
|
||||
pub constness: Constness,
|
||||
pub safety: Safety,
|
||||
pub polarity: ImplPolarity,
|
||||
@@ -4388,13 +4396,7 @@ pub struct Impl<'hir> {
|
||||
// We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
|
||||
// decoding as `Span`s cannot be decoded when a `Session` is not available.
|
||||
pub defaultness_span: Option<Span>,
|
||||
pub generics: &'hir Generics<'hir>,
|
||||
|
||||
/// The trait being implemented, if any.
|
||||
pub of_trait: Option<TraitRef<'hir>>,
|
||||
|
||||
pub self_ty: &'hir Ty<'hir>,
|
||||
pub items: &'hir [ImplItemId],
|
||||
pub trait_ref: TraitRef<'hir>,
|
||||
}
|
||||
|
||||
impl ItemKind<'_> {
|
||||
@@ -4756,8 +4758,8 @@ pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> {
|
||||
/// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`.
|
||||
pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
|
||||
if let Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) = self
|
||||
&& let Some(trait_ref) = impl_block.of_trait
|
||||
&& let Some(trait_id) = trait_ref.trait_def_id()
|
||||
&& let Some(of_trait) = impl_block.of_trait
|
||||
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
|
||||
&& trait_id == trait_def_id
|
||||
{
|
||||
Some(impl_block)
|
||||
@@ -4952,7 +4954,7 @@ mod size_asserts {
|
||||
static_assert_size!(GenericArg<'_>, 16);
|
||||
static_assert_size!(GenericBound<'_>, 64);
|
||||
static_assert_size!(Generics<'_>, 56);
|
||||
static_assert_size!(Impl<'_>, 80);
|
||||
static_assert_size!(Impl<'_>, 40);
|
||||
static_assert_size!(ImplItem<'_>, 96);
|
||||
static_assert_size!(ImplItemKind<'_>, 40);
|
||||
static_assert_size!(Item<'_>, 88);
|
||||
@@ -4967,6 +4969,7 @@ mod size_asserts {
|
||||
static_assert_size!(Res, 12);
|
||||
static_assert_size!(Stmt<'_>, 32);
|
||||
static_assert_size!(StmtKind<'_>, 16);
|
||||
static_assert_size!(TraitImplHeader<'_>, 48);
|
||||
static_assert_size!(TraitItem<'_>, 88);
|
||||
static_assert_size!(TraitItemKind<'_>, 48);
|
||||
static_assert_size!(Ty<'_>, 48);
|
||||
|
||||
@@ -590,21 +590,21 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
try_visit!(visitor.visit_enum_def(enum_definition));
|
||||
}
|
||||
ItemKind::Impl(Impl {
|
||||
constness: _,
|
||||
safety: _,
|
||||
defaultness: _,
|
||||
polarity: _,
|
||||
defaultness_span: _,
|
||||
generics,
|
||||
of_trait,
|
||||
self_ty,
|
||||
items,
|
||||
}) => {
|
||||
ItemKind::Impl(Impl { generics, of_trait, self_ty, items }) => {
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
visit_opt!(visitor, visit_trait_ref, of_trait);
|
||||
if let Some(TraitImplHeader {
|
||||
constness: _,
|
||||
safety: _,
|
||||
polarity: _,
|
||||
defaultness: _,
|
||||
defaultness_span: _,
|
||||
trait_ref,
|
||||
}) = of_trait
|
||||
{
|
||||
try_visit!(visitor.visit_trait_ref(trait_ref));
|
||||
}
|
||||
try_visit!(visitor.visit_ty_unambig(self_ty));
|
||||
walk_list!(visitor, visit_impl_item_ref, *items);
|
||||
walk_list!(visitor, visit_impl_item_ref, items);
|
||||
}
|
||||
ItemKind::Struct(ident, ref generics, ref struct_definition)
|
||||
| ItemKind::Union(ident, ref generics, ref struct_definition) => {
|
||||
|
||||
@@ -244,48 +244,48 @@ pub(super) fn check_item<'tcx>(
|
||||
//
|
||||
// won't be allowed unless there's an *explicit* implementation of `Send`
|
||||
// for `T`
|
||||
hir::ItemKind::Impl(impl_) => {
|
||||
let header = tcx.impl_trait_header(def_id);
|
||||
let is_auto = header
|
||||
.is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id));
|
||||
|
||||
hir::ItemKind::Impl(ref impl_) => {
|
||||
crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
|
||||
let mut res = Ok(());
|
||||
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
|
||||
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
|
||||
res = Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(sp, "impls of auto traits cannot be default")
|
||||
.with_span_labels(impl_.defaultness_span, "default because of this")
|
||||
.with_span_label(sp, "auto trait")
|
||||
.emit());
|
||||
}
|
||||
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
|
||||
match header.map(|h| h.polarity) {
|
||||
// `None` means this is an inherent impl
|
||||
Some(ty::ImplPolarity::Positive) | None => {
|
||||
res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
|
||||
}
|
||||
Some(ty::ImplPolarity::Negative) => {
|
||||
let ast::ImplPolarity::Negative(span) = impl_.polarity else {
|
||||
bug!("impl_polarity query disagrees with impl's polarity in HIR");
|
||||
};
|
||||
// FIXME(#27579): what amount of WF checking do we need for neg impls?
|
||||
if let hir::Defaultness::Default { .. } = impl_.defaultness {
|
||||
let mut spans = vec![span];
|
||||
spans.extend(impl_.defaultness_span);
|
||||
res = Err(struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
spans,
|
||||
E0750,
|
||||
"negative impls cannot be default impls"
|
||||
)
|
||||
if let Some(of_trait) = impl_.of_trait {
|
||||
let header = tcx.impl_trait_header(def_id).unwrap();
|
||||
let is_auto = tcx.trait_is_auto(header.trait_ref.skip_binder().def_id);
|
||||
if let (hir::Defaultness::Default { .. }, true) = (of_trait.defaultness, is_auto) {
|
||||
let sp = of_trait.trait_ref.path.span;
|
||||
res = Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(sp, "impls of auto traits cannot be default")
|
||||
.with_span_labels(of_trait.defaultness_span, "default because of this")
|
||||
.with_span_label(sp, "auto trait")
|
||||
.emit());
|
||||
}
|
||||
match header.polarity {
|
||||
ty::ImplPolarity::Positive => {
|
||||
res = res.and(check_impl(tcx, item, impl_));
|
||||
}
|
||||
ty::ImplPolarity::Negative => {
|
||||
let ast::ImplPolarity::Negative(span) = of_trait.polarity else {
|
||||
bug!("impl_polarity query disagrees with impl's polarity in HIR");
|
||||
};
|
||||
// FIXME(#27579): what amount of WF checking do we need for neg impls?
|
||||
if let hir::Defaultness::Default { .. } = of_trait.defaultness {
|
||||
let mut spans = vec![span];
|
||||
spans.extend(of_trait.defaultness_span);
|
||||
res = Err(struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
spans,
|
||||
E0750,
|
||||
"negative impls cannot be default impls"
|
||||
)
|
||||
.emit());
|
||||
}
|
||||
}
|
||||
ty::ImplPolarity::Reservation => {
|
||||
// FIXME: what amount of WF checking do we need for reservation impls?
|
||||
}
|
||||
}
|
||||
Some(ty::ImplPolarity::Reservation) => {
|
||||
// FIXME: what amount of WF checking do we need for reservation impls?
|
||||
}
|
||||
} else {
|
||||
res = res.and(check_impl(tcx, item, impl_));
|
||||
}
|
||||
res
|
||||
}
|
||||
@@ -1258,16 +1258,15 @@ pub(crate) fn check_const_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<()
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))]
|
||||
#[instrument(level = "debug", skip(tcx, impl_))]
|
||||
fn check_impl<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: &'tcx hir::Item<'tcx>,
|
||||
hir_self_ty: &hir::Ty<'_>,
|
||||
hir_trait_ref: &Option<hir::TraitRef<'_>>,
|
||||
impl_: &hir::Impl<'_>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
|
||||
match hir_trait_ref {
|
||||
Some(hir_trait_ref) => {
|
||||
match impl_.of_trait {
|
||||
Some(of_trait) => {
|
||||
// `#[rustc_reservation_impl]` impls are not real impls and
|
||||
// therefore don't need to be WF (the trait's `Self: Trait` predicate
|
||||
// won't hold).
|
||||
@@ -1275,7 +1274,7 @@ fn check_impl<'tcx>(
|
||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||
// other `Foo` impls are incoherent.
|
||||
tcx.ensure_ok().coherent_trait(trait_ref.def_id)?;
|
||||
let trait_span = hir_trait_ref.path.span;
|
||||
let trait_span = of_trait.trait_ref.path.span;
|
||||
let trait_ref = wfcx.deeply_normalize(
|
||||
trait_span,
|
||||
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
||||
@@ -1299,12 +1298,12 @@ fn check_impl<'tcx>(
|
||||
if let Some(pred) = obligation.predicate.as_trait_clause()
|
||||
&& pred.skip_binder().self_ty() == trait_ref.self_ty()
|
||||
{
|
||||
obligation.cause.span = hir_self_ty.span;
|
||||
obligation.cause.span = impl_.self_ty.span;
|
||||
}
|
||||
if let Some(pred) = obligation.predicate.as_projection_clause()
|
||||
&& pred.skip_binder().self_ty() == trait_ref.self_ty()
|
||||
{
|
||||
obligation.cause.span = hir_self_ty.span;
|
||||
obligation.cause.span = impl_.self_ty.span;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1321,7 +1320,7 @@ fn check_impl<'tcx>(
|
||||
wfcx.register_obligation(Obligation::new(
|
||||
tcx,
|
||||
ObligationCause::new(
|
||||
hir_self_ty.span,
|
||||
impl_.self_ty.span,
|
||||
wfcx.body_def_id,
|
||||
ObligationCauseCode::WellFormed(None),
|
||||
),
|
||||
@@ -1342,7 +1341,7 @@ fn check_impl<'tcx>(
|
||||
self_ty,
|
||||
);
|
||||
wfcx.register_wf_obligation(
|
||||
hir_self_ty.span,
|
||||
impl_.self_ty.span,
|
||||
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
||||
self_ty.into(),
|
||||
);
|
||||
|
||||
@@ -531,8 +531,10 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
||||
}));
|
||||
} else if diff_fields.len() > 1 {
|
||||
let item = tcx.hir_expect_item(impl_did);
|
||||
let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(t), .. }) = &item.kind {
|
||||
t.path.span
|
||||
let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) =
|
||||
&item.kind
|
||||
{
|
||||
of_trait.trait_ref.path.span
|
||||
} else {
|
||||
tcx.def_span(impl_did)
|
||||
};
|
||||
|
||||
@@ -384,7 +384,7 @@ fn emit_orphan_check_error<'tcx>(
|
||||
traits::OrphanCheckErr::NonLocalInputType(tys) => {
|
||||
let item = tcx.hir_expect_item(impl_def_id);
|
||||
let impl_ = item.expect_impl();
|
||||
let hir_trait_ref = impl_.of_trait.as_ref().unwrap();
|
||||
let of_trait = impl_.of_trait.unwrap();
|
||||
|
||||
let span = tcx.def_span(impl_def_id);
|
||||
let mut diag = tcx.dcx().create_err(match trait_ref.self_ty().kind() {
|
||||
@@ -401,7 +401,7 @@ fn emit_orphan_check_error<'tcx>(
|
||||
impl_.self_ty.span
|
||||
} else {
|
||||
// Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
|
||||
hir_trait_ref.path.span
|
||||
of_trait.trait_ref.path.span
|
||||
};
|
||||
|
||||
ty = tcx.erase_regions(ty);
|
||||
|
||||
@@ -1295,18 +1295,22 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let item = tcx.hir_expect_item(def_id);
|
||||
let impl_ = item.expect_impl();
|
||||
impl_.of_trait.as_ref().map(|ast_trait_ref| {
|
||||
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
|
||||
if is_rustc_reservation && impl_.of_trait.is_none() {
|
||||
tcx.dcx().span_err(item.span, "reservation impls can't be inherent");
|
||||
}
|
||||
impl_.of_trait.map(|of_trait| {
|
||||
let selfty = tcx.type_of(def_id).instantiate_identity();
|
||||
|
||||
check_impl_constness(tcx, impl_.constness, ast_trait_ref);
|
||||
check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref);
|
||||
|
||||
let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
|
||||
let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty);
|
||||
|
||||
ty::ImplTraitHeader {
|
||||
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
||||
safety: impl_.safety,
|
||||
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
|
||||
constness: impl_.constness,
|
||||
safety: of_trait.safety,
|
||||
polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation),
|
||||
constness: of_trait.constness,
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1350,26 +1354,18 @@ fn check_impl_constness(
|
||||
|
||||
fn polarity_of_impl(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
impl_: &hir::Impl<'_>,
|
||||
span: Span,
|
||||
of_trait: &hir::TraitImplHeader<'_>,
|
||||
is_rustc_reservation: bool,
|
||||
) -> ty::ImplPolarity {
|
||||
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
|
||||
match &impl_ {
|
||||
hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
|
||||
match of_trait.polarity {
|
||||
hir::ImplPolarity::Negative(span) => {
|
||||
if is_rustc_reservation {
|
||||
let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
|
||||
let span = span.to(of_trait.trait_ref.path.span);
|
||||
tcx.dcx().span_err(span, "reservation impls can't be negative");
|
||||
}
|
||||
ty::ImplPolarity::Negative
|
||||
}
|
||||
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
|
||||
if is_rustc_reservation {
|
||||
tcx.dcx().span_err(span, "reservation impls can't be inherent");
|
||||
}
|
||||
ty::ImplPolarity::Positive
|
||||
}
|
||||
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
|
||||
hir::ImplPolarity::Positive => {
|
||||
if is_rustc_reservation {
|
||||
ty::ImplPolarity::Reservation
|
||||
} else {
|
||||
|
||||
@@ -158,7 +158,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
if let Node::Item(item) = node {
|
||||
match item.kind {
|
||||
ItemKind::Impl(impl_) => {
|
||||
if impl_.defaultness.is_default() {
|
||||
if let Some(of_trait) = impl_.of_trait
|
||||
&& of_trait.defaultness.is_default()
|
||||
{
|
||||
is_default_impl_trait = tcx
|
||||
.impl_trait_ref(def_id)
|
||||
.map(|t| ty::Binder::dummy(t.instantiate_identity()));
|
||||
|
||||
@@ -604,13 +604,10 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
match &item.kind {
|
||||
hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
|
||||
if let Some(of_trait) = of_trait {
|
||||
self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
if let hir::ItemKind::Impl(impl_) = item.kind
|
||||
&& let Some(of_trait) = impl_.of_trait
|
||||
{
|
||||
self.record_late_bound_vars(of_trait.trait_ref.hir_ref_id, Vec::default());
|
||||
}
|
||||
match item.kind {
|
||||
hir::ItemKind::Fn { generics, .. } => {
|
||||
@@ -636,7 +633,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
| hir::ItemKind::Union(_, generics, _)
|
||||
| hir::ItemKind::Trait(_, _, _, _, generics, ..)
|
||||
| hir::ItemKind::TraitAlias(_, generics, ..)
|
||||
| hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
|
||||
| hir::ItemKind::Impl(hir::Impl { generics, .. }) => {
|
||||
// These kinds of items have only early-bound lifetime parameters.
|
||||
self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
|
||||
}
|
||||
@@ -2106,7 +2103,7 @@ fn try_append_return_type_notation_params(
|
||||
// If we have a self type alias (in an impl), try to resolve an
|
||||
// associated item from one of the supertraits of the impl's trait.
|
||||
Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => {
|
||||
let hir::ItemKind::Impl(hir::Impl { of_trait: Some(trait_ref), .. }) = self
|
||||
let hir::ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = self
|
||||
.tcx
|
||||
.hir_node_by_def_id(impl_def_id.expect_local())
|
||||
.expect_item()
|
||||
@@ -2114,7 +2111,7 @@ fn try_append_return_type_notation_params(
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(trait_def_id) = trait_ref.trait_def_id() else {
|
||||
let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else {
|
||||
return;
|
||||
};
|
||||
let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars(
|
||||
|
||||
@@ -251,7 +251,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
|
||||
.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: () });
|
||||
Ty::new_error(tcx, guar)
|
||||
}
|
||||
_ => icx.lower_ty(*self_ty),
|
||||
_ => icx.lower_ty(self_ty),
|
||||
},
|
||||
ItemKind::Fn { .. } => {
|
||||
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
|
||||
@@ -147,7 +147,11 @@ fn is_in_trait_impl(&self) -> bool {
|
||||
let hir::Node::Item(hir::Item {
|
||||
kind:
|
||||
hir::ItemKind::Impl(hir::Impl {
|
||||
of_trait: Some(hir::TraitRef { hir_ref_id: id_in_of_trait, .. }),
|
||||
of_trait:
|
||||
Some(hir::TraitImplHeader {
|
||||
trait_ref: hir::TraitRef { hir_ref_id: id_in_of_trait, .. },
|
||||
..
|
||||
}),
|
||||
..
|
||||
}),
|
||||
..
|
||||
|
||||
@@ -200,7 +200,7 @@ fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
|
||||
}) = tcx.hir_node_by_def_id(parent_id)
|
||||
&& self_ty.hir_id == impl_self_ty.hir_id
|
||||
{
|
||||
let Some(of_trait_ref) = of_trait else {
|
||||
let Some(of_trait) = of_trait else {
|
||||
diag.span_suggestion_verbose(
|
||||
impl_self_ty.span.shrink_to_hi(),
|
||||
"you might have intended to implement this trait for a given type",
|
||||
@@ -209,10 +209,10 @@ fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
|
||||
);
|
||||
return;
|
||||
};
|
||||
if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
|
||||
if !of_trait.trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
|
||||
return;
|
||||
}
|
||||
let of_trait_span = of_trait_ref.path.span;
|
||||
let of_trait_span = of_trait.trait_ref.path.span;
|
||||
// make sure that we are not calling unwrap to abort during the compilation
|
||||
let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else {
|
||||
return;
|
||||
|
||||
@@ -2732,7 +2732,7 @@ pub(super) fn suggest_trait_fn_ty_for_impl_fn_infer(
|
||||
};
|
||||
let i = tcx.parent_hir_node(fn_hir_id).expect_item().expect_impl();
|
||||
|
||||
let trait_ref = self.lower_impl_trait_ref(i.of_trait.as_ref()?, self.lower_ty(i.self_ty));
|
||||
let trait_ref = self.lower_impl_trait_ref(&i.of_trait?.trait_ref, self.lower_ty(i.self_ty));
|
||||
|
||||
let assoc = tcx.associated_items(trait_ref.def_id).find_by_ident_and_kind(
|
||||
tcx,
|
||||
|
||||
@@ -154,8 +154,9 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
|
||||
hir::ItemKind::TyAlias(_, _, ty)
|
||||
| hir::ItemKind::Static(_, _, ty, _)
|
||||
| hir::ItemKind::Const(_, _, ty, _) => vec![ty],
|
||||
hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
|
||||
Some(t) => t
|
||||
hir::ItemKind::Impl(impl_) => match impl_.of_trait {
|
||||
Some(of_trait) => of_trait
|
||||
.trait_ref
|
||||
.path
|
||||
.segments
|
||||
.last()
|
||||
|
||||
@@ -690,39 +690,44 @@ fn print_item(&mut self, item: &hir::Item<'_>) {
|
||||
let (cb, ib) = self.head("union");
|
||||
self.print_struct(ident.name, generics, struct_def, item.span, true, cb, ib);
|
||||
}
|
||||
hir::ItemKind::Impl(&hir::Impl {
|
||||
constness,
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
defaultness_span: _,
|
||||
generics,
|
||||
ref of_trait,
|
||||
self_ty,
|
||||
items,
|
||||
}) => {
|
||||
hir::ItemKind::Impl(hir::Impl { generics, of_trait, self_ty, items }) => {
|
||||
let (cb, ib) = self.head("");
|
||||
self.print_defaultness(defaultness);
|
||||
self.print_safety(safety);
|
||||
self.word_nbsp("impl");
|
||||
|
||||
if let hir::Constness::Const = constness {
|
||||
self.word_nbsp("const");
|
||||
}
|
||||
let impl_generics = |this: &mut Self| {
|
||||
this.word_nbsp("impl");
|
||||
if !generics.params.is_empty() {
|
||||
this.print_generic_params(generics.params);
|
||||
this.space();
|
||||
}
|
||||
};
|
||||
|
||||
if !generics.params.is_empty() {
|
||||
self.print_generic_params(generics.params);
|
||||
self.space();
|
||||
}
|
||||
match of_trait {
|
||||
None => impl_generics(self),
|
||||
Some(&hir::TraitImplHeader {
|
||||
constness,
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
defaultness_span: _,
|
||||
ref trait_ref,
|
||||
}) => {
|
||||
self.print_defaultness(defaultness);
|
||||
self.print_safety(safety);
|
||||
|
||||
if let hir::ImplPolarity::Negative(_) = polarity {
|
||||
self.word("!");
|
||||
}
|
||||
impl_generics(self);
|
||||
|
||||
if let Some(t) = of_trait {
|
||||
self.print_trait_ref(t);
|
||||
self.space();
|
||||
self.word_space("for");
|
||||
if let hir::Constness::Const = constness {
|
||||
self.word_nbsp("const");
|
||||
}
|
||||
|
||||
if let hir::ImplPolarity::Negative(_) = polarity {
|
||||
self.word("!");
|
||||
}
|
||||
|
||||
self.print_trait_ref(trait_ref);
|
||||
self.space();
|
||||
self.word_space("for");
|
||||
}
|
||||
}
|
||||
|
||||
self.print_type(self_ty);
|
||||
|
||||
@@ -936,7 +936,7 @@ fn can_add_return_type(&self, fn_id: LocalDefId) -> bool {
|
||||
Node::ImplItem(item) => {
|
||||
// If it doesn't impl a trait, we can add a return type
|
||||
let Node::Item(&hir::Item {
|
||||
kind: hir::ItemKind::Impl(&hir::Impl { of_trait, .. }),
|
||||
kind: hir::ItemKind::Impl(hir::Impl { of_trait, .. }),
|
||||
..
|
||||
}) = self.tcx.parent_hir_node(item.hir_id())
|
||||
else {
|
||||
|
||||
@@ -1103,7 +1103,7 @@ fn report_no_match_method_error(
|
||||
self_ty.span.ctxt().outer_expn_data().kind,
|
||||
ExpnKind::Macro(MacroKind::Derive, _)
|
||||
) || matches!(
|
||||
of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind),
|
||||
of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind),
|
||||
Some(ExpnKind::Macro(MacroKind::Derive, _))
|
||||
) =>
|
||||
{
|
||||
@@ -1165,13 +1165,13 @@ fn report_no_match_method_error(
|
||||
entry.0.insert(cause_span);
|
||||
entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
|
||||
} else {
|
||||
if let Some(trait_ref) = of_trait {
|
||||
entry.0.insert(trait_ref.path.span);
|
||||
if let Some(of_trait) = of_trait {
|
||||
entry.0.insert(of_trait.trait_ref.path.span);
|
||||
}
|
||||
entry.0.insert(self_ty.span);
|
||||
};
|
||||
if let Some(trait_ref) = of_trait {
|
||||
entry.1.insert((trait_ref.path.span, ""));
|
||||
if let Some(of_trait) = of_trait {
|
||||
entry.1.insert((of_trait.trait_ref.path.span, ""));
|
||||
}
|
||||
entry.1.insert((self_ty.span, ""));
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||
// `Deref` is being implemented for `t`
|
||||
if let hir::ItemKind::Impl(impl_) = item.kind
|
||||
// the trait is a `Deref` implementation
|
||||
&& let Some(trait_) = &impl_.of_trait
|
||||
&& let Some(did) = trait_.trait_def_id()
|
||||
&& let Some(of_trait) = &impl_.of_trait
|
||||
&& let Some(did) = of_trait.trait_ref.trait_def_id()
|
||||
&& tcx.is_lang_item(did, LangItem::Deref)
|
||||
// the self type is `dyn t_principal`
|
||||
&& let self_ty = tcx.type_of(item.owner_id).instantiate_identity()
|
||||
|
||||
@@ -582,8 +582,8 @@ fn diagnostic_outside_of_impl<'cx>(
|
||||
for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) {
|
||||
debug!(?parent);
|
||||
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) = parent
|
||||
&& let hir::Impl { of_trait: Some(of_trait), .. } = impl_
|
||||
&& let Some(def_id) = of_trait.trait_def_id()
|
||||
&& let Some(of_trait) = impl_.of_trait
|
||||
&& let Some(def_id) = of_trait.trait_ref.trait_def_id()
|
||||
&& let Some(name) = cx.tcx.get_diagnostic_name(def_id)
|
||||
&& matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
|
||||
{
|
||||
|
||||
@@ -129,8 +129,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
// of the `impl` definition
|
||||
let mut collector = PathCollector { paths: Vec::new() };
|
||||
collector.visit_ty_unambig(&impl_.self_ty);
|
||||
if let Some(of_trait) = &impl_.of_trait {
|
||||
collector.visit_trait_ref(of_trait);
|
||||
if let Some(of_trait) = impl_.of_trait {
|
||||
collector.visit_trait_ref(&of_trait.trait_ref);
|
||||
}
|
||||
|
||||
// 1.5. Remove any path that doesn't resolve to a `DefId` or if it resolve to a
|
||||
|
||||
@@ -1155,8 +1155,7 @@ fn check_doc_fake_variadic(&self, meta: &MetaItemInner, hir_id: HirId) {
|
||||
let is_valid = doc_fake_variadic_is_allowed_self_ty(i.self_ty)
|
||||
|| if let Some(&[hir::GenericArg::Type(ty)]) = i
|
||||
.of_trait
|
||||
.as_ref()
|
||||
.and_then(|trait_ref| trait_ref.path.segments.last())
|
||||
.and_then(|of_trait| of_trait.trait_ref.path.segments.last())
|
||||
.map(|last_segment| last_segment.args().args)
|
||||
{
|
||||
matches!(&ty.kind, hir::TyKind::Tup([_]))
|
||||
@@ -1646,8 +1645,8 @@ fn check_may_dangle(&self, hir_id: HirId, attr_span: Span) {
|
||||
&& let parent_hir_id = self.tcx.parent_hir_id(hir_id)
|
||||
&& let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
|
||||
&& let hir::ItemKind::Impl(impl_) = item.kind
|
||||
&& let Some(trait_) = impl_.of_trait
|
||||
&& let Some(def_id) = trait_.trait_def_id()
|
||||
&& let Some(of_trait) = impl_.of_trait
|
||||
&& let Some(def_id) = of_trait.trait_ref.trait_def_id()
|
||||
&& self.tcx.is_lang_item(def_id, hir::LangItem::Drop)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -590,9 +590,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
// For implementations of traits, check the stability of each item
|
||||
// individually as it's possible to have a stable trait with unstable
|
||||
// items.
|
||||
hir::ItemKind::Impl(hir::Impl {
|
||||
of_trait: Some(t), self_ty, items, constness, ..
|
||||
}) => {
|
||||
hir::ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), self_ty, items, .. }) => {
|
||||
let features = self.tcx.features();
|
||||
if features.staged_api() {
|
||||
let attrs = self.tcx.hir_attrs(item.hir_id());
|
||||
@@ -628,7 +626,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
{
|
||||
let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
|
||||
c.visit_ty_unambig(self_ty);
|
||||
c.visit_trait_ref(t);
|
||||
c.visit_trait_ref(&of_trait.trait_ref);
|
||||
|
||||
// Skip the lint if the impl is marked as unstable using
|
||||
// #[unstable_feature_bound(..)]
|
||||
@@ -641,7 +639,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
|
||||
// do not lint when the trait isn't resolved, since resolution error should
|
||||
// be fixed first
|
||||
if t.path.res != Res::Err
|
||||
if of_trait.trait_ref.path.res != Res::Err
|
||||
&& c.fully_stable
|
||||
&& !unstable_feature_bound_in_effect
|
||||
{
|
||||
@@ -655,7 +653,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
}
|
||||
|
||||
if features.const_trait_impl()
|
||||
&& let hir::Constness::Const = constness
|
||||
&& let hir::Constness::Const = of_trait.constness
|
||||
{
|
||||
let stable_or_implied_stable = match const_stab {
|
||||
None => true,
|
||||
@@ -671,7 +669,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
Some(_) => false,
|
||||
};
|
||||
|
||||
if let Some(trait_id) = t.trait_def_id()
|
||||
if let Some(trait_id) = of_trait.trait_ref.trait_def_id()
|
||||
&& let Some(const_stab) = self.tcx.lookup_const_stability(trait_id)
|
||||
{
|
||||
// the const stability of a trait impl must match the const stability on the trait.
|
||||
@@ -699,14 +697,18 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
if let hir::Constness::Const = constness
|
||||
&& let Some(def_id) = t.trait_def_id()
|
||||
if let hir::Constness::Const = of_trait.constness
|
||||
&& let Some(def_id) = of_trait.trait_ref.trait_def_id()
|
||||
{
|
||||
// FIXME(const_trait_impl): Improve the span here.
|
||||
self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
|
||||
self.tcx.check_const_stability(
|
||||
def_id,
|
||||
of_trait.trait_ref.path.span,
|
||||
of_trait.trait_ref.path.span,
|
||||
);
|
||||
}
|
||||
|
||||
for impl_item_ref in *items {
|
||||
for impl_item_ref in items {
|
||||
let impl_item = self.tcx.associated_item(impl_item_ref.owner_id);
|
||||
|
||||
if let Some(def_id) = impl_item.trait_item_def_id {
|
||||
|
||||
@@ -1779,7 +1779,8 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
if let DefKind::Impl { of_trait: true } = tcx.def_kind(def_id) {
|
||||
let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
|
||||
let trait_ref = trait_ref.instantiate_identity();
|
||||
visitor.span = tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().path.span;
|
||||
visitor.span =
|
||||
tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().trait_ref.path.span;
|
||||
let _ =
|
||||
visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path());
|
||||
}
|
||||
|
||||
@@ -3471,8 +3471,8 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
|
||||
..
|
||||
})) => {
|
||||
let mut spans = Vec::with_capacity(2);
|
||||
if let Some(trait_ref) = of_trait {
|
||||
spans.push(trait_ref.path.span);
|
||||
if let Some(of_trait) = of_trait {
|
||||
spans.push(of_trait.trait_ref.path.span);
|
||||
}
|
||||
spans.push(self_ty.span);
|
||||
let mut spans: MultiSpan = spans.into();
|
||||
@@ -3480,7 +3480,7 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
|
||||
self_ty.span.ctxt().outer_expn_data().kind,
|
||||
ExpnKind::Macro(MacroKind::Derive, _)
|
||||
) || matches!(
|
||||
of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind),
|
||||
of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind),
|
||||
Some(ExpnKind::Macro(MacroKind::Derive, _))
|
||||
) {
|
||||
spans.push_span_label(
|
||||
@@ -3592,7 +3592,7 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
|
||||
..
|
||||
})) => {
|
||||
let mut spans = vec![self_ty.span];
|
||||
spans.extend(of_trait.as_ref().map(|t| t.path.span));
|
||||
spans.extend(of_trait.map(|t| t.trait_ref.path.span));
|
||||
let mut spans: MultiSpan = spans.into();
|
||||
spans.push_span_label(data.span, "unsatisfied trait bound introduced here");
|
||||
err.span_note(spans, msg);
|
||||
|
||||
@@ -174,10 +174,10 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
|
||||
})
|
||||
.collect(),
|
||||
ItemKind::Impl(impl_) => {
|
||||
let Some(trait_ref) = impl_.of_trait else {
|
||||
let Some(of_trait) = impl_.of_trait else {
|
||||
return Default::default();
|
||||
};
|
||||
let Some(trait_def_id) = trait_ref.trait_def_id() else {
|
||||
let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else {
|
||||
return Default::default();
|
||||
};
|
||||
let in_trait_def = tcx.associated_types_for_impl_traits_in_trait_or_impl(trait_def_id);
|
||||
|
||||
@@ -172,10 +172,12 @@ fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span>
|
||||
let trait_args = impl_
|
||||
.of_trait
|
||||
.into_iter()
|
||||
.flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args)
|
||||
.flat_map(|of_trait| of_trait.trait_ref.path.segments.last().unwrap().args().args)
|
||||
.map(|arg| arg.span());
|
||||
let dummy_spans_for_default_args =
|
||||
impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span));
|
||||
let dummy_spans_for_default_args = impl_
|
||||
.of_trait
|
||||
.into_iter()
|
||||
.flat_map(|of_trait| iter::repeat(of_trait.trait_ref.path.span));
|
||||
iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args)
|
||||
} else {
|
||||
bug!("unexpected item for impl {def_id:?}: {item:?}")
|
||||
|
||||
@@ -87,7 +87,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
|
||||
DefKind::InlineConst | DefKind::Closure | DefKind::SyntheticCoroutineBody => {}
|
||||
DefKind::Impl { of_trait } => {
|
||||
if of_trait {
|
||||
let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span;
|
||||
let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().trait_ref.path.span;
|
||||
let args = &tcx.impl_trait_ref(item).unwrap().instantiate_identity().args[1..];
|
||||
try_visit!(visitor.visit(span, args));
|
||||
}
|
||||
|
||||
@@ -81,7 +81,11 @@ fn sizedness_constraint_for_ty<'tcx>(
|
||||
fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
|
||||
match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(hir::Impl { defaultness, of_trait: Some(_), .. }),
|
||||
kind:
|
||||
hir::ItemKind::Impl(hir::Impl {
|
||||
of_trait: Some(hir::TraitImplHeader { defaultness, .. }),
|
||||
..
|
||||
}),
|
||||
..
|
||||
})
|
||||
| hir::Node::ImplItem(hir::ImplItem { defaultness, .. })
|
||||
|
||||
@@ -2768,7 +2768,7 @@ fn get_name(
|
||||
// These kinds of item either don't need a `name` or accept a `None` one so we handle them
|
||||
// before.
|
||||
match item.kind {
|
||||
ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
|
||||
ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
|
||||
ItemKind::Use(path, kind) => {
|
||||
return clean_use_statement(
|
||||
item,
|
||||
@@ -2896,7 +2896,7 @@ fn clean_impl<'tcx>(
|
||||
) -> Vec<Item> {
|
||||
let tcx = cx.tcx;
|
||||
let mut ret = Vec::new();
|
||||
let trait_ = impl_.of_trait.as_ref().map(|t| clean_trait_ref(t, cx));
|
||||
let trait_ = impl_.of_trait.map(|t| clean_trait_ref(&t.trait_ref, cx));
|
||||
let items = impl_
|
||||
.items
|
||||
.iter()
|
||||
@@ -2922,7 +2922,10 @@ fn clean_impl<'tcx>(
|
||||
});
|
||||
let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
|
||||
let kind = ImplItem(Box::new(Impl {
|
||||
safety: impl_.safety,
|
||||
safety: match impl_.of_trait {
|
||||
Some(of_trait) => of_trait.safety,
|
||||
None => hir::Safety::Safe,
|
||||
},
|
||||
generics: clean_generics(impl_.generics, cx),
|
||||
trait_,
|
||||
for_,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -37,12 +37,12 @@
|
||||
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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -201,10 +201,11 @@
|
||||
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());
|
||||
|
||||
|
||||
@@ -36,11 +36,11 @@
|
||||
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
|
||||
|
||||
@@ -52,7 +52,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
);
|
||||
},
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -67,12 +67,12 @@ pub fn new(conf: &'static Conf) -> Self {
|
||||
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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
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>");
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
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) {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -150,7 +150,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
} = 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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -61,10 +61,10 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
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
|
||||
|
||||
@@ -778,7 +778,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>)
|
||||
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
|
||||
|
||||
@@ -83,10 +83,10 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -34,15 +34,15 @@
|
||||
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,
|
||||
|
||||
@@ -68,9 +68,9 @@ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
|
||||
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
|
||||
|
||||
@@ -26,16 +26,16 @@
|
||||
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)),
|
||||
|
||||
@@ -48,10 +48,10 @@
|
||||
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(
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
}
|
||||
},
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -347,10 +347,10 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
|
||||
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 {
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
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("}")),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -460,7 +460,8 @@ fn visit_block(&mut self, b: &'tcx Block<'_>) -> Self::Result {
|
||||
}
|
||||
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 {
|
||||
|
||||
@@ -509,7 +509,7 @@ mod items {
|
||||
impl () { }
|
||||
impl <T> () { }
|
||||
impl Default for () { }
|
||||
impl const <T> Default for () { }
|
||||
impl <T> const Default for () { }
|
||||
}
|
||||
/// ItemKind::MacCall
|
||||
mod item_mac_call { }
|
||||
|
||||
Reference in New Issue
Block a user