Split AssocContainer::{InherentImpl,TraitImpl}

This commit is contained in:
Cameron Steffen 2025-08-13 15:24:19 -05:00
parent 88a8bfcaf0
commit 9615ec7d10
33 changed files with 173 additions and 229 deletions

View file

@ -1009,7 +1009,7 @@ 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::AssocContainer::Impl => {}
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {}
ty::AssocContainer::Trait => {
res = res.and(check_trait_item(tcx, def_id));
}
@ -1026,7 +1026,7 @@ 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::AssocContainer::Impl => {}
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {}
ty::AssocContainer::Trait => {
res = res.and(check_trait_item(tcx, def_id));
}
@ -1043,7 +1043,7 @@ 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::AssocContainer::Impl => true,
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);
@ -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());

View file

@ -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,7 +1449,9 @@ fn compare_self_type<'tcx>(
let self_string = |method: ty::AssocItem| {
let untransformed_self_ty = match method.container {
ty::AssocContainer::Impl => impl_trait_ref.self_ty(),
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);
@ -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::AssocContainer::InherentImpl => bug!(),
ty::AssocContainer::Trait => impl_ty,
ty::AssocContainer::Impl => tcx.associated_item(impl_ty.trait_item_def_id.unwrap()),
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]> =

View file

@ -944,12 +944,13 @@ 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::AssocContainer::Trait => tcx.types.self_param,
ty::AssocContainer::Impl => tcx.type_of(item.container_id(tcx)).instantiate_identity(),
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
tcx.type_of(item.container_id(tcx)).instantiate_identity()
}
};
let span = tcx.def_span(item_id);

View file

@ -1033,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.set_tainted_by_errors(e);
}
}
ty::AssocContainer::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

View file

@ -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)

View file

@ -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::AssocContainer::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();

View file

@ -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: _,

View file

@ -34,7 +34,7 @@ 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() {

View file

@ -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,24 +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::AssocContainer::Trait => MethodLateContext::TraitAutoImpl,
ty::AssocContainer::Impl => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
Some(_) => MethodLateContext::TraitImpl,
None => MethodLateContext::PlainImpl,
},
}
}
declare_lint! {
/// The `non_camel_case_types` lint detects types, variants, traits and
/// type parameters that don't have camel case names.
@ -384,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(..))
{
@ -393,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)

View file

@ -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)> {

View file

@ -1254,7 +1254,7 @@ 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::AssocContainer::Impl => true,
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(),
}
}
@ -1726,23 +1726,16 @@ impl<'a, 'tcx> EncodeContext<'a, '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);
record!(self.tables.assoc_container[def_id] <- item.container);
match item.container {
AssocContainer::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());
}
}
}
AssocContainer::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 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 {

View file

@ -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::AssocContainer>,
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>>,

View file

@ -221,13 +221,6 @@ fixed_size_enum! {
}
}
fixed_size_enum! {
ty::AssocContainer {
( Trait )
( Impl )
}
}
fixed_size_enum! {
MacroKind {
( Attr )

View file

@ -5,7 +5,7 @@ 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;
@ -13,7 +13,9 @@ use crate::ty;
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)]
pub enum AssocContainer {
Trait,
Impl,
InherentImpl,
/// The `DefId` points to the trait item being implemented.
TraitImpl(Result<DefId, ErrorGuaranteed>),
}
/// Information about an associated item
@ -22,10 +24,6 @@ pub struct AssocItem {
pub def_id: DefId,
pub kind: AssocKind,
pub container: AssocContainer,
/// 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>,
}
impl AssocItem {
@ -58,6 +56,30 @@ impl AssocItem {
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]
pub fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility<DefId> {
tcx.visibility(self.def_id)
@ -71,7 +93,7 @@ impl AssocItem {
#[inline]
pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
match self.container {
AssocContainer::Impl => None,
AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => None,
AssocContainer::Trait => Some(tcx.parent(self.def_id)),
}
}
@ -79,7 +101,9 @@ impl AssocItem {
#[inline]
pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
match self.container {
AssocContainer::Impl => Some(tcx.parent(self.def_id)),
AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => {
Some(tcx.parent(self.def_id))
}
AssocContainer::Trait => None,
}
}
@ -156,11 +180,11 @@ impl AssocItem {
return false;
}
let def_id = match (self.container, self.trait_item_def_id) {
(AssocContainer::Trait, _) => self.def_id,
(AssocContainer::Impl, Some(trait_item_did)) => trait_item_did,
// Inherent impl but this attr is only applied to trait assoc items.
(AssocContainer::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(_))
}

View file

@ -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)
}
}
_ => {}
}

View file

