Skip to content

collecting lang items thru AST #116470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
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
3 changes: 3 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 }
}

Expand Down
139 changes: 11 additions & 128 deletions compiler/rustc_passes/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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) {
Expand Down Expand Up @@ -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.
Expand All @@ -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
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_passes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ mod naked_functions;
mod reachable;
pub mod stability;
mod upvars;
mod weak_lang_items;

fluent_messages! { "../messages.ftl" }

Expand Down
74 changes: 0 additions & 74 deletions compiler/rustc_passes/src/weak_lang_items.rs

This file was deleted.