add mapping from DefKind to Target and remove more ItemLikeVisitor impls

Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com>
This commit is contained in:
Miguel Guarniz 2022-04-07 18:21:37 -04:00
parent df10715463
commit d2840d237c
3 changed files with 60 additions and 62 deletions

View File

@ -7,6 +7,7 @@
use crate::hir;
use crate::{Item, ItemKind, TraitItem, TraitItemKind};
use crate::def::DefKind;
use std::fmt::{self, Display};
#[derive(Copy, Clone, PartialEq, Debug)]
@ -130,6 +131,29 @@ pub fn from_item(item: &Item<'_>) -> Target {
}
}
pub fn from_def_kind(def_kind: DefKind) -> Target {
match def_kind {
DefKind::ExternCrate => Target::ExternCrate,
DefKind::Use => Target::Use,
DefKind::Static(..) => Target::Static,
DefKind::Const => Target::Const,
DefKind::Fn => Target::Fn,
DefKind::Macro(..) => Target::MacroDef,
DefKind::Mod => Target::Mod,
DefKind::ForeignMod => Target::ForeignMod,
DefKind::GlobalAsm => Target::GlobalAsm,
DefKind::TyAlias => Target::TyAlias,
DefKind::OpaqueTy => Target::OpaqueTy,
DefKind::Enum => Target::Enum,
DefKind::Struct => Target::Struct,
DefKind::Union => Target::Union,
DefKind::Trait => Target::Trait,
DefKind::TraitAlias => Target::TraitAlias,
DefKind::Impl => Target::Impl,
_ => panic!("impossible case reached"),
}
}
pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
match trait_item.kind {
TraitItemKind::Const(..) => Target::AssocConst,

View File

@ -12,8 +12,8 @@
use rustc_errors::{pluralize, struct_span_err};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt;
@ -27,28 +27,6 @@ struct LanguageItemCollector<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) {
self.check_for_lang(Target::from_item(item), item.hir_id());
if let hir::ItemKind::Enum(def, ..) = &item.kind {
for variant in def.variants {
self.check_for_lang(Target::Variant, variant.id);
}
}
}
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
self.check_for_lang(Target::from_trait_item(trait_item), trait_item.hir_id())
}
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
self.check_for_lang(target_from_impl_item(self.tcx, impl_item), impl_item.hir_id())
}
fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {}
}
impl<'tcx> LanguageItemCollector<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
LanguageItemCollector { tcx, items: LanguageItems::new() }
@ -262,18 +240,28 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
let item = tcx.hir().item(id);
collector.visit_item(item);
collector.check_for_lang(Target::from_def_kind(tcx.hir().def_kind(id.def_id)), id.hir_id());
if matches!(tcx.hir().def_kind(id.def_id), DefKind::Enum) {
let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(def, ..) = &item.kind {
for variant in def.variants {
collector.check_for_lang(Target::Variant, variant.id);
}
}
}
}
// FIXME: avoid calling trait_item() when possible
for id in crate_items.trait_items() {
let item = tcx.hir().trait_item(id);
collector.visit_trait_item(item);
collector.check_for_lang(Target::from_trait_item(item), item.hir_id())
}
// FIXME: avoid calling impl_item() when possible
for id in crate_items.impl_items() {
let item = tcx.hir().impl_item(id);
collector.visit_impl_item(item);
collector.check_for_lang(target_from_impl_item(tcx, item), item.hir_id())
}
// Extract out the found lang items.

View File

@ -2,20 +2,11 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::lang_items::{self, LangItem};
use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
use rustc_middle::middle::lang_items::required;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::CrateType;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
struct Context<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
items: &'a mut lang_items::LanguageItems,
}
/// Checks the crate for usage of weak lang items, returning a vector of all the
/// language items required by this crate, but not defined yet.
@ -30,10 +21,28 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
items.missing.push(LangItem::EhCatchTypeinfo);
}
{
let mut cx = Context { tcx, items };
tcx.hir().visit_all_item_likes(&mut cx.as_deep_visitor());
let crate_items = tcx.hir_crate_items(());
for id in crate_items.foreign_items() {
let attrs = tcx.hir().attrs(id.hir_id());
let span = tcx.hir().span(id.hir_id());
if let Some((lang_item, _)) = lang_items::extract(attrs) {
if let Some(&item) = WEAK_ITEMS_REFS.get(&lang_item) {
if items.require(item).is_err() {
items.missing.push(item);
}
} else {
struct_span_err!(
tcx.sess,
span,
E0264,
"unknown external lang item: `{}`",
lang_item
)
.emit();
}
}
}
verify(tcx, items);
}
@ -80,26 +89,3 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
}
}
}
impl<'a, 'tcx> Context<'a, 'tcx> {
fn register(&mut self, name: Symbol, span: Span) {
if let Some(&item) = WEAK_ITEMS_REFS.get(&name) {
if self.items.require(item).is_err() {
self.items.missing.push(item);
}
} else {
struct_span_err!(self.tcx.sess, span, E0264, "unknown external lang item: `{}`", name)
.emit();
}
}
}
impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
let attrs = self.tcx.hir().attrs(i.hir_id());
if let Some((lang_item, _)) = lang_items::extract(attrs) {
self.register(lang_item, i.span);
}
intravisit::walk_foreign_item(self, i)
}
}