Skip to content

Make AssocItem aware of its impl kind #145186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, Target, find_attr};
use rustc_hir::{
self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr,
};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
Expand Down Expand Up @@ -1117,20 +1119,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
};

let span = self.lower_span(i.span);
let item = hir::ImplItem {
owner_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
generics,
impl_kind: if is_in_trait_impl {
ImplItemImplKind::Trait {
defaultness,
trait_item_def_id: self
.resolver
.get_partial_res(i.id)
.and_then(|r| r.expect_full_res().opt_def_id())
.ok_or_else(|| {
self.dcx().span_delayed_bug(
span,
"could not resolve trait item being implemented",
)
}),
}
} else {
ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) }
},
kind,
vis_span: self.lower_span(i.vis.span),
span: self.lower_span(i.span),
defaultness,
span,
has_delayed_lints: !self.delayed_lints.is_empty(),
trait_item_def_id: self
.resolver
.get_partial_res(i.id)
.map(|r| r.expect_full_res().opt_def_id())
.unwrap_or(None),
};
self.arena.alloc(item)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return (false, false, None);
};

let implemented_trait_item = self.infcx.tcx.associated_item(my_def).trait_item_def_id;
let implemented_trait_item = self.infcx.tcx.trait_item_of(my_def);

(
true,
Expand Down
16 changes: 4 additions & 12 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,26 +576,18 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
codegen_fn_attrs
}

/// If the provided DefId is a method in a trait impl, return the DefId of the method prototype.
fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
let impl_item = tcx.opt_associated_item(def_id)?;
match impl_item.container {
ty::AssocItemContainer::Impl => impl_item.trait_item_def_id,
_ => None,
}
}

/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
/// applied to the method prototype.
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let Some(trait_item) = opt_trait_item(tcx, def_id) else { return false };
tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
tcx.trait_item_of(def_id).is_some_and(|id| {
tcx.codegen_fn_attrs(id).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
})
}

/// If the provided DefId is a method in a trait impl, return the value of the `#[align]`
/// attribute on the method prototype (if any).
fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment
tcx.codegen_fn_attrs(tcx.trait_item_of(def_id)?).alignment
}

/// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)]
Expand Down
26 changes: 21 additions & 5 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3193,12 +3193,21 @@ pub struct ImplItem<'hir> {
pub owner_id: OwnerId,
pub generics: &'hir Generics<'hir>,
pub kind: ImplItemKind<'hir>,
pub defaultness: Defaultness,
pub impl_kind: ImplItemImplKind,
pub span: Span,
pub vis_span: Span,
pub has_delayed_lints: bool,
/// When we are in a trait impl, link to the trait-item's id.
pub trait_item_def_id: Option<DefId>,
}

#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum ImplItemImplKind {
Inherent {
vis_span: Span,
},
Trait {
defaultness: Defaultness,
/// Item in the trait that this item implements
trait_item_def_id: Result<DefId, ErrorGuaranteed>,
},
}