@ -1936,11 +1936,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// 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> {
let assoc = self.opt_associated_item(def_id.into_query_param())?;
if assoc.container != AssocContainer::Impl {
return None;
}
assoc.trait_item_def_id
self.opt_associated_item(def_id.into_query_param())?.trait_item_def_id()
}
/// If the given `DefId` is an associated item of a trait,
@ -2158,17 +2154,12 @@ impl<'tcx> TyCtxt<'tcx> {
let Some(item) = self.opt_associated_item(def_id) else {
return false;
};
if item.container != ty::AssocContainer::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()
}
}

View file

@ -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};
@ -710,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,

View file

@ -1613,10 +1613,6 @@ pub struct AssocItem {
pub def_id: AssocDef,
pub kind: AssocKind,
pub container: AssocContainer,
/// 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>,
}
#[derive(Clone, PartialEq, Debug, Eq, Serialize)]
@ -1637,8 +1633,10 @@ pub enum AssocKind {
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
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)]

View file

@ -1079,11 +1079,18 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind {
impl<'tcx> Stable<'tcx> for ty::AssocContainer {
type T = crate::ty::AssocContainer;
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
fn stable(
&self,
tables: &mut Tables<'_, BridgeTys>,
_: &CompilerCtxt<'_, BridgeTys>,
) -> Self::T {
use crate::ty::AssocContainer;
match self {
ty::AssocContainer::Trait => AssocContainer::Trait,
ty::AssocContainer::Impl => AssocContainer::Impl,
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)),
}
}
}

View file

@ -861,7 +861,7 @@ fn foo(&self) -> Self::T { String::new() }
"associated type defaults can't be assumed inside the \
trait defining them"
}
ty::AssocContainer::Impl => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
"associated type is `default` and may be overridden"
}
};

View file

@ -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

View file

@ -76,7 +76,8 @@ 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 {
AssocContainer::Impl => tcx.trait_id_of_impl(container_id),
AssocContainer::InherentImpl => None,
AssocContainer::TraitImpl(_) => tcx.trait_id_of_impl(container_id),
AssocContainer::Trait => Some(container_id),
}
});

View file

@ -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::AssocContainer::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)?;

View file

@ -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::AssocContainer::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,15 +113,13 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>
}
};
ty::AssocItem {
kind,
def_id: owner_id.to_def_id(),
container: ty::AssocContainer::Impl,
trait_item_def_id: match impl_item.impl_kind {
ImplItemImplKind::Inherent { .. } => None,
ImplItemImplKind::Trait { trait_item_def_id, .. } => trait_item_def_id.ok(),
},
}
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>,
@ -262,7 +255,6 @@ fn associated_type_for_impl_trait_in_trait(
}),
},
def_id,
trait_item_def_id: None,
container: ty::AssocContainer::Trait,
});
@ -328,8 +320,7 @@ fn associated_type_for_impl_trait_in_impl(
}),
},
def_id,
trait_item_def_id: Some(trait_assoc_def_id),
container: ty::AssocContainer::Impl,
container: ty::AssocContainer::TraitImpl(Ok(trait_assoc_def_id)),
});
// Copy visility of the containing function.

View file

@ -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;
}

View file

