rustc_passes/weak_lang_items.rs
1//! Validity checking for weak lang items
2
3use rustc_data_structures::fx::FxHashSet;
4use rustc_hir::lang_items::{self, LangItem};
5use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
6use rustc_middle::middle::lang_items::required;
7use rustc_middle::ty::TyCtxt;
8use rustc_session::config::CrateType;
9
10use crate::diagnostics::{MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd};
11
12/// Checks the crate for usage of weak lang items. Erroring on all the
13/// lang items required by this crate, but not defined yet.
14pub(crate) fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) {
15 // This is never called by user code, it's generated by the compiler. It
16 // will never implicitly be added to the `missing` array unless we do so
17 // here.
18 if items.eh_personality().is_none() {
19 items.missing.push(LangItem::EhPersonality);
20 }
21
22 items.trim_missing();
23
24 verify(tcx, items);
25}
26
27fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
28 // We only need to check for the presence of weak lang items if we're
29 // emitting something that's not an rlib.
30 let needs_check = tcx.crate_types().iter().any(|kind| match *kind {
31 CrateType::Dylib
32 | CrateType::ProcMacro
33 | CrateType::Cdylib
34 | CrateType::Executable
35 | CrateType::StaticLib
36 | CrateType::Sdylib => true,
37 CrateType::Rlib => false,
38 });
39 if !needs_check {
40 return;
41 }
42
43 let mut missing = FxHashSet::default();
44 for &cnum in tcx.crates(()).iter() {
45 for &item in tcx.missing_lang_items(cnum).iter() {
46 missing.insert(item);
47 }
48 }
49
50 for &item in WEAK_LANG_ITEMS.iter() {
51 if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() {
52 if item == LangItem::PanicImpl {
53 tcx.dcx().emit_err(MissingPanicHandler);
54 } else if item == LangItem::EhPersonality {
55 tcx.dcx().emit_err(PanicUnwindWithoutStd);
56 } else {
57 tcx.dcx().emit_err(MissingLangItem { name: item.name() });
58 }
59 }
60 }
61}