rustc_metadata/
eii.rs

1use rustc_data_structures::fx::FxIndexMap;
2use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl};
3use rustc_hir::def_id::DefId;
4use rustc_hir::find_attr;
5use rustc_middle::query::LocalCrate;
6use rustc_middle::ty::TyCtxt;
7
8// basically the map below but flattened out
9pub(crate) type EiiMapEncodedKeyValue = (DefId, (EiiDecl, Vec<(DefId, EiiImpl)>));
10
11pub(crate) type EiiMap = FxIndexMap<
12    DefId, // the defid of the macro that declared the eii
13    (
14        // the corresponding declaration
15        EiiDecl,
16        // all the given implementations, indexed by defid.
17        // We expect there to be only one, but collect them all to give errors if there are more
18        // (or if there are none) in the final crate we build.
19        FxIndexMap<DefId, EiiImpl>,
20    ),
21>;
22
23pub(crate) fn collect<'tcx>(tcx: TyCtxt<'tcx>, LocalCrate: LocalCrate) -> EiiMap {
24    let mut eiis = EiiMap::default();
25
26    // iterate over all items in the current crate
27    for id in tcx.hir_crate_items(()).eiis() {
28        for i in
29            find_attr!(tcx.get_all_attrs(id), AttributeKind::EiiImpls(e) => e).into_iter().flatten()
30        {
31            eiis.entry(i.eii_macro)
32                .or_insert_with(|| {
33                    // find the decl for this one if it wasn't in yet (maybe it's from the local crate? not very useful but not illegal)
34                    (find_attr!(tcx.get_all_attrs(i.eii_macro), AttributeKind::EiiExternTarget(d) => *d).unwrap(), Default::default())
35                }).1.insert(id.into(), *i);
36        }
37
38        // if we find a new declaration, add it to the list without a known implementation
39        if let Some(decl) =
40            find_attr!(tcx.get_all_attrs(id), AttributeKind::EiiExternTarget(d) => *d)
41        {
42            eiis.entry(id.into()).or_insert((decl, Default::default()));
43        }
44    }
45
46    eiis
47}