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