rustc_passes/
canonical_symbols.rs1use rustc_hir::attrs::CanonicalSymbols;
2use rustc_hir::{ForeignItemId, find_attr};
3use rustc_middle::query::{LocalCrate, Providers};
4use rustc_middle::ty::{Instance, List, TyCtxt};
5use rustc_span::def_id::{DefId, LOCAL_CRATE};
6use rustc_span::{Symbol, sym};
7
8use crate::diagnostics::DuplicateCanonicalSymbolInCrate;
9
10fn observe_item<'tcx>(
11 tcx: TyCtxt<'tcx>,
12 canonical_symbols: &mut CanonicalSymbols,
13 fid: ForeignItemId,
14) {
15 let attrs = tcx.hir_attrs(fid.owner_id.into());
16 if {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(RustcCanonicalSymbol) =>
{
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, RustcCanonicalSymbol) {
17 let did = fid.owner_id.def_id;
18 let instance = Instance::new_raw(did.to_def_id(), List::identity_for_item(tcx, did));
19 let symbol_name = tcx.symbol_name(instance);
20 let symbol_name = Symbol::intern(symbol_name.name);
21
22 collect_item(tcx, canonical_symbols, symbol_name, fid.owner_id.to_def_id());
24 }
25}
26
27fn collect_item(
28 tcx: TyCtxt<'_>,
29 canonical_symbols: &mut CanonicalSymbols,
30 symbol: Symbol,
31 item_def_id: DefId,
32) {
33 if let Some(original_def_id) = canonical_symbols.set(symbol, item_def_id) {
34 report_duplicate_item(tcx, symbol, original_def_id, item_def_id);
35 }
36}
37
38fn report_duplicate_item(
39 tcx: TyCtxt<'_>,
40 name: Symbol,
41 original_def_id: DefId,
42 item_def_id: DefId,
43) {
44 let orig_span = tcx.hir_span_if_local(original_def_id);
45 let duplicate_span = tcx.hir_span_if_local(item_def_id);
46 tcx.dcx().emit_err(DuplicateCanonicalSymbolInCrate {
47 duplicate_span,
48 orig_span,
49 crate_name: tcx.crate_name(item_def_id.krate),
50 orig_crate_name: tcx.crate_name(original_def_id.krate),
51 different_crates: (item_def_id.krate != original_def_id.krate),
52 name,
53 });
54}
55
56fn canonical_symbols(tcx: TyCtxt<'_>, _: LocalCrate) -> CanonicalSymbols {
58 let mut canonical_symbols = CanonicalSymbols::new();
60
61 if tcx.features().enabled_features().contains(&sym::rustc_attrs) {
64 let crate_items = tcx.hir_crate_items(());
66 for id in crate_items.foreign_items() {
67 observe_item(tcx, &mut canonical_symbols, id);
68 }
69 }
70 canonical_symbols
71}
72
73fn all_canonical_symbols(tcx: TyCtxt<'_>, (): ()) -> CanonicalSymbols {
75 let mut items = CanonicalSymbols::new();
77
78 for cnum in tcx.crates(()).iter().copied().chain(std::iter::once(LOCAL_CRATE)) {
80 for cs in tcx.canonical_symbols(cnum).iter() {
81 collect_item(tcx, &mut items, cs.symbol, cs.def_id);
82 }
83 }
84
85 items
86}
87
88pub(crate) fn provide(providers: &mut Providers) {
89 providers.canonical_symbols = canonical_symbols;
90 providers.all_canonical_symbols = all_canonical_symbols;
91}