Skip to main content

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}