diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 85ab5e7223bf1..f5489166bbab8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -429,8 +429,10 @@ fn compute_hir_hash( } pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { + println!("running lower_to_hir"); let sess = tcx.sess; // Queries that borrow `resolver_for_lowering`. + tcx.ensure_with_value().get_lang_items(()); tcx.ensure_with_value().output_filenames(()); tcx.ensure_with_value().early_lint_checks(()); tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); @@ -464,6 +466,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { // Don't hash unless necessary, because it's expensive. let opt_hir_hash = if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; + println!("exiting lower_to_hir"); hir::Crate { owners, opt_hir_hash } } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 7e83724391836..d31f9b78e8db4 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -7,21 +7,14 @@ //! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`. //! * Functions called by the compiler itself. -use crate::check_attr::target_from_impl_item; -use crate::errors::{ - DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem, -}; -use crate::weak_lang_items; +use crate::errors::DuplicateLangItem; -use rustc_hir as hir; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::lang_items::{extract, GenericRequirement}; -use rustc_hir::{LangItem, LanguageItems, Target}; +use rustc_ast::visit::Visitor; +use rustc_hir::def_id::DefId; +use rustc_hir::{LangItem, LanguageItems}; use rustc_middle::ty::TyCtxt; use rustc_session::cstore::ExternCrate; use rustc_span::symbol::kw::Empty; -use rustc_span::{sym, Span}; use rustc_middle::query::Providers; @@ -36,36 +29,13 @@ struct LanguageItemCollector<'tcx> { tcx: TyCtxt<'tcx>, } +impl<'tcx, 'ast> Visitor<'ast> for LanguageItemCollector<'tcx> {} + impl<'tcx> LanguageItemCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> { LanguageItemCollector { tcx, items: LanguageItems::new() } } - fn check_for_lang(&mut self, actual_target: Target, def_id: LocalDefId) { - let attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id)); - if let Some((name, span)) = extract(&attrs) { - match LangItem::from_name(name) { - // Known lang item with attribute on correct target. - Some(lang_item) if actual_target == lang_item.target() => { - self.collect_item_extended(lang_item, def_id, span); - } - // Known lang item with attribute on incorrect target. - Some(lang_item) => { - self.tcx.sess.emit_err(LangItemOnIncorrectTarget { - span, - name, - expected_target: lang_item.target(), - actual_target, - }); - } - // Unknown lang item. - _ => { - self.tcx.sess.emit_err(UnknownLangItem { span, name }); - } - } - } - } - fn collect_item(&mut self, lang_item: LangItem, item_def_id: DefId) { // Check for duplicates. if let Some(original_def_id) = self.items.get(lang_item) { @@ -140,67 +110,6 @@ impl<'tcx> LanguageItemCollector<'tcx> { // Matched. self.items.set(lang_item, item_def_id); } - - // Like collect_item() above, but also checks whether the lang item is declared - // with the right number of generic arguments. - fn collect_item_extended(&mut self, lang_item: LangItem, item_def_id: LocalDefId, span: Span) { - let name = lang_item.name(); - - // Now check whether the lang_item has the expected number of generic - // arguments. Generally speaking, binary and indexing operations have - // one (for the RHS/index), unary operations have none, the closure - // traits have one for the argument list, generators have one for the - // resume argument, and ordering/equality relations have one for the RHS - // Some other types like Box and various functions like drop_in_place - // have minimum requirements. - - if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) = - self.tcx.hir().get_by_def_id(item_def_id) - { - let (actual_num, generics_span) = match kind.generics() { - Some(generics) => ( - generics - .params - .iter() - .filter(|p| !self.tcx.has_attr(p.def_id, sym::rustc_host)) - .count(), - generics.span, - ), - None => (0, *item_span), - }; - - let mut at_least = false; - let required = match lang_item.required_generics() { - GenericRequirement::Exact(num) if num != actual_num => Some(num), - GenericRequirement::Minimum(num) if actual_num < num => { - at_least = true; - Some(num)} - , - // If the number matches, or there is no requirement, handle it normally - _ => None, - }; - - if let Some(num) = required { - // We are issuing E0718 "incorrect target" here, because while the - // item kind of the target is correct, the target is still wrong - // because of the wrong number of generic arguments. - self.tcx.sess.emit_err(IncorrectTarget { - span, - generics_span, - name: name.as_str(), - kind: kind.descr(), - num, - actual_num, - at_least, - }); - - // return early to not collect the lang item - return; - } - } - - self.collect_item(lang_item, item_def_id.to_def_id()); - } } /// Traverses and collects all the lang items in all crates. @@ -216,39 +125,13 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { } // Collect lang items in this crate. - let crate_items = tcx.hir_crate_items(()); - - for id in crate_items.items() { - collector - .check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.owner_id.def_id); - - if matches!(tcx.def_kind(id.owner_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.def_id); - } - } - } - } - - // FIXME: avoid calling trait_item() when possible - for id in crate_items.trait_items() { - let item = tcx.hir().trait_item(id); - collector.check_for_lang(Target::from_trait_item(item), item.owner_id.def_id) - } - - // FIXME: avoid calling impl_item() when possible - for id in crate_items.impl_items() { - let item = tcx.hir().impl_item(id); - collector.check_for_lang(target_from_impl_item(tcx, item), item.owner_id.def_id) - } + let krate = &tcx.resolver_for_lowering(()).borrow().1; + println!("running visit_crate"); + collector.visit_crate(&krate); + println!("exiting visit_crate"); // Extract out the found lang items. - let LanguageItemCollector { mut items, .. } = collector; - - // Find all required but not-yet-defined lang items. - weak_lang_items::check_crate(tcx, &mut items); + let LanguageItemCollector { items, .. } = collector; items } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 51f3c9ad76f16..b16ac153365d9 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -43,7 +43,6 @@ mod naked_functions; mod reachable; pub mod stability; mod upvars; -mod weak_lang_items; fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs deleted file mode 100644 index 75e071f1fcfed..0000000000000 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Validity checking for weak lang items - -use rustc_data_structures::fx::FxHashSet; -use rustc_hir::lang_items::{self, LangItem}; -use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; -use rustc_middle::middle::lang_items::required; -use rustc_middle::ty::TyCtxt; -use rustc_session::config::CrateType; - -use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}; - -/// 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. -pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) { - // These are never called by user code, they're generated by the compiler. - // They will never implicitly be added to the `missing` array unless we do - // so here. - if items.eh_personality().is_none() { - items.missing.push(LangItem::EhPersonality); - } - if tcx.sess.target.os == "emscripten" && items.eh_catch_typeinfo().is_none() { - items.missing.push(LangItem::EhCatchTypeinfo); - } - - let crate_items = tcx.hir_crate_items(()); - for id in crate_items.foreign_items() { - let attrs = tcx.hir().attrs(id.hir_id()); - if let Some((lang_item, _)) = lang_items::extract(attrs) { - if let Some(item) = LangItem::from_name(lang_item) && item.is_weak() { - if items.get(item).is_none() { - items.missing.push(item); - } - } else { - let span = tcx.def_span(id.owner_id); - tcx.sess.emit_err(UnknownExternLangItem { span, lang_item }); - } - } - } - - verify(tcx, items); -} - -fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { - // We only need to check for the presence of weak lang items if we're - // emitting something that's not an rlib. - let needs_check = tcx.crate_types().iter().any(|kind| match *kind { - CrateType::Dylib - | CrateType::ProcMacro - | CrateType::Cdylib - | CrateType::Executable - | CrateType::Staticlib => true, - CrateType::Rlib => false, - }); - if !needs_check { - return; - } - - let mut missing = FxHashSet::default(); - for &cnum in tcx.crates(()).iter() { - for &item in tcx.missing_lang_items(cnum).iter() { - missing.insert(item); - } - } - - for &item in WEAK_LANG_ITEMS.iter() { - if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() { - if item == LangItem::PanicImpl { - tcx.sess.emit_err(MissingPanicHandler); - } else { - tcx.sess.emit_err(MissingLangItem { name: item.name() }); - } - } - } -}