1 //! Used by `rustc` when compiling a plugin crate.
4 use rustc_hir
::def_id
::{CrateNum, DefId, LOCAL_CRATE}
;
5 use rustc_hir
::itemlikevisit
::ItemLikeVisitor
;
6 use rustc_middle
::ty
::query
::Providers
;
7 use rustc_middle
::ty
::TyCtxt
;
8 use rustc_span
::symbol
::sym
;
11 struct RegistrarFinder
<'tcx
> {
13 registrars
: Vec
<(hir
::HirId
, Span
)>,
16 impl<'v
, 'tcx
> ItemLikeVisitor
<'v
> for RegistrarFinder
<'tcx
> {
17 fn visit_item(&mut self, item
: &hir
::Item
<'_
>) {
18 if let hir
::ItemKind
::Fn(..) = item
.kind
{
19 if self.tcx
.sess
.contains_name(&item
.attrs
, sym
::plugin_registrar
) {
20 self.registrars
.push((item
.hir_id
, item
.span
));
25 fn visit_trait_item(&mut self, _trait_item
: &hir
::TraitItem
<'_
>) {}
27 fn visit_impl_item(&mut self, _impl_item
: &hir
::ImplItem
<'_
>) {}
30 /// Finds the function marked with `#[plugin_registrar]`, if any.
31 pub fn find_plugin_registrar(tcx
: TyCtxt
<'_
>) -> Option
<DefId
> {
32 tcx
.plugin_registrar_fn(LOCAL_CRATE
)
35 fn plugin_registrar_fn(tcx
: TyCtxt
<'_
>, cnum
: CrateNum
) -> Option
<DefId
> {
36 assert_eq
!(cnum
, LOCAL_CRATE
);
38 let mut finder
= RegistrarFinder { tcx, registrars: Vec::new() }
;
39 tcx
.hir().krate().visit_all_item_likes(&mut finder
);
41 match finder
.registrars
.len() {
44 let (hir_id
, _
) = finder
.registrars
.pop().unwrap();
45 Some(tcx
.hir().local_def_id(hir_id
).to_def_id())
48 let diagnostic
= tcx
.sess
.diagnostic();
49 let mut e
= diagnostic
.struct_err("multiple plugin registration functions found");
50 for &(_
, span
) in &finder
.registrars
{
51 e
.span_note(span
, "one is here");
54 diagnostic
.abort_if_errors();
60 pub fn provide(providers
: &mut Providers
) {
61 *providers
= Providers { plugin_registrar_fn, ..*providers }
;