impl<'hir> ImplItem<'hir> {
Expand All @@ -3212,6 +3221,13 @@ impl<'hir> ImplItem<'hir> {
ImplItemId { owner_id: self.owner_id }
}

pub fn vis_span(&self) -> Option<Span> {
match self.impl_kind {
ImplItemImplKind::Trait { .. } => None,
ImplItemImplKind::Inherent { vis_span, .. } => Some(vis_span),
}
}

expect_methods_self_kind! {
expect_const, (&'hir Ty<'hir>, BodyId), ImplItemKind::Const(ty, body), (ty, *body);
expect_fn, (&FnSig<'hir>, BodyId), ImplItemKind::Fn(ty, body), (ty, *body);
Expand Down Expand Up @@ -4958,7 +4974,7 @@ mod size_asserts {
static_assert_size!(GenericBound<'_>, 64);
static_assert_size!(Generics<'_>, 56);
static_assert_size!(Impl<'_>, 40);
static_assert_size!(ImplItem<'_>, 96);
static_assert_size!(ImplItem<'_>, 88);
static_assert_size!(ImplItemKind<'_>, 40);
static_assert_size!(Item<'_>, 88);
static_assert_size!(ItemKind<'_>, 64);
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1257,18 +1257,21 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
owner_id: _,
ident,
ref generics,
ref impl_kind,
ref kind,
ref defaultness,
span: _,
vis_span: _,
has_delayed_lints: _,
trait_item_def_id: _,
} = *impl_item;

try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_defaultness(defaultness));
try_visit!(visitor.visit_id(impl_item.hir_id()));
match impl_kind {
ImplItemImplKind::Inherent { vis_span: _ } => {}
ImplItemImplKind::Trait { defaultness, trait_item_def_id: _ } => {
try_visit!(visitor.visit_defaultness(defaultness));
}
}
match *kind {
ImplItemKind::Const(ref ty, body) => {
try_visit!(visitor.visit_ty_unambig(ty));
Expand Down
21 changes: 9 additions & 12 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,8 +1009,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
res = res.and(check_associated_item(tcx, def_id));
let assoc_item = tcx.associated_item(def_id);
match assoc_item.container {
ty::AssocItemContainer::Impl => {}
ty::AssocItemContainer::Trait => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {}
ty::AssocContainer::Trait => {
res = res.and(check_trait_item(tcx, def_id));
}
}
Expand All @@ -1026,8 +1026,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
res = res.and(check_associated_item(tcx, def_id));
let assoc_item = tcx.associated_item(def_id);
match assoc_item.container {
ty::AssocItemContainer::Impl => {}
ty::AssocItemContainer::Trait => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {}
ty::AssocContainer::Trait => {
res = res.and(check_trait_item(tcx, def_id));
}
}
Expand All @@ -1043,8 +1043,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),

let assoc_item = tcx.associated_item(def_id);
let has_type = match assoc_item.container {
ty::AssocItemContainer::Impl => true,
ty::AssocItemContainer::Trait => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
ty::AssocContainer::Trait => {
tcx.ensure_ok().explicit_item_bounds(def_id);
tcx.ensure_ok().explicit_item_self_bounds(def_id);
if tcx.is_conditionally_const(def_id) {
Expand Down Expand Up @@ -1177,12 +1177,9 @@ fn check_impl_items_against_trait<'tcx>(

for &impl_item in impl_item_refs {
let ty_impl_item = tcx.associated_item(impl_item);
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
tcx.associated_item(trait_item_id)
} else {
// Checked in `associated_item`.
tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
continue;
let ty_trait_item = match ty_impl_item.expect_trait_impl() {
Ok(trait_item_id) => tcx.associated_item(trait_item_id),
Err(ErrorGuaranteed { .. }) => continue,
};

let res = tcx.ensure_ok().compare_impl_item(impl_item.expect_local());
Expand Down
18 changes: 12 additions & 6 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub(super) fn compare_impl_item(
impl_item_def_id: LocalDefId,
) -> Result<(), ErrorGuaranteed> {
let impl_item = tcx.associated_item(impl_item_def_id);
let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap());
let trait_item = tcx.associated_item(impl_item.expect_trait_impl()?);
let impl_trait_ref =
tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
debug!(?impl_trait_ref);
Expand Down Expand Up @@ -446,7 +446,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
impl_m_def_id: LocalDefId,
) -> Result<&'tcx DefIdMap<ty::EarlyBinder<'tcx, Ty<'tcx>>>, ErrorGuaranteed> {
let impl_m = tcx.associated_item(impl_m_def_id.to_def_id());
let trait_m = tcx.associated_item(impl_m.trait_item_def_id.unwrap());
let trait_m = tcx.associated_item(impl_m.expect_trait_impl()?);
let impl_trait_ref =
tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity();
// First, check a few of the same things as `compare_impl_method`,
Expand Down Expand Up @@ -1449,8 +1449,10 @@ fn compare_self_type<'tcx>(

let self_string = |method: ty::AssocItem| {
let untransformed_self_ty = match method.container {
ty::AssocItemContainer::Impl => impl_trait_ref.self_ty(),
ty::AssocItemContainer::Trait => tcx.types.self_param,
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
impl_trait_ref.self_ty()
}
ty::AssocContainer::Trait => tcx.types.self_param,
};
let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
let (infcx, param_env) = tcx
Expand Down Expand Up @@ -2458,8 +2460,12 @@ fn param_env_with_gat_bounds<'tcx>(

for impl_ty in impl_tys_to_install {
let trait_ty = match impl_ty.container {
ty::AssocItemContainer::Trait => impl_ty,
ty::AssocItemContainer::Impl => tcx.associated_item(impl_ty.trait_item_def_id.unwrap()),
ty::AssocContainer::InherentImpl => bug!(),
ty::AssocContainer::Trait => impl_ty,
ty::AssocContainer::TraitImpl(Err(_)) => continue,
ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) => {
tcx.associated_item(trait_item_def_id)
}
};

let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -944,12 +944,11 @@ pub(crate) fn check_associated_item(

// 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(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?;
tcx.ensure_ok().coherent_trait(tcx.parent(item.trait_item_or_self()?))?;

let self_ty = match item.container {
ty::AssocItemContainer::Trait => tcx.types.self_param,
ty::AssocItemContainer::Impl => {
ty::AssocContainer::Trait => tcx.types.self_param,
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
tcx.type_of(item.container_id(tcx)).instantiate_identity()
}
};
Expand Down Expand Up @@ -978,7 +977,7 @@ pub(crate) fn check_associated_item(
check_method_receiver(wfcx, hir_sig, item, self_ty)
}
ty::AssocKind::Type { .. } => {
if let ty::AssocItemContainer::Trait = item.container {
if let ty::AssocContainer::Trait = item.container {
check_associated_type_bounds(wfcx, item, span)
}
if item.defaultness(tcx).has_value() {
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}

Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
let assoc_item = tcx.associated_item(def_id);
let trait_assoc_predicates =
tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
let trait_item_def_id = tcx.trait_item_of(def_id).unwrap();
let trait_assoc_predicates = tcx.explicit_predicates_of(trait_item_def_id);

let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
let impl_def_id = tcx.parent(fn_def_id);
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => {
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
Ok(map) => {
let assoc_item = tcx.associated_item(def_id);
return map[&assoc_item.trait_item_def_id.unwrap()];
let trait_item_def_id = tcx.trait_item_of(def_id).unwrap();
return map[&trait_item_def_id];
}
Err(_) => {
return ty::EarlyBinder::bind(Ty::new_error_with_message(
Expand Down Expand Up @@ -198,7 +198,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
}
}
ImplItemKind::Type(ty) => {
if tcx.impl_trait_ref(tcx.hir_get_parent_item(hir_id)).is_none() {
if let ImplItemImplKind::Inherent { .. } = item.impl_kind {
check_feature_inherent_assoc_ty(tcx, item.span);
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let container_id = assoc_item.container_id(tcx);
debug!(?def_id, ?container, ?container_id);
match container {
ty::AssocItemContainer::Trait => {
ty::AssocContainer::Trait => {
if let Err(e) = callee::check_legal_trait_for_method_call(
tcx,
path_span,
Expand All @@ -1033,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.set_tainted_by_errors(e);
}
}
ty::AssocItemContainer::Impl => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
if segments.len() == 1 {
// `<T>::assoc` will end up here, and so
// can `T::assoc`. If this came from an
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2347,7 +2347,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We want it to always point to the trait item.
// If we're pointing at an inherent function, we don't need to do anything,
// so we fetch the parent and verify if it's a trait item.
&& let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
&& let Ok(maybe_trait_item_def_id) = assoc_item.trait_item_or_self()
&& let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
// Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
&& let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1816,7 +1816,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if segment.ident.name == sym::clone
&& results.type_dependent_def_id(expr.hir_id).is_some_and(|did| {
let assoc_item = self.tcx.associated_item(did);
assoc_item.container == ty::AssocItemContainer::Trait
assoc_item.container == ty::AssocContainer::Trait
&& assoc_item.container_id(self.tcx) == clone_trait_did
})
// If that clone call hasn't already dereferenced the self type (i.e. don't give this
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
{
if let Some(item) = tcx.opt_associated_item(def_id.into())
&& let ty::AssocKind::Const { .. } = item.kind
&& let ty::AssocItemContainer::Impl = item.container
&& let Some(trait_item_def_id) = item.trait_item_def_id
&& let ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container
{
let impl_def_id = item.container_id(tcx);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
Expand Down
Loading
Loading