1 //! Validity checking for weak lang items
5 use rustc_data_structures
::fx
::FxHashSet
;
6 use rustc_hir
::lang_items
::{self, LangItem}
;
7 use rustc_hir
::weak_lang_items
::WEAK_LANG_ITEMS
;
8 use rustc_middle
::middle
::lang_items
::required
;
9 use rustc_middle
::ty
::TyCtxt
;
10 use rustc_session
::config
::CrateType
;
12 use crate::errors
::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}
;
14 /// Checks the crate for usage of weak lang items, returning a vector of all the
15 /// language items required by this crate, but not defined yet.
16 pub fn check_crate(tcx
: TyCtxt
<'_
>, items
: &mut lang_items
::LanguageItems
, krate
: &ast
::Crate
) {
17 // These are never called by user code, they're generated by the compiler.
18 // They will never implicitly be added to the `missing` array unless we do
20 if items
.eh_personality().is_none() {
21 items
.missing
.push(LangItem
::EhPersonality
);
23 if tcx
.sess
.target
.os
== "emscripten" && items
.eh_catch_typeinfo().is_none() {
24 items
.missing
.push(LangItem
::EhCatchTypeinfo
);
27 visit
::Visitor
::visit_crate(&mut WeakLangItemVisitor { tcx, items }
, krate
);
32 struct WeakLangItemVisitor
<'a
, 'tcx
> {
34 items
: &'a
mut lang_items
::LanguageItems
,
37 impl<'ast
> visit
::Visitor
<'ast
> for WeakLangItemVisitor
<'_
, '_
> {
38 fn visit_foreign_item(&mut self, i
: &'ast ast
::ForeignItem
) {
39 if let Some((lang_item
, _
)) = lang_items
::extract(&i
.attrs
) {
40 if let Some(item
) = LangItem
::from_name(lang_item
)
43 if self.items
.get(item
).is_none() {
44 self.items
.missing
.push(item
);
47 self.tcx
.sess
.emit_err(UnknownExternLangItem { span: i.span, lang_item }
);
53 fn verify(tcx
: TyCtxt
<'_
>, items
: &lang_items
::LanguageItems
) {
54 // We only need to check for the presence of weak lang items if we're
55 // emitting something that's not an rlib.
56 let needs_check
= tcx
.crate_types().iter().any(|kind
| match *kind
{
58 | CrateType
::ProcMacro
60 | CrateType
::Executable
61 | CrateType
::Staticlib
=> true,
62 CrateType
::Rlib
=> false,
68 let mut missing
= FxHashSet
::default();
69 for &cnum
in tcx
.crates(()).iter() {
70 for &item
in tcx
.missing_lang_items(cnum
).iter() {
75 for &item
in WEAK_LANG_ITEMS
.iter() {
76 if missing
.contains(&item
) && required(tcx
, item
) && items
.get(item
).is_none() {
77 if item
== LangItem
::PanicImpl
{
78 tcx
.sess
.emit_err(MissingPanicHandler
);
80 tcx
.sess
.emit_err(MissingLangItem { name: item.name() }
);