]>
Commit | Line | Data |
---|---|---|
74b04a01 XL |
1 | //! Validity checking for weak lang items |
2 | ||
74b04a01 | 3 | use rustc_data_structures::fx::FxHashSet; |
3dfed10e | 4 | use rustc_hir::lang_items::{self, LangItem}; |
487cf647 | 5 | use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; |
f035d41b | 6 | use rustc_middle::middle::lang_items::required; |
ba9703b0 | 7 | use rustc_middle::ty::TyCtxt; |
f9f354fc | 8 | use rustc_session::config::CrateType; |
74b04a01 | 9 | |
487cf647 | 10 | use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}; |
2b03887a | 11 | |
74b04a01 XL |
12 | /// Checks the crate for usage of weak lang items, returning a vector of all the |
13 | /// language items required by this crate, but not defined yet. | |
9c376795 | 14 | pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) { |
74b04a01 XL |
15 | // These are never called by user code, they're generated by the compiler. |
16 | // They will never implicitly be added to the `missing` array unless we do | |
17 | // so here. | |
18 | if items.eh_personality().is_none() { | |
3dfed10e | 19 | items.missing.push(LangItem::EhPersonality); |
74b04a01 | 20 | } |
923072b8 | 21 | if tcx.sess.target.os == "emscripten" && items.eh_catch_typeinfo().is_none() { |
1b1a35ee XL |
22 | items.missing.push(LangItem::EhCatchTypeinfo); |
23 | } | |
74b04a01 | 24 | |
04454e1e FG |
25 | let crate_items = tcx.hir_crate_items(()); |
26 | for id in crate_items.foreign_items() { | |
27 | let attrs = tcx.hir().attrs(id.hir_id()); | |
28 | if let Some((lang_item, _)) = lang_items::extract(attrs) { | |
487cf647 FG |
29 | if let Some(item) = LangItem::from_name(lang_item) && item.is_weak() { |
30 | if items.get(item).is_none() { | |
04454e1e FG |
31 | items.missing.push(item); |
32 | } | |
33 | } else { | |
2b03887a FG |
34 | let span = tcx.def_span(id.owner_id); |
35 | tcx.sess.emit_err(UnknownExternLangItem { span, lang_item }); | |
04454e1e FG |
36 | } |
37 | } | |
74b04a01 | 38 | } |
04454e1e | 39 | |
74b04a01 XL |
40 | verify(tcx, items); |
41 | } | |
42 | ||
9c376795 | 43 | fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { |
74b04a01 XL |
44 | // We only need to check for the presence of weak lang items if we're |
45 | // emitting something that's not an rlib. | |
f9f354fc XL |
46 | let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind { |
47 | CrateType::Dylib | |
48 | | CrateType::ProcMacro | |
49 | | CrateType::Cdylib | |
50 | | CrateType::Executable | |
51 | | CrateType::Staticlib => true, | |
52 | CrateType::Rlib => false, | |
74b04a01 XL |
53 | }); |
54 | if !needs_check { | |
55 | return; | |
56 | } | |
57 | ||
58 | let mut missing = FxHashSet::default(); | |
136023e0 | 59 | for &cnum in tcx.crates(()).iter() { |
74b04a01 XL |
60 | for &item in tcx.missing_lang_items(cnum).iter() { |
61 | missing.insert(item); | |
62 | } | |
63 | } | |
64 | ||
487cf647 FG |
65 | for &item in WEAK_LANG_ITEMS.iter() { |
66 | if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() { | |
3dfed10e | 67 | if item == LangItem::PanicImpl { |
2b03887a | 68 | tcx.sess.emit_err(MissingPanicHandler); |
74b04a01 | 69 | } else { |
487cf647 | 70 | tcx.sess.emit_err(MissingLangItem { name: item.name() }); |
74b04a01 XL |
71 | } |
72 | } | |
73 | } | |
74 | } |