diff options
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/ty/assoc.rs | 50 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/instance.rs | 41 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 15 |
3 files changed, 59 insertions, 47 deletions
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 8a2f62ce833..60181783f9b 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -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(_)) } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index ec2a23bfebe..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) + } } _ => {} } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a34bf9b5297..d4c001f625e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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() } } |
