use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;
use crate::rustc_data_structures::fx::FxIndexMap;
use crate::rustc_hir::attrs::{EiiDecl, EiiImpl, EiiImplResolution};
use crate::rustc_hir::def_id::DefId;
use crate::find_attr;
use crate::bug;
use crate::rustc_middle::query::LocalCrate;
use crate::rustc_middle::ty::TyCtxt;
pub(crate) type EiiMapEncodedKeyValue = (DefId, (EiiDecl, Vec<(DefId, EiiImpl)>));
pub(crate) type EiiMap = FxIndexMap<
DefId, (
// the corresponding declaration
EiiDecl,
// all the given implementations, indexed by defid.
// We expect there to be only one, but collect them all to give errors if there are more
// (or if there are none) in the final crate we build.
FxIndexMap<DefId, EiiImpl>,
),
>;
pub(crate) fn collect<'tcx>(tcx: TyCtxt<'tcx>, LocalCrate: LocalCrate) -> EiiMap {
let mut eiis = EiiMap::default();
let decls_by_foreign_item: FxIndexMap<DefId, EiiDecl> = tcx
.hir_crate_items(())
.eiis()
.filter_map(|id| find_attr!(tcx, id, EiiDeclaration(d) => *d))
.map(|decl| (decl.foreign_item, decl))
.collect();
for id in tcx.hir_crate_items(()).eiis() {
if let Some(decl) = find_attr!(tcx, id, EiiDeclaration(d) => *d) {
eiis.entry(decl.foreign_item).or_insert((decl, Default::default()));
}
if let Some(i) = find_attr!(tcx, id, EiiImpl(i) => i) {
let (foreign_item, decl) = match i.resolution {
EiiImplResolution::Macro(macro_defid) => {
let Some(decl) = find_attr!(tcx, macro_defid, EiiDeclaration(d) => *d) else {
tcx.dcx()
.span_delayed_bug(i.span, "resolved to something that's not an EII");
continue;
};
(decl.foreign_item, decl)
}
EiiImplResolution::Known(foreign_item_did) => {
let decl = decls_by_foreign_item.get(&foreign_item_did).unwrap_or_else(|| {
bug!(
"EII impl has Known resolution but can't find EiiDeclaration for {:?}",
foreign_item_did
)
});
(foreign_item_did, *decl)
}
EiiImplResolution::Error(_eg) => continue,
};
eiis.entry(foreign_item)
.or_insert_with(|| (decl, Default::default()))
.1
.insert(id.into(), **i);
}
}
eiis
}