@ -1295,11 +1295,13 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
simplify::move_bounds_to_generic_parameters(&mut generics);
match assoc_item.container {
ty::AssocContainer::Impl => ImplAssocConstItem(Box::new(Constant {
generics,
kind: ConstantKind::Extern { def_id: assoc_item.def_id },
type_: ty,
})),
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
ImplAssocConstItem(Box::new(Constant {
generics,
kind: ConstantKind::Extern { def_id: assoc_item.def_id },
type_: ty,
}))
}
ty::AssocContainer::Trait => {
if tcx.defaultness(assoc_item.def_id).has_value() {
ProvidedAssocConstItem(Box::new(Constant {
@ -1318,7 +1320,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
if has_self {
let self_ty = match assoc_item.container {
ty::AssocContainer::Impl => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity()
}
ty::AssocContainer::Trait => tcx.types.self_param,
@ -1338,13 +1340,13 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
}
let provided = match assoc_item.container {
ty::AssocContainer::Impl => true,
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(),
};
if provided {
let defaultness = match assoc_item.container {
ty::AssocContainer::Impl => Some(assoc_item.defaultness(tcx)),
ty::AssocContainer::Trait => None,
ty::AssocContainer::TraitImpl(_) => Some(assoc_item.defaultness(tcx)),
ty::AssocContainer::InherentImpl | ty::AssocContainer::Trait => None,
};
MethodItem(item, defaultness)
} else {

View file

@ -690,16 +690,13 @@ impl Item {
// rustc's `is_const_fn` returns `true` for associated functions that have an `impl const` parent
// or that have a `const trait` parent. Do not display those as `const` in rustdoc because we
// won't be printing correct syntax plus the syntax is unstable.
match tcx.opt_associated_item(def_id) {
Some(ty::AssocItem {
container: ty::AssocContainer::Impl,
trait_item_def_id: Some(_),
..
})
| Some(ty::AssocItem { container: ty::AssocContainer::Trait, .. }) => {
hir::Constness::NotConst
}
None | Some(_) => hir::Constness::Const,
if let Some(assoc) = tcx.opt_associated_item(def_id)
&& let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
assoc.container
{
hir::Constness::NotConst
} else {
hir::Constness::Const
}
} else {
hir::Constness::NotConst
@ -779,17 +776,13 @@ impl Item {
| RequiredAssocTypeItem(..)
| RequiredMethodItem(..)
| MethodItem(..) => {
let assoc_item = tcx.associated_item(def_id);
let is_trait_item = match assoc_item.container {
ty::AssocContainer::Trait => true,
ty::AssocContainer::Impl => {
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some()
match tcx.associated_item(def_id).container {
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
return None;
}
};
if is_trait_item {
return None;
ty::AssocContainer::InherentImpl => {}
}
}
_ => {}

View file

@ -16,7 +16,7 @@ use rustc_hir::Attribute;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::Visibility;
use rustc_middle::ty::{AssocContainer, Visibility};
use rustc_session::impl_lint_pass;
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::symbol::kw;
@ -246,12 +246,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
// If the method is an impl for a trait, don't doc.
if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) {
if cx.tcx.impl_trait_ref(cid).is_some() {
match cx.tcx.associated_item(impl_item.owner_id).container {
AssocContainer::Trait | AssocContainer::TraitImpl(_) => {
note_prev_span_then_ret!(self.prev_span, impl_item.span);
}
} else {
note_prev_span_then_ret!(self.prev_span, impl_item.span);
},
AssocContainer::InherentImpl => {}
}
let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());

View file

@ -167,7 +167,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
let container_id = assoc_item.container_id(cx.tcx);
let trait_def_id = match assoc_item.container {
AssocContainer::Trait => Some(container_id),
AssocContainer::Impl => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
AssocContainer::TraitImpl(_) => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
AssocContainer::InherentImpl => None,
};
if let Some(trait_def_id) = trait_def_id

View file

@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
.tcx
.associated_items(item.owner_id)
.in_definition_order()
.filter_map(|assoc_item| assoc_item.trait_item_def_id)
.filter_map(|assoc_item| assoc_item.expect_trait_impl().ok())
.collect();
for assoc in cx

View file

@ -3251,7 +3251,7 @@ pub fn get_path_from_caller_to_method_type<'tcx>(
let def_id = assoc_item.container_id(tcx);
match assoc_item.container {
rustc_ty::AssocContainer::Trait => get_path_to_callee(tcx, from, def_id),
rustc_ty::AssocContainer::Impl => {
rustc_ty::AssocContainer::InherentImpl | rustc_ty::AssocContainer::TraitImpl(_) => {
let ty = tcx.type_of(def_id).instantiate_identity();
get_path_to_ty(tcx, from, ty, args)
},

View file

@ -11,7 +11,6 @@ where
{
fn unimplemented(self, _: &Foo) -> Self::Output {
//~^ ERROR method `unimplemented` is not a member of trait `std::ops::Add`
//~| ERROR type annotations needed
loop {}
}
}

View file

@ -3,7 +3,6 @@ error[E0407]: method `unimplemented` is not a member of trait `std::ops::Add`
|
LL | / fn unimplemented(self, _: &Foo) -> Self::Output {
LL | |
LL | |
LL | | loop {}
LL | | }
| |_____^ not a member of trait `std::ops::Add`
@ -39,21 +38,7 @@ LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
= note: expressions using a const parameter must map each value to a distinct output value
= note: proving the result of expressions other than the parameter are unique is not supported
error[E0284]: type annotations needed
--> $DIR/post-analysis-user-facing-param-env.rs:12:40
|
LL | fn unimplemented(self, _: &Foo) -> Self::Output {
| ^^^^^^^^^^^^ cannot infer the value of const parameter `NUM`
|
note: required for `Foo` to implement `Add<&'a Foo>`
--> $DIR/post-analysis-user-facing-param-env.rs:6:28
|
LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
| ---------------- ^^^^^^^^^^^^^^^^^^^^^^ ^^^
| |
| unsatisfied trait bound introduced here
error: aborting due to 3 previous errors; 1 warning emitted
error: aborting due to 4 previous errors; 1 warning emitted
Some errors have detailed explanations: E0046, E0207, E0284, E0407.
Some errors have detailed explanations: E0046, E0207, E0407.
For more information about an error, try `rustc --explain E0046`.