Move name
field from AssocItem
to AssocKind
variants.
To accurately reflect that RPITIT assoc items don't have a name. This avoids the use of `kw::Empty` to mean "no name", which is error prone. Helps with #137978.
This commit is contained in:
parent
89e93a51c8
commit
78599d83e7
43 changed files with 276 additions and 231 deletions
|
@ -18,7 +18,6 @@ pub enum AssocItemContainer {
|
|||
#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash, Encodable, Decodable)]
|
||||
pub struct AssocItem {
|
||||
pub def_id: DefId,
|
||||
pub name: Symbol,
|
||||
pub kind: AssocKind,
|
||||
pub container: AssocItemContainer,
|
||||
|
||||
|
@ -28,8 +27,24 @@ pub struct AssocItem {
|
|||
}
|
||||
|
||||
impl AssocItem {
|
||||
// Gets the identifier, if it has one.
|
||||
pub fn opt_name(&self) -> Option<Symbol> {
|
||||
match self.kind {
|
||||
ty::AssocKind::Type { data: AssocTypeData::Normal(name) } => Some(name),
|
||||
ty::AssocKind::Type { data: AssocTypeData::Rpitit(_) } => None,
|
||||
ty::AssocKind::Const { name } => Some(name),
|
||||
ty::AssocKind::Fn { name, .. } => Some(name),
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the identifier name. Aborts if it lacks one, i.e. is an RPITIT
|
||||
// associated type.
|
||||
pub fn name(&self) -> Symbol {
|
||||
self.opt_name().expect("name of non-Rpitit assoc item")
|
||||
}
|
||||
|
||||
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
|
||||
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
|
||||
Ident::new(self.name(), tcx.def_ident_span(self.def_id).unwrap())
|
||||
}
|
||||
|
||||
/// Gets the defaultness of the associated item.
|
||||
|
@ -76,22 +91,18 @@ impl AssocItem {
|
|||
// regions just fine, showing `fn(&MyType)`.
|
||||
tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string()
|
||||
}
|
||||
ty::AssocKind::Type { .. } => format!("type {};", self.name),
|
||||
ty::AssocKind::Const => {
|
||||
format!(
|
||||
"const {}: {:?};",
|
||||
self.name,
|
||||
tcx.type_of(self.def_id).instantiate_identity()
|
||||
)
|
||||
ty::AssocKind::Type { .. } => format!("type {};", self.name()),
|
||||
ty::AssocKind::Const { name } => {
|
||||
format!("const {}: {:?};", name, tcx.type_of(self.def_id).instantiate_identity())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self.kind {
|
||||
ty::AssocKind::Const => "associated const",
|
||||
ty::AssocKind::Fn { has_self: true } => "method",
|
||||
ty::AssocKind::Fn { has_self: false } => "associated function",
|
||||
ty::AssocKind::Const { .. } => "associated const",
|
||||
ty::AssocKind::Fn { has_self: true, .. } => "method",
|
||||
ty::AssocKind::Fn { has_self: false, .. } => "associated function",
|
||||
ty::AssocKind::Type { .. } => "associated type",
|
||||
}
|
||||
}
|
||||
|
@ -99,13 +110,13 @@ impl AssocItem {
|
|||
pub fn namespace(&self) -> Namespace {
|
||||
match self.kind {
|
||||
ty::AssocKind::Type { .. } => Namespace::TypeNS,
|
||||
ty::AssocKind::Const | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_def_kind(&self) -> DefKind {
|
||||
match self.kind {
|
||||
AssocKind::Const => DefKind::AssocConst,
|
||||
AssocKind::Const { .. } => DefKind::AssocConst,
|
||||
AssocKind::Fn { .. } => DefKind::AssocFn,
|
||||
AssocKind::Type { .. } => DefKind::AssocTy,
|
||||
}
|
||||
|
@ -119,19 +130,19 @@ impl AssocItem {
|
|||
}
|
||||
|
||||
pub fn is_method(&self) -> bool {
|
||||
matches!(self.kind, ty::AssocKind::Fn { has_self: true })
|
||||
matches!(self.kind, ty::AssocKind::Fn { has_self: true, .. })
|
||||
}
|
||||
|
||||
pub fn as_tag(&self) -> AssocTag {
|
||||
match self.kind {
|
||||
AssocKind::Const => AssocTag::Const,
|
||||
AssocKind::Const { .. } => AssocTag::Const,
|
||||
AssocKind::Fn { .. } => AssocTag::Fn,
|
||||
AssocKind::Type { .. } => AssocTag::Type,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_impl_trait_in_trait(&self) -> bool {
|
||||
matches!(self.kind, AssocKind::Type { opt_rpitit_info: Some(_) })
|
||||
matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) })
|
||||
}
|
||||
|
||||
/// Returns true if:
|
||||
|
@ -139,7 +150,7 @@ impl AssocItem {
|
|||
/// - If it is in a trait impl, the item from the original trait has this attribute, or
|
||||
/// - It is an inherent assoc const.
|
||||
pub fn is_type_const_capable(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
if self.kind != ty::AssocKind::Const {
|
||||
if !matches!(self.kind, ty::AssocKind::Const { .. }) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -153,26 +164,45 @@ impl AssocItem {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
|
||||
pub enum AssocTypeData {
|
||||
Normal(Symbol),
|
||||
/// The associated type comes from an RPITIT. It has no name, and the
|
||||
/// `ImplTraitInTraitData` provides additional information about its
|
||||
/// source.
|
||||
Rpitit(ty::ImplTraitInTraitData),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
|
||||
pub enum AssocKind {
|
||||
Const,
|
||||
Fn {
|
||||
has_self: bool,
|
||||
},
|
||||
Type {
|
||||
/// `Some` if the associated type comes from an RPITIT. The
|
||||
/// `ImplTraitInTraitData` provides additional information about its
|
||||
/// source.
|
||||
opt_rpitit_info: Option<ty::ImplTraitInTraitData>,
|
||||
},
|
||||
Const { name: Symbol },
|
||||
Fn { name: Symbol, has_self: bool },
|
||||
Type { data: AssocTypeData },
|
||||
}
|
||||
|
||||
impl AssocKind {
|
||||
pub fn namespace(&self) -> Namespace {
|
||||
match *self {
|
||||
ty::AssocKind::Type { .. } => Namespace::TypeNS,
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_def_kind(&self) -> DefKind {
|
||||
match self {
|
||||
AssocKind::Const { .. } => DefKind::AssocConst,
|
||||
AssocKind::Fn { .. } => DefKind::AssocFn,
|
||||
AssocKind::Type { .. } => DefKind::AssocTy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AssocKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AssocKind::Fn { has_self: true } => write!(f, "method"),
|
||||
AssocKind::Fn { has_self: false } => write!(f, "associated function"),
|
||||
AssocKind::Const => write!(f, "associated const"),
|
||||
AssocKind::Fn { has_self: true, .. } => write!(f, "method"),
|
||||
AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"),
|
||||
AssocKind::Const { .. } => write!(f, "associated const"),
|
||||
AssocKind::Type { .. } => write!(f, "associated type"),
|
||||
}
|
||||
}
|
||||
|
@ -193,17 +223,17 @@ pub enum AssocTag {
|
|||
/// done only on items with the same name.
|
||||
#[derive(Debug, Clone, PartialEq, HashStable)]
|
||||
pub struct AssocItems {
|
||||
items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
|
||||
items: SortedIndexMultiMap<u32, Option<Symbol>, ty::AssocItem>,
|
||||
}
|
||||
|
||||
impl AssocItems {
|
||||
/// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
|
||||
pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
|
||||
let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect();
|
||||
let items = items_in_def_order.into_iter().map(|item| (item.opt_name(), item)).collect();
|
||||
AssocItems { items }
|
||||
}
|
||||
|
||||
/// Returns a slice of associated items in the order they were defined.
|
||||
/// Returns an iterator over associated items in the order they were defined.
|
||||
///
|
||||
/// New code should avoid relying on definition order. If you need a particular associated item
|
||||
/// for a known trait, make that trait a lang item instead of indexing this array.
|
||||
|
@ -220,7 +250,8 @@ impl AssocItems {
|
|||
&self,
|
||||
name: Symbol,
|
||||
) -> impl '_ + Iterator<Item = &ty::AssocItem> {
|
||||
self.items.get_by_key(name)
|
||||
assert!(!name.is_empty());
|
||||
self.items.get_by_key(Some(name))
|
||||
}
|
||||
|
||||
/// Returns the associated item with the given identifier and `AssocKind`, if one exists.
|
||||
|
|
|
@ -1611,9 +1611,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// about where that RPITIT came from.
|
||||
pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> {
|
||||
if let DefKind::AssocTy = self.def_kind(def_id)
|
||||
&& let AssocKind::Type { opt_rpitit_info } = self.associated_item(def_id).kind
|
||||
&& let AssocKind::Type { data: AssocTypeData::Rpitit(rpitit_info) } =
|
||||
self.associated_item(def_id).kind
|
||||
{
|
||||
opt_rpitit_info
|
||||
Some(rpitit_info)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -1214,7 +1214,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
&& assoc
|
||||
.trait_container(tcx)
|
||||
.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine))
|
||||
&& assoc.name == rustc_span::sym::Return
|
||||
&& assoc.opt_name() == Some(rustc_span::sym::Return)
|
||||
{
|
||||
if let ty::Coroutine(_, args) = args.type_at(0).kind() {
|
||||
let return_ty = args.as_coroutine().return_ty();
|
||||
|
@ -1237,7 +1237,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
p!(", ");
|
||||
}
|
||||
|
||||
p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name));
|
||||
p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name()));
|
||||
|
||||
match term.unpack() {
|
||||
TermKind::Ty(ty) => p!(print(ty)),
|
||||
|
@ -3291,7 +3291,7 @@ define_print! {
|
|||
}
|
||||
|
||||
ty::ExistentialProjection<'tcx> {
|
||||
let name = cx.tcx().associated_item(self.def_id).name;
|
||||
let name = cx.tcx().associated_item(self.def_id).name();
|
||||
// The args don't contain the self ty (as it has been erased) but the corresp.
|
||||
// generics do as the trait always has a self ty param. We need to offset.
|
||||
let args = &self.args[cx.tcx().generics_of(self.def_id).parent_count - 1..];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue