Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion compiler/rustc_passes/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ struct LanguageItemCollector<'ast, 'tcx> {
// so we can avoid constructing this map for local def-ids.
item_spans: FxHashMap<DefId, Span>,
parent_item: Option<&'ast ast::Item>,
/// Weak lang items declared by foreign items, in visit order. Whether
/// they end up missing is decided only once collection has finished,
/// which used to require a second full crate walk.
weak_foreign_candidates: Vec<LangItem>,
}

impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
Expand All @@ -51,6 +55,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
tcx,
resolver,
items: LanguageItems::new(),
weak_foreign_candidates: Vec::new(),
item_spans: FxHashMap::default(),
parent_item: None,
}
Expand Down Expand Up @@ -269,7 +274,8 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
visit::Visitor::visit_crate(&mut collector, krate);

// Find all required but not-yet-defined lang items.
weak_lang_items::check_crate(tcx, &mut collector.items, krate);
let weak_foreign_candidates = std::mem::take(&mut collector.weak_foreign_candidates);
weak_lang_items::check_crate(tcx, &mut collector.items, &weak_foreign_candidates);

// Return all the lang items that were found.
collector.items
Expand Down Expand Up @@ -314,6 +320,12 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
}

fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) {
if let Some((lang_item, _)) = extract_ast(&i.attrs)
&& let Some(item) = LangItem::from_name(lang_item)
&& item.is_weak()
{
self.weak_foreign_candidates.push(item);
}
self.check_for_lang(
Target::Fn,
self.resolver.owners[&i.id].def_id,
Expand Down
33 changes: 11 additions & 22 deletions compiler/rustc_passes/src/weak_lang_items.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! Validity checking for weak lang items

use rustc_ast as ast;
use rustc_ast::visit;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::lang_items::{self, LangItem};
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
Expand All @@ -10,14 +8,18 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::config::CrateType;

use crate::diagnostics::{MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd};
use crate::lang_items::extract_ast;

/// Checks the crate for usage of weak lang items, returning a vector of all the
/// lang items required by this crate, but not defined yet.
///
/// `weak_foreign_candidates` holds the weak lang items declared by the
/// crate's foreign items, in visit order; the lang item collector records
/// them during its walk so no second crate walk is needed here. Whether a
/// candidate is missing can only be decided now, after collection finished.
pub(crate) fn check_crate(
tcx: TyCtxt<'_>,
items: &mut lang_items::LanguageItems,
krate: &ast::Crate,
weak_foreign_candidates: &[LangItem],
) {
// This is never called by user code, it's generated by the compiler. It
// will never implicitly be added to the `missing` array unless we do so
Expand All @@ -26,26 +28,13 @@ pub(crate) fn check_crate(
items.missing.push(LangItem::EhPersonality);
}

visit::Visitor::visit_crate(&mut WeakLangItemVisitor { items }, krate);

verify(tcx, items);
}

struct WeakLangItemVisitor<'a> {
items: &'a mut lang_items::LanguageItems,
}

impl<'ast> visit::Visitor<'ast> for WeakLangItemVisitor<'_> {
fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) {
if let Some((lang_item, _)) = extract_ast(&i.attrs)
&& let Some(item) = LangItem::from_name(lang_item)
&& item.is_weak()
{
if self.items.get(item).is_none() {
self.items.missing.push(item);
}
for &item in weak_foreign_candidates {
if items.get(item).is_none() {
items.missing.push(item);
}
}

verify(tcx, items);
}

fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
Expand Down
Loading