diff options
Diffstat (limited to 'compiler')
42 files changed, 289 insertions, 298 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index bb559bd8921..53351f91c46 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -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}; @@ -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) } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index ea264c8064a..6d69040c711 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -716,7 +716,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, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 008340e614d..dc500c363f4 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -562,15 +562,6 @@ 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, - } -} - fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet { // Backtrack to the crate root. let mut disabled = match tcx.opt_local_parent(did) { @@ -600,14 +591,15 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet { /// 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(...)] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 75551fe4c19..493236718a8 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3220,12 +3220,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> { @@ -3239,6 +3248,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); @@ -4985,7 +5001,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); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 25a7ae239f3..eb682f32111 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -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)); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 08b344638dd..886ebddc75c 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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)); } } @@ -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)); } } @@ -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) { @@ -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()); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e4827256193..84fb09b7390 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -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); @@ -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`, @@ -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 @@ -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]> = diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 22a9446fd4c..d33f1f3e12a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -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() } }; @@ -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() { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 126ffabd448..dd3590f9ac5 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -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); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 62125c99d80..8cbf17162e3 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -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( @@ -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); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 0b3d50ff219..7370124e800 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -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, @@ -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 diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 94b635c41b4..44a6084ebd5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2354,7 +2354,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) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index d7ddbcc8b53..1998a1884b7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1882,7 +1882,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 diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 129de32fd4a..7f5397a7926 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -278,8 +278,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(); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 52a8eff984b..4185f7f6996 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -18,8 +18,8 @@ use rustc_middle::middle::stability; use rustc_middle::ty::elaborate::supertrait_def_ids; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type}; use rustc_middle::ty::{ - self, AssocItem, AssocItemContainer, GenericArgs, GenericArgsRef, GenericParamDefKind, - ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, Upcast, + self, AssocContainer, AssocItem, GenericArgs, GenericArgsRef, GenericParamDefKind, ParamEnvAnd, + Ty, TyCtxt, TypeVisitableExt, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -528,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::Single(def_id) => { let item = self.tcx.associated_item(def_id); // FIXME(fn_delegation): Delegation to inherent methods is not yet supported. - assert_eq!(item.container, AssocItemContainer::Trait); + assert_eq!(item.container, AssocContainer::Trait); let trait_def_id = self.tcx.parent(def_id); let trait_span = self.tcx.def_span(trait_def_id); @@ -1659,7 +1659,7 @@ impl<'tcx> Pick<'tcx> { /// Do not use for type checking. pub(crate) fn differs_from(&self, other: &Self) -> bool { let Self { - item: AssocItem { def_id, kind: _, container: _, trait_item_def_id: _ }, + item: AssocItem { def_id, kind: _, container: _ }, kind: _, import_ids: _, autoderefs: _, @@ -1702,7 +1702,7 @@ impl<'tcx> Pick<'tcx> { tcx.def_path_str(self.item.def_id), )); } - (ty::AssocKind::Const { name }, ty::AssocItemContainer::Trait) => { + (ty::AssocKind::Const { name }, ty::AssocContainer::Trait) => { let def_id = self.item.container_id(tcx); lint.span_suggestion( span, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c3c0a34df71..75a0f89321b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -29,12 +29,12 @@ use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; -use rustc_hir::{Body, FnDecl, PatKind, PredicateOrigin, find_attr}; +use rustc_hir::{Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr}; use rustc_middle::bug; use rustc_middle::lint::LevelAndSource; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; +use rustc_middle::ty::{self, AssocContainer, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; use rustc_session::lint::FutureIncompatibilityReason; // hardwired lints from rustc_lint_defs pub use rustc_session::lint::builtin::*; @@ -61,7 +61,6 @@ use crate::lints::{ BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel, }; -use crate::nonstandard_style::{MethodLateContext, method_context}; use crate::{ EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, fluent_generated as fluent, @@ -469,14 +468,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { - let context = method_context(cx, impl_item.owner_id.def_id); + let container = cx.tcx.associated_item(impl_item.owner_id.def_id).container; - match context { + match container { // If the method is an impl for a trait, don't doc. - MethodLateContext::TraitImpl => return, - MethodLateContext::TraitAutoImpl => {} + AssocContainer::TraitImpl(_) => return, + AssocContainer::Trait => {} // If the method is an impl for an item with docs_hidden, don't doc. - MethodLateContext::PlainImpl => { + AssocContainer::InherentImpl => { let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()); let impl_ty = cx.tcx.type_of(parent).instantiate_identity(); let outerdef = match impl_ty.kind() { @@ -1321,9 +1320,8 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { - // Only lint inherent impl items. - if cx.tcx.associated_item(impl_item.owner_id).trait_item_def_id.is_none() { - self.perform_lint(cx, "item", impl_item.owner_id.def_id, impl_item.vis_span, false); + if let ImplItemImplKind::Inherent { vis_span } = impl_item.impl_kind { + self.perform_lint(cx, "item", impl_item.owner_id.def_id, vis_span, false); } } } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 65075cfecfa..7f643a551bb 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{FnKind, Visitor}; use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr}; use rustc_middle::hir::nested_filter::All; -use rustc_middle::ty; +use rustc_middle::ty::AssocContainer; use rustc_session::config::CrateType; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::def_id::LocalDefId; @@ -20,29 +20,6 @@ use crate::lints::{ }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; -#[derive(PartialEq)] -pub(crate) enum MethodLateContext { - TraitAutoImpl, - TraitImpl, - PlainImpl, -} - -pub(crate) fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext { - let item = cx.tcx.associated_item(id); - match item.container { - ty::AssocItemContainer::Trait => MethodLateContext::TraitAutoImpl, - ty::AssocItemContainer::Impl => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) { - Some(_) => MethodLateContext::TraitImpl, - None => MethodLateContext::PlainImpl, - }, - } -} - -fn assoc_item_in_trait_impl(cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) -> bool { - let item = cx.tcx.associated_item(ii.owner_id); - item.trait_item_def_id.is_some() -} - declare_lint! { /// The `non_camel_case_types` lint detects types, variants, traits and /// type parameters that don't have camel case names. @@ -389,8 +366,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { id: LocalDefId, ) { match &fk { - FnKind::Method(ident, sig, ..) => match method_context(cx, id) { - MethodLateContext::PlainImpl => { + FnKind::Method(ident, sig, ..) => match cx.tcx.associated_item(id).container { + AssocContainer::InherentImpl => { if sig.header.abi != ExternAbi::Rust && find_attr!(cx.tcx.get_all_attrs(id), AttributeKind::NoMangle(..)) { @@ -398,10 +375,10 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } self.check_snake_case(cx, "method", ident); } - MethodLateContext::TraitAutoImpl => { + AssocContainer::Trait => { self.check_snake_case(cx, "trait method", ident); } - _ => (), + AssocContainer::TraitImpl(_) => {} }, FnKind::ItemFn(ident, _, header) => { // Skip foreign-ABI #[no_mangle] functions (Issue #31924) @@ -602,7 +579,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) { if let hir::ImplItemKind::Const(..) = ii.kind - && !assoc_item_in_trait_impl(cx, ii) + && let hir::ImplItemImplKind::Inherent { .. } = ii.impl_kind { NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ii.ident); } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 110b26c62ef..0c8d1f32e99 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1194,10 +1194,6 @@ impl<'a> CrateMetadataRef<'a> { self.root.tables.default_fields.get(self, id).map(|d| d.decode(self)) } - fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> { - self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode_from_cdata(self)) - } - fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId { self.root .tables @@ -1359,14 +1355,9 @@ impl<'a> CrateMetadataRef<'a> { } _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; - let container = self.root.tables.assoc_container.get(self, id).unwrap(); + let container = self.root.tables.assoc_container.get(self, id).unwrap().decode(self); - ty::AssocItem { - kind, - def_id: self.local_def_id(id), - trait_item_def_id: self.get_trait_item_def_id(id), - container, - } + ty::AssocItem { kind, def_id: self.local_def_id(id), container } } fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a7e7e9985f4..db66938457f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -22,7 +22,7 @@ use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::mir::interpret; use rustc_middle::query::Providers; use rustc_middle::traits::specialization_graph; -use rustc_middle::ty::AssocItemContainer; +use rustc_middle::ty::AssocContainer; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, TreatParams}; use rustc_middle::{bug, span_bug}; @@ -1254,8 +1254,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> DefKind::AssocTy => { let assoc_item = tcx.associated_item(def_id); match assoc_item.container { - ty::AssocItemContainer::Impl => true, - ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(), + ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true, + ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(), } } DefKind::TyParam => { @@ -1725,24 +1725,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let item = tcx.associated_item(def_id); - self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx)); - self.tables.assoc_container.set_some(def_id.index, item.container); - - match item.container { - AssocItemContainer::Trait => { - if item.is_type() { - self.encode_explicit_item_bounds(def_id); - self.encode_explicit_item_self_bounds(def_id); - if tcx.is_conditionally_const(def_id) { - record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id] - <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder()); - } - } - } - AssocItemContainer::Impl => { - if let Some(trait_item_def_id) = item.trait_item_def_id { - self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into()); - } + if matches!(item.container, AssocContainer::Trait | AssocContainer::TraitImpl(_)) { + self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx)); + } + + record!(self.tables.assoc_container[def_id] <- item.container); + + if let AssocContainer::Trait = item.container + && item.is_type() + { + self.encode_explicit_item_bounds(def_id); + self.encode_explicit_item_self_bounds(def_id); + if tcx.is_conditionally_const(def_id) { + record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id] + <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder()); } } if let ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(rpitit_info) } = item.kind { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 1f7d142d330..720970bbaf9 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -447,7 +447,6 @@ define_tables! { coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>, eval_static_initializer: Table<DefIndex, LazyValue<mir::interpret::ConstAllocation<'static>>>, trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>, - trait_item_def_id: Table<DefIndex, RawDefId>, expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>, default_fields: Table<DefIndex, LazyValue<DefId>>, params_in_repr: Table<DefIndex, LazyValue<DenseBitSet<u32>>>, @@ -459,7 +458,7 @@ define_tables! { def_keys: Table<DefIndex, LazyValue<DefKey>>, proc_macro_quoted_spans: Table<usize, LazyValue<Span>>, variant_data: Table<DefIndex, LazyValue<VariantData>>, - assoc_container: Table<DefIndex, ty::AssocItemContainer>, + assoc_container: Table<DefIndex, LazyValue<ty::AssocContainer>>, macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>, proc_macro: Table<DefIndex, MacroKind>, deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>, diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index 34180001f80..4b2dc2c814e 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -102,7 +102,7 @@ trivially_parameterized_over_tcx! { rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault, rustc_middle::mir::ConstQualifs, rustc_middle::ty::AnonConstKind, - rustc_middle::ty::AssocItemContainer, + rustc_middle::ty::AssocContainer, rustc_middle::ty::AsyncDestructor, rustc_middle::ty::Asyncness, rustc_middle::ty::DeducedParamAttrs, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 2cb07a28a8a..a882ee4f2b9 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -222,13 +222,6 @@ fixed_size_enum! { } fixed_size_enum! { - ty::AssocItemContainer { - ( Trait ) - ( Impl ) - } -} - -fixed_size_enum! { MacroKind { ( Attr ) ( Bang ) diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index bea2191c560..4c00b769237 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -318,7 +318,7 @@ trivial! { rustc_middle::traits::WellFormedLoc, rustc_middle::ty::adjustment::CoerceUnsizedInfo, rustc_middle::ty::AssocItem, - rustc_middle::ty::AssocItemContainer, + rustc_middle::ty::AssocContainer, rustc_middle::ty::Asyncness, rustc_middle::ty::AsyncDestructor, rustc_middle::ty::BoundVariableKind, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2aa32dfa0d8..0e645a3aae4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1881,6 +1881,7 @@ rustc_queries! { } /// Returns whether the impl or associated function has the `default` keyword. + /// Note: This will ICE on inherent impl items. Consider using `AssocItem::defaultness`. query defaultness(def_id: DefId) -> hir::Defaultness { desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index a902a8a61e5..768646c7630 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -5,15 +5,17 @@ use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_hir::find_attr; use rustc_macros::{Decodable, Encodable, HashStable}; -use rustc_span::{Ident, Symbol}; +use rustc_span::{ErrorGuaranteed, Ident, Symbol}; use super::{TyCtxt, Visibility}; use crate::ty; #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)] -pub enum AssocItemContainer { +pub enum AssocContainer { Trait, - Impl, + InherentImpl, + /// The `DefId` points to the trait item being implemented. + TraitImpl(Result<DefId, ErrorGuaranteed>), } /// Information about an associated item @@ -21,11 +23,7 @@ pub enum AssocItemContainer { pub struct AssocItem { pub def_id: DefId, pub kind: AssocKind, - pub container: AssocItemContainer, - - /// If this is an item in an impl of a trait then this is the `DefId` of - /// the associated item on the trait that this implements. - pub trait_item_def_id: Option<DefId>, + pub container: AssocContainer, } impl AssocItem { @@ -55,7 +53,34 @@ impl AssocItem { /// /// [`type_of`]: crate::ty::TyCtxt::type_of pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness { - tcx.defaultness(self.def_id) + match self.container { + AssocContainer::InherentImpl => hir::Defaultness::Final, + AssocContainer::Trait | AssocContainer::TraitImpl(_) => tcx.defaultness(self.def_id), + } + } + + pub fn expect_trait_impl(&self) -> Result<DefId, ErrorGuaranteed> { + let AssocContainer::TraitImpl(trait_item_id) = self.container else { + bug!("expected item to be in a trait impl: {:?}", self.def_id); + }; + trait_item_id + } + + /// If this is a trait impl item, returns the `DefId` of the trait item this implements. + /// Otherwise, returns `DefId` for self. Returns an Err in case the trait item was not + /// resolved successfully. + pub fn trait_item_or_self(&self) -> Result<DefId, ErrorGuaranteed> { + match self.container { + AssocContainer::TraitImpl(id) => id, + AssocContainer::Trait | AssocContainer::InherentImpl => Ok(self.def_id), + } + } + + pub fn trait_item_def_id(&self) -> Option<DefId> { + match self.container { + AssocContainer::TraitImpl(Ok(id)) => Some(id), + _ => None, + } } #[inline] @@ -71,16 +96,18 @@ impl AssocItem { #[inline] pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> { match self.container { - AssocItemContainer::Impl => None, - AssocItemContainer::Trait => Some(tcx.parent(self.def_id)), + AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => None, + AssocContainer::Trait => Some(tcx.parent(self.def_id)), } } #[inline] pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> { match self.container { - AssocItemContainer::Impl => Some(tcx.parent(self.def_id)), - AssocItemContainer::Trait => None, + AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => { + Some(tcx.parent(self.def_id)) + } + AssocContainer::Trait => None, } } @@ -156,11 +183,11 @@ impl AssocItem { return false; } - let def_id = match (self.container, self.trait_item_def_id) { - (AssocItemContainer::Trait, _) => self.def_id, - (AssocItemContainer::Impl, Some(trait_item_did)) => trait_item_did, - // Inherent impl but this attr is only applied to trait assoc items. - (AssocItemContainer::Impl, None) => return true, + let def_id = match self.container { + AssocContainer::Trait => self.def_id, + AssocContainer::TraitImpl(Ok(trait_item_did)) => trait_item_did, + AssocContainer::TraitImpl(Err(_)) => return false, + AssocContainer::InherentImpl => return true, }; find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8ea767dccd3..79700d485c4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2276,7 +2276,16 @@ impl<'tcx> TyCtxt<'tcx> { let is_impl_item = match self.hir_node_by_def_id(suitable_region_binding_scope) { Node::Item(..) | Node::TraitItem(..) => false, - Node::ImplItem(..) => self.is_bound_region_in_impl_item(suitable_region_binding_scope), + Node::ImplItem(impl_item) => match impl_item.impl_kind { + // For now, we do not try to target impls of traits. This is + // because this message is going to suggest that the user + // change the fn signature, but they may not be free to do so, + // since the signature must match the trait. + // + // FIXME(#42706) -- in some cases, we could do better here. + hir::ImplItemImplKind::Trait { .. } => true, + _ => false, + }, _ => false, }; @@ -2330,21 +2339,6 @@ impl<'tcx> TyCtxt<'tcx> { None } - /// Checks if the bound region is in Impl Item. - pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool { - let container_id = self.parent(suitable_region_binding_scope.to_def_id()); - if self.impl_trait_ref(container_id).is_some() { - // For now, we do not try to target impls of traits. This is - // because this message is going to suggest that the user - // change the fn signature, but they may not be free to do so, - // since the signature must match the trait. - // - // FIXME(#42706) -- in some cases, we could do better here. - return true; - } - false - } - /// Determines whether identifiers in the assembly have strict naming rules. /// Currently, only NVPTX* targets need it. pub fn has_strict_asm_symbol_naming(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index e76993e0542..34ead91b4f6 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -18,8 +18,8 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::print::{FmtPrinter, Print}; use crate::ty::{ - self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, + self, AssocContainer, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; /// An `InstanceKind` along with the args that are needed to substitute the instance. @@ -611,26 +611,23 @@ impl<'tcx> Instance<'tcx> { debug!(" => fn pointer created for virtual call"); resolved.def = InstanceKind::ReifyShim(def_id, reason); } - // Reify `Trait::method` implementations if KCFI is enabled - // FIXME(maurer) only reify it if it is a vtable-safe function - _ if tcx.sess.is_sanitizer_kcfi_enabled() - && tcx - .opt_associated_item(def_id) - .and_then(|assoc| assoc.trait_item_def_id) - .is_some() => - { - // If this function could also go in a vtable, we need to `ReifyShim` it with - // KCFI because it can only attach one type per function. - resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason) - } - // Reify `::call`-like method implementations if KCFI is enabled - _ if tcx.sess.is_sanitizer_kcfi_enabled() - && tcx.is_closure_like(resolved.def_id()) => - { - // Reroute through a reify via the *unresolved* instance. The resolved one can't - // be directly reified because it's closure-like. The reify can handle the - // unresolved instance. - resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args } + _ if tcx.sess.is_sanitizer_kcfi_enabled() => { + // Reify `::call`-like method implementations + if tcx.is_closure_like(resolved.def_id()) { + // Reroute through a reify via the *unresolved* instance. The resolved one can't + // be directly reified because it's closure-like. The reify can handle the + // unresolved instance. + resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args } + // Reify `Trait::method` implementations + // FIXME(maurer) only reify it if it is a vtable-safe function + } else if let Some(assoc) = tcx.opt_associated_item(def_id) + && let AssocContainer::Trait | AssocContainer::TraitImpl(Ok(_)) = + assoc.container + { + // If this function could also go in a vtable, we need to `ReifyShim` it with + // KCFI because it can only attach one type per function. + resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason) + } } _ => {} } @@ -683,7 +680,7 @@ impl<'tcx> Instance<'tcx> { && !matches!( tcx.opt_associated_item(def), Some(ty::AssocItem { - container: ty::AssocItemContainer::Trait, + container: ty::AssocContainer::Trait, .. }) ); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index da17ec1f9f3..d4c001f625e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1934,6 +1934,11 @@ impl<'tcx> TyCtxt<'tcx> { Some((parent, def_kind)) } + /// Returns the trait item that is implemented by the given item `DefId`. + pub fn trait_item_of(self, def_id: impl IntoQueryParam<DefId>) -> Option<DefId> { + self.opt_associated_item(def_id.into_query_param())?.trait_item_def_id() + } + /// If the given `DefId` is an associated item of a trait, /// returns the `DefId` of the trait; otherwise, returns `None`. pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> { @@ -2149,17 +2154,12 @@ impl<'tcx> TyCtxt<'tcx> { let Some(item) = self.opt_associated_item(def_id) else { return false; }; - if item.container != ty::AssocItemContainer::Impl { - return false; - } - let Some(trait_item_def_id) = item.trait_item_def_id else { + let AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container else { return false; }; - return !self - .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id) - .is_empty(); + !self.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id).is_empty() } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index fc33405d455..3c2c9683a4d 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -373,31 +373,27 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { /// Automatically generated items marked with `rustc_trivial_field_reads` /// will be ignored for the purposes of dead code analysis (see PR #85200 /// for discussion). - fn should_ignore_item(&mut self, def_id: DefId) -> bool { - if let Some(impl_of) = self.tcx.trait_impl_of_assoc(def_id) { - if !self.tcx.is_automatically_derived(impl_of) { - return false; - } - - if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) - && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) + fn should_ignore_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) -> bool { + if let hir::ImplItemImplKind::Trait { .. } = impl_item.impl_kind + && let impl_of = self.tcx.parent(impl_item.owner_id.to_def_id()) + && self.tcx.is_automatically_derived(impl_of) + && let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity() + && self.tcx.has_attr(trait_ref.def_id, sym::rustc_trivial_field_reads) + { + if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() + && let Some(adt_def_id) = adt_def.did().as_local() { - let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity(); - if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() - && let Some(adt_def_id) = adt_def.did().as_local() - { - self.ignored_derived_traits.entry(adt_def_id).or_default().insert(trait_of); - } - return true; + self.ignored_derived_traits.entry(adt_def_id).or_default().insert(trait_ref.def_id); } + return true; } false } fn visit_node(&mut self, node: Node<'tcx>) { - if let Node::ImplItem(hir::ImplItem { owner_id, .. }) = node - && self.should_ignore_item(owner_id.to_def_id()) + if let Node::ImplItem(impl_item) = node + && self.should_ignore_impl_item(impl_item) { return; } @@ -439,7 +435,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } Node::ImplItem(impl_item) => { let item = self.tcx.local_parent(impl_item.owner_id.def_id); - if self.tcx.impl_trait_ref(item).is_none() { + if let hir::ImplItemImplKind::Inherent { .. } = impl_item.impl_kind { //// If it's a type whose items are live, then it's live, too. //// This is done to handle the case where, for example, the static //// method of a private type is used, but the type itself is never @@ -484,13 +480,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn check_impl_or_impl_item_live(&mut self, local_def_id: LocalDefId) -> bool { let (impl_block_id, trait_def_id) = match self.tcx.def_kind(local_def_id) { // assoc impl items of traits are live if the corresponding trait items are live - DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => ( - self.tcx.local_parent(local_def_id), - self.tcx - .associated_item(local_def_id) - .trait_item_def_id - .and_then(|def_id| def_id.as_local()), - ), + DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => { + let trait_item_id = + self.tcx.trait_item_of(local_def_id).and_then(|def_id| def_id.as_local()); + (self.tcx.local_parent(local_def_id), trait_item_id) + } // impl items are live if the corresponding traits are live DefKind::Impl { of_trait: true } => ( local_def_id, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 71650c6b9b9..2ee1bd0dfd1 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -21,8 +21,8 @@ use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability::{AllowUnstable, Deprecated, DeprecationEntry, EvalResult}; use rustc_middle::query::{LocalCrate, Providers}; -use rustc_middle::ty::TyCtxt; use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::{AssocContainer, TyCtxt}; use rustc_session::lint; use rustc_session::lint::builtin::{DEPRECATED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL}; use rustc_span::{Span, Symbol, sym}; @@ -486,8 +486,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { self.check_compatible_stability(ii.owner_id.def_id); - let impl_def_id = self.tcx.hir_get_parent_item(ii.hir_id()); - if self.tcx.impl_trait_ref(impl_def_id).is_none() { + if let hir::ImplItemImplKind::Inherent { .. } = ii.impl_kind { self.check_missing_stability(ii.owner_id.def_id); self.check_missing_const_stability(ii.owner_id.def_id); } @@ -711,7 +710,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { 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 { + if let AssocContainer::TraitImpl(Ok(def_id)) = impl_item.container { // Pass `None` to skip deprecation warnings. self.tcx.check_stability( def_id, diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs index 1b5f0ed1429..bcc77ff849d 100644 --- a/compiler/rustc_public/src/ty.rs +++ b/compiler/rustc_public/src/ty.rs @@ -1612,11 +1612,7 @@ crate_def! { pub struct AssocItem { pub def_id: AssocDef, pub kind: AssocKind, - pub container: AssocItemContainer, - - /// If this is an item in an impl of a trait then this is the `DefId` of - /// the associated item on the trait that this implements. - pub trait_item_def_id: Option<AssocDef>, + pub container: AssocContainer, } #[derive(Clone, PartialEq, Debug, Eq, Serialize)] @@ -1636,9 +1632,11 @@ pub enum AssocKind { } #[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum AssocItemContainer { +pub enum AssocContainer { + InherentImpl, + /// The `AssocDef` points to the trait item being implemented. + TraitImpl(AssocDef), Trait, - Impl, } #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 207038db40d..5131611eb02 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -1076,14 +1076,21 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind { } } -impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { - type T = crate::ty::AssocItemContainer; +impl<'tcx> Stable<'tcx> for ty::AssocContainer { + type T = crate::ty::AssocContainer; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { - use crate::ty::AssocItemContainer; + fn stable( + &self, + tables: &mut Tables<'_, BridgeTys>, + _: &CompilerCtxt<'_, BridgeTys>, + ) -> Self::T { + use crate::ty::AssocContainer; match self { - ty::AssocItemContainer::Trait => AssocItemContainer::Trait, - ty::AssocItemContainer::Impl => AssocItemContainer::Impl, + ty::AssocContainer::Trait => AssocContainer::Trait, + ty::AssocContainer::InherentImpl => AssocContainer::InherentImpl, + ty::AssocContainer::TraitImpl(trait_item_id) => { + AssocContainer::TraitImpl(tables.assoc_def(trait_item_id.unwrap())) + } } } } @@ -1100,7 +1107,6 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem { def_id: tables.assoc_def(self.def_id), kind: self.kind.stable(tables, cx), container: self.container.stable(tables, cx), - trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), } } } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index d81fa062e01..577a16a0d25 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -469,8 +469,7 @@ fn implemented_method<'tcx>( let ancestor = if let Some(impl_id) = tcx.impl_of_assoc(instance.def_id()) { // Implementation in an `impl` block trait_ref = tcx.impl_trait_ref(impl_id)?; - let impl_method = tcx.associated_item(instance.def_id()); - method_id = impl_method.trait_item_def_id?; + method_id = tcx.trait_item_of(instance.def_id())?; trait_method = tcx.associated_item(method_id); trait_id = trait_ref.skip_binder().def_id; impl_id diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index e042ce84955..f997842a607 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -857,11 +857,11 @@ fn foo(&self) -> Self::T { String::new() } && self.infcx.can_eq(param_env, assoc_ty, found) { let msg = match assoc_item.container { - ty::AssocItemContainer::Trait => { + ty::AssocContainer::Trait => { "associated type defaults can't be assumed inside the \ trait defining them" } - ty::AssocItemContainer::Impl => { + ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => { "associated type is `default` and may be overridden" } }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 7369134420c..518d4fe17e8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -571,13 +571,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // but right now it's not really very smart when it comes to implicit `Sized` // predicates and bounds on the trait itself. - let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) - else { - return; - }; - let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else { + let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(impl_item_def_id.to_def_id()) else { return; }; + let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); let trait_args = trait_ref .instantiate_identity() // Replace the explicit self type with `Self` for better suggestion rendering diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs index 8a67e4ccd45..f54ebd76cab 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs @@ -5,7 +5,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{LangItem, lang_items}; -use rustc_middle::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv}; +use rustc_middle::ty::{AssocContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv}; use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, sym}; use tracing::debug; @@ -76,8 +76,9 @@ pub fn call_kind<'tcx>( let parent = tcx.opt_associated_item(method_did).and_then(|assoc| { let container_id = assoc.container_id(tcx); match assoc.container { - AssocItemContainer::Impl => tcx.trait_id_of_impl(container_id), - AssocItemContainer::Trait => Some(container_id), + AssocContainer::InherentImpl => None, + AssocContainer::TraitImpl(_) => tcx.trait_id_of_impl(container_id), + AssocContainer::Trait => Some(container_id), } }); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index cb84d583e6e..f2f840581cf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -421,7 +421,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) | hir::Node::ImplItem(hir::ImplItem { generics, - trait_item_def_id: None, + impl_kind: hir::ImplItemImplKind::Inherent { .. }, kind: hir::ImplItemKind::Fn(..), .. }) if finder.can_suggest_bound(generics) => { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 19eb85506b6..4d0465777dd 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -387,7 +387,7 @@ pub(crate) fn assoc_def( if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_def_id) { // Ensure that the impl is constrained, otherwise projection may give us // bad unconstrained infer vars. - if assoc_item.item.container == ty::AssocItemContainer::Impl + if let ty::AssocContainer::TraitImpl(_) = assoc_item.item.container && let Some(impl_def_id) = assoc_item.item.container_id(tcx).as_local() { tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?; diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index e9629e31482..84f52e7fc9d 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -2,7 +2,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, ItemKind}; +use rustc_hir::{self as hir, ImplItemImplKind, ItemKind}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -63,7 +63,7 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems { fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> { tcx.associated_items(impl_id) .in_definition_order() - .filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id))) + .filter_map(|item| item.trait_item_def_id().map(|trait_item| (trait_item, item.def_id))) .collect() } @@ -97,12 +97,7 @@ fn associated_item_from_trait_item( } }; - ty::AssocItem { - kind, - def_id: owner_id.to_def_id(), - trait_item_def_id: Some(owner_id.to_def_id()), - container: ty::AssocItemContainer::Trait, - } + ty::AssocItem { kind, def_id: owner_id.to_def_id(), container: ty::AssocContainer::Trait } } fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> ty::AssocItem { @@ -118,12 +113,13 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_> } }; - ty::AssocItem { - kind, - def_id: owner_id.to_def_id(), - trait_item_def_id: impl_item.trait_item_def_id, - container: ty::AssocItemContainer::Impl, - } + let container = match impl_item.impl_kind { + ImplItemImplKind::Inherent { .. } => ty::AssocContainer::InherentImpl, + ImplItemImplKind::Trait { trait_item_def_id, .. } => { + ty::AssocContainer::TraitImpl(trait_item_def_id) + } + }; + ty::AssocItem { kind, def_id: owner_id.to_def_id(), container } } struct RPITVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -190,7 +186,10 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>( } let did = item.owner_id.def_id.to_def_id(); let item = tcx.hir_impl_item(*item); - let Some(trait_item_def_id) = item.trait_item_def_id else { + let ImplItemImplKind::Trait { + trait_item_def_id: Ok(trait_item_def_id), .. + } = item.impl_kind + else { return Some((did, vec![])); }; let iter = in_trait_def[&trait_item_def_id].iter().map(|&id| { @@ -256,8 +255,7 @@ fn associated_type_for_impl_trait_in_trait( }), }, def_id, - trait_item_def_id: None, - container: ty::AssocItemContainer::Trait, + container: ty::AssocContainer::Trait, }); // Copy visility of the containing function. @@ -322,8 +320,7 @@ fn associated_type_for_impl_trait_in_impl( }), }, def_id, - trait_item_def_id: Some(trait_assoc_def_id), - container: ty::AssocItemContainer::Impl, + container: ty::AssocContainer::TraitImpl(Ok(trait_assoc_def_id)), }); // Copy visility of the containing function. diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index cdfb93c4e7d..543f6a3ccf7 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -107,7 +107,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' // the assumed wf types of the trait's RPITIT GAT. ty::ImplTraitInTraitData::Impl { .. } => { let impl_def_id = tcx.local_parent(def_id); - let rpitit_def_id = tcx.associated_item(def_id).trait_item_def_id.unwrap(); + let rpitit_def_id = tcx.trait_item_of(def_id).unwrap(); let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto( tcx, impl_def_id.to_def_id(), diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4a7263d0ccd..eb3236d3006 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -245,7 +245,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { for &assoc in self.tcx.associated_items(parent).in_definition_order() { trace!(?assoc); - if assoc.trait_item_def_id != Some(alias_ty.def_id) { + if assoc.expect_trait_impl() != Ok(alias_ty.def_id) { continue; } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index b22c326b9f2..a5987757dc3 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -88,7 +88,10 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { }), .. }) - | hir::Node::ImplItem(hir::ImplItem { defaultness, .. }) + | hir::Node::ImplItem(hir::ImplItem { + impl_kind: hir::ImplItemImplKind::Trait { defaultness, .. }, + .. + }) | hir::Node::TraitItem(hir::TraitItem { defaultness, .. }) => *defaultness, node => { bug!("`defaultness` called on {:?}", node); @@ -165,7 +168,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { if tcx.def_kind(def_id) == DefKind::AssocFn && let assoc_item = tcx.associated_item(def_id) - && assoc_item.container == ty::AssocItemContainer::Trait + && assoc_item.container == ty::AssocContainer::Trait && assoc_item.defaultness(tcx).has_value() { let sig = tcx.fn_sig(def_id).instantiate_identity(); |
