diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index ce4c08aa485e5..3bb70e1f55137 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -8,6 +8,7 @@ use rustc_span::{Ident, Symbol, sym}; use super::{TyCtxt, Visibility}; use crate::ty; +/// Indicates whether an associated item is defined in a trait or an impl block. #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)] pub enum AssocItemContainer { Trait, @@ -128,6 +129,7 @@ impl AssocItem { } } +/// Represents the kind of an associated item. #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)] pub enum AssocKind { Const, diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index bb2b2dea2f37f..1b6f908bfe2f9 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -12,10 +12,11 @@ use stable_mir::mir::alloc::AllocId; use stable_mir::mir::mono::{Instance, MonoItem, StaticDef}; use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp}; use stable_mir::ty::{ - Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind, - ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, - GenericArgKind, GenericArgs, IndexedVal, IntTy, MirConst, Movability, Pattern, Region, RigidTy, - Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx, + Abi, AdtDef, AssocItem, AssocItemContainer, AssocKind, Binder, BoundRegionKind, BoundTyKind, + BoundVariableKind, ClosureKind, DynKind, ExistentialPredicate, ExistentialProjection, + ExistentialTraitRef, FloatTy, FnSig, GenericArgKind, GenericArgs, ImplTraitInTraitData, + IndexedVal, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span, TermKind, TraitRef, + Ty, TyConst, UintTy, VariantDef, VariantIdx, }; use stable_mir::{CrateItem, CrateNum, DefId}; @@ -570,6 +571,65 @@ impl RustcInternal for ProjectionElem { } } +impl RustcInternal for AssocItem { + type T<'tcx> = rustc_middle::ty::AssocItem; + + fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { + rustc_middle::ty::AssocItem { + def_id: self.def_id.0.internal(tables, tcx), + name: Symbol::intern(&self.name), + kind: self.kind.internal(tables, tcx), + container: self.container.internal(tables, tcx), + trait_item_def_id: self.trait_item_def_id.map(|did| did.0.internal(tables, tcx)), + fn_has_self_parameter: self.fn_has_self_parameter, + opt_rpitit_info: self.opt_rpitit_info.map(|did| did.internal(tables, tcx)), + } + } +} + +impl RustcInternal for AssocItemContainer { + type T<'tcx> = rustc_middle::ty::AssocItemContainer; + + fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { + match self { + AssocItemContainer::Trait => rustc_middle::ty::AssocItemContainer::Trait, + AssocItemContainer::Impl => rustc_middle::ty::AssocItemContainer::Impl, + } + } +} + +impl RustcInternal for AssocKind { + type T<'tcx> = rustc_middle::ty::AssocKind; + + fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { + match self { + AssocKind::Const => rustc_middle::ty::AssocKind::Const, + AssocKind::Fn => rustc_middle::ty::AssocKind::Fn, + AssocKind::Type => rustc_middle::ty::AssocKind::Type, + } + } +} + +impl RustcInternal for ImplTraitInTraitData { + type T<'tcx> = rustc_middle::ty::ImplTraitInTraitData; + + fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { + match self { + ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { + rustc_middle::ty::ImplTraitInTraitData::Trait { + fn_def_id: fn_def_id.0.internal(tables, tcx), + opaque_def_id: opaque_def_id.0.internal(tables, tcx), + } + } + ImplTraitInTraitData::Impl { fn_def_id } => { + rustc_middle::ty::ImplTraitInTraitData::Impl { + fn_def_id: fn_def_id.0.internal(tables, tcx), + } + } + } + } +} + impl RustcInternal for BinOp { type T<'tcx> = rustc_middle::mir::BinOp; diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index ad38ea228bf53..30e9b2e72f735 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -147,6 +147,14 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::CoroutineWitnessDef(self.create_def_id(did)) } + pub fn assoc_def(&mut self, did: DefId) -> stable_mir::ty::AssocDef { + stable_mir::ty::AssocDef(self.create_def_id(did)) + } + + pub fn opaque_def(&mut self, did: DefId) -> stable_mir::ty::OpaqueDef { + stable_mir::ty::OpaqueDef(self.create_def_id(did)) + } + pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov { stable_mir::ty::Prov(self.create_alloc_id(aid)) } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index aa1921fc8e784..322e86147c19b 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -822,6 +822,21 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let ty = un_op.internal(&mut *tables, tcx).ty(tcx, arg_internal); ty.stable(&mut *tables) } + + fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let def_id = tables[def_id]; + let assoc_items = if tcx.is_trait_alias(def_id) { + Vec::new() + } else { + tcx.associated_item_def_ids(def_id) + .iter() + .map(|did| tcx.associated_item(*did).stable(&mut *tables)) + .collect() + }; + assoc_items + } } pub(crate) struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index aa0eac628dd0f..8309809d7b51c 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -890,3 +890,63 @@ impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { } } } + +impl<'tcx> Stable<'tcx> for ty::AssocKind { + type T = stable_mir::ty::AssocKind; + + fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::AssocKind; + match self { + ty::AssocKind::Const => AssocKind::Const, + ty::AssocKind::Fn => AssocKind::Fn, + ty::AssocKind::Type => AssocKind::Type, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { + type T = stable_mir::ty::AssocItemContainer; + + fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::AssocItemContainer; + match self { + ty::AssocItemContainer::Trait => AssocItemContainer::Trait, + ty::AssocItemContainer::Impl => AssocItemContainer::Impl, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::AssocItem { + type T = stable_mir::ty::AssocItem; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + stable_mir::ty::AssocItem { + def_id: tables.assoc_def(self.def_id), + name: self.name.to_string(), + kind: self.kind.stable(tables), + container: self.container.stable(tables), + trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), + fn_has_self_parameter: self.fn_has_self_parameter, + opt_rpitit_info: self.opt_rpitit_info.map(|rpitit| rpitit.stable(tables)), + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { + type T = stable_mir::ty::ImplTraitInTraitData; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + use stable_mir::ty::ImplTraitInTraitData; + match self { + ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { + ImplTraitInTraitData::Trait { + fn_def_id: tables.fn_def(*fn_def_id), + opaque_def_id: tables.opaque_def(*opaque_def_id), + } + } + ty::ImplTraitInTraitData::Impl { fn_def_id } => { + ImplTraitInTraitData::Impl { fn_def_id: tables.fn_def(*fn_def_id) } + } + } + } +} diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index e82c957c34ea6..46154da36ca07 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -18,8 +18,8 @@ use crate::ty::{ TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, }; use crate::{ - Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, - Symbol, TraitDecls, mir, + AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, + ItemKind, Symbol, TraitDecls, mir, }; /// This trait defines the interface between stable_mir and the Rust compiler. @@ -251,6 +251,9 @@ pub trait Context { /// Get the resulting type of unary operation. fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty; + + /// Get all associated items of a definition. + fn associated_items(&self, def_id: DefId) -> AssocItems; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs index 2577c281ca4f2..75228135e4cb3 100644 --- a/compiler/stable_mir/src/crate_def.rs +++ b/compiler/stable_mir/src/crate_def.rs @@ -4,7 +4,7 @@ use serde::Serialize; use crate::ty::{GenericArgs, Span, Ty}; -use crate::{Crate, Symbol, with}; +use crate::{AssocItems, Crate, Symbol, with}; /// A unique identification number for each item accessible for the current compilation unit. #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] @@ -103,6 +103,14 @@ pub trait CrateDefType: CrateDef { } } +/// A trait for retrieving all items from a definition within a crate. +pub trait CrateDefItems: CrateDef { + /// Retrieve all associated items from a definition. + fn associated_items(&self) -> AssocItems { + with(|cx| cx.associated_items(self.def_id())) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct Attribute { value: String, @@ -158,3 +166,9 @@ macro_rules! crate_def_with_ty { impl CrateDefType for $name {} }; } + +macro_rules! impl_crate_def_items { + ( $name:ident $(;)? ) => { + impl CrateDefItems for $name {} + }; +} diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 70d42dfbfcb9a..df90d3e5a0841 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -23,11 +23,11 @@ use std::{fmt, io}; use serde::Serialize; use crate::compiler_interface::with; -pub use crate::crate_def::{CrateDef, CrateDefType, DefId}; +pub use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId}; pub use crate::error::*; use crate::mir::mono::StaticDef; use crate::mir::{Body, Mutability}; -use crate::ty::{FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; +use crate::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; pub mod abi; #[macro_use] @@ -71,6 +71,9 @@ pub type TraitDecls = Vec<TraitDef>; /// A list of impl trait decls. pub type ImplTraitDecls = Vec<ImplDef>; +/// A list of associated items. +pub type AssocItems = Vec<AssocItem>; + /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub struct Crate { diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 8278afb7a2f17..65d9f20f0a3b1 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -9,7 +9,7 @@ use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, Ter use crate::mir::{ Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents, }; -use crate::ty::{AdtKind, IndexedVal, MirConst, Ty, TyConst}; +use crate::ty::{AdtKind, AssocKind, IndexedVal, MirConst, Ty, TyConst}; use crate::{Body, CrateDef, Mutability, with}; impl Display for Ty { @@ -18,6 +18,16 @@ impl Display for Ty { } } +impl Display for AssocKind { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + AssocKind::Fn => write!(f, "method"), + AssocKind::Const => write!(f, "associated const"), + AssocKind::Type => write!(f, "associated type"), + } + } +} + impl Debug for Place { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { with(|ctx| write!(f, "{}", ctx.place_pretty(self))) diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index b857a735b7259..836ee3f7262dc 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -6,11 +6,11 @@ use serde::Serialize; use super::mir::{Body, Mutability, Safety}; use super::{DefId, Error, Symbol, with}; use crate::abi::{FnAbi, Layout}; -use crate::crate_def::{CrateDef, CrateDefType}; +use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType}; use crate::mir::alloc::{AllocId, read_target_int, read_target_uint}; use crate::mir::mono::StaticDef; use crate::target::MachineInfo; -use crate::{Filename, Opaque}; +use crate::{AssocItems, Filename, Opaque}; #[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)] pub struct Ty(usize); @@ -773,6 +773,15 @@ pub enum AdtKind { Struct, } +impl CrateDefItems for AdtDef { + fn associated_items(&self) -> AssocItems { + match &self.kind() { + AdtKind::Enum | AdtKind::Struct => with(|cx| cx.associated_items(self.def_id())), + AdtKind::Union => Vec::new(), + } + } +} + impl AdtDef { pub fn kind(&self) -> AdtKind { with(|cx| cx.adt_kind(*self)) @@ -910,6 +919,10 @@ crate_def! { pub TraitDef; } +impl_crate_def_items! { + TraitDef; +} + impl TraitDef { pub fn declaration(trait_def: &TraitDef) -> TraitDecl { with(|cx| cx.trait_decl(trait_def)) @@ -932,6 +945,10 @@ crate_def! { pub ImplDef; } +impl_crate_def_items! { + ImplDef; +} + impl ImplDef { /// Retrieve information about this implementation. pub fn trait_impl(&self) -> ImplTrait { @@ -1555,3 +1572,60 @@ index_impl!(Span); pub struct VariantIdx(usize); index_impl!(VariantIdx); + +crate_def! { + /// Hold infomation about an Opaque definition, particularly useful in `RPITIT`. + #[derive(Serialize)] + pub OpaqueDef; +} + +crate_def! { + #[derive(Serialize)] + pub AssocDef; +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub struct AssocItem { + pub def_id: AssocDef, + pub name: Symbol, + 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>, + + /// Whether this is a method with an explicit self + /// as its first parameter, allowing method calls. + pub fn_has_self_parameter: bool, + + /// `Some` if the associated item (an associated type) comes from the + /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData` + /// provides additional information about its source. + pub opt_rpitit_info: Option<ImplTraitInTraitData>, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub enum AssocKind { + Const, + Fn, + Type, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub enum AssocItemContainer { + Trait, + Impl, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] +pub enum ImplTraitInTraitData { + Trait { fn_def_id: FnDef, opaque_def_id: OpaqueDef }, + Impl { fn_def_id: FnDef }, +} + +impl AssocItem { + pub fn is_impl_trait_in_trait(&self) -> bool { + self.opt_rpitit_info.is_some() + } +}