about summary refs log tree commit diff
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/query/erase.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs63
-rw-r--r--compiler/rustc_middle/src/ty/context.rs26
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs43
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs14
6 files changed, 84 insertions, 65 deletions
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()
     }
 }