Skip to content

Commit c04195d

Browse files
committed
Move get_lang_items query in librustc_passes.
1 parent ff36923 commit c04195d

File tree

5 files changed

+176
-172
lines changed

5 files changed

+176
-172
lines changed

src/librustc/middle/lang_items.rs

Lines changed: 0 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -9,180 +9,13 @@
99
1010
pub use self::LangItem::*;
1111

12-
use crate::middle::cstore::ExternCrate;
13-
use crate::middle::weak_lang_items;
1412
use crate::ty::{self, TyCtxt};
1513

16-
use rustc_errors::struct_span_err;
17-
use rustc_hir as hir;
1814
use rustc_hir::def_id::DefId;
19-
use rustc_hir::itemlikevisit::ItemLikeVisitor;
20-
use rustc_lang_items::lang_items::ITEM_REFS;
21-
use rustc_lang_items::Target;
22-
use rustc_span::symbol::{sym, Symbol};
2315
use rustc_span::Span;
24-
use syntax::ast;
2516

2617
pub use rustc_lang_items::{LangItem, LanguageItems};
2718

28-
struct LanguageItemCollector<'tcx> {
29-
items: LanguageItems,
30-
tcx: TyCtxt<'tcx>,
31-
}
32-
33-
impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
34-
fn visit_item(&mut self, item: &hir::Item<'_>) {
35-
if let Some((value, span)) = extract(&item.attrs) {
36-
let actual_target = Target::from_item(item);
37-
match ITEM_REFS.get(&*value.as_str()).cloned() {
38-
// Known lang item with attribute on correct target.
39-
Some((item_index, expected_target)) if actual_target == expected_target => {
40-
let def_id = self.tcx.hir().local_def_id(item.hir_id);
41-
self.collect_item(item_index, def_id);
42-
}
43-
// Known lang item with attribute on incorrect target.
44-
Some((_, expected_target)) => {
45-
struct_span_err!(
46-
self.tcx.sess,
47-
span,
48-
E0718,
49-
"`{}` language item must be applied to a {}",
50-
value,
51-
expected_target,
52-
)
53-
.span_label(
54-
span,
55-
format!(
56-
"attribute should be applied to a {}, not a {}",
57-
expected_target, actual_target,
58-
),
59-
)
60-
.emit();
61-
}
62-
// Unknown lang item.
63-
_ => {
64-
struct_span_err!(
65-
self.tcx.sess,
66-
span,
67-
E0522,
68-
"definition of an unknown language item: `{}`",
69-
value
70-
)
71-
.span_label(span, format!("definition of unknown language item `{}`", value))
72-
.emit();
73-
}
74-
}
75-
}
76-
}
77-
78-
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
79-
// At present, lang items are always items, not trait items.
80-
}
81-
82-
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
83-
// At present, lang items are always items, not impl items.
84-
}
85-
}
86-
87-
impl LanguageItemCollector<'tcx> {
88-
fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
89-
LanguageItemCollector { tcx, items: LanguageItems::new() }
90-
}
91-
92-
fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
93-
// Check for duplicates.
94-
if let Some(original_def_id) = self.items.items[item_index] {
95-
if original_def_id != item_def_id {
96-
let name = LangItem::from_u32(item_index as u32).unwrap().name();
97-
let mut err = match self.tcx.hir().span_if_local(item_def_id) {
98-
Some(span) => struct_span_err!(
99-
self.tcx.sess,
100-
span,
101-
E0152,
102-
"found duplicate lang item `{}`",
103-
name
104-
),
105-
None => match self.tcx.extern_crate(item_def_id) {
106-
Some(ExternCrate { dependency_of, .. }) => {
107-
self.tcx.sess.struct_err(&format!(
108-
"duplicate lang item in crate `{}` (which `{}` depends on): `{}`.",
109-
self.tcx.crate_name(item_def_id.krate),
110-
self.tcx.crate_name(*dependency_of),
111-
name
112-
))
113-
}
114-
_ => self.tcx.sess.struct_err(&format!(
115-
"duplicate lang item in crate `{}`: `{}`.",
116-
self.tcx.crate_name(item_def_id.krate),
117-
name
118-
)),
119-
},
120-
};
121-
if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
122-
err.span_note(span, "the lang item is first defined here");
123-
} else {
124-
match self.tcx.extern_crate(original_def_id) {
125-
Some(ExternCrate { dependency_of, .. }) => {
126-
err.note(&format!(
127-
"the lang item is first defined in crate `{}` (which `{}` depends on)",
128-
self.tcx.crate_name(original_def_id.krate),
129-
self.tcx.crate_name(*dependency_of)));
130-
}
131-
_ => {
132-
err.note(&format!(
133-
"the lang item is first defined in crate `{}`.",
134-
self.tcx.crate_name(original_def_id.krate)
135-
));
136-
}
137-
}
138-
}
139-
err.emit();
140-
}
141-
}
142-
143-
// Matched.
144-
self.items.items[item_index] = Some(item_def_id);
145-
}
146-
}
147-
148-
/// Extracts the first `lang = "$name"` out of a list of attributes.
149-
/// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
150-
/// are also extracted out when found.
151-
pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
152-
attrs.iter().find_map(|attr| {
153-
Some(match attr {
154-
_ if attr.check_name(sym::lang) => (attr.value_str()?, attr.span),
155-
_ if attr.check_name(sym::panic_handler) => (sym::panic_impl, attr.span),
156-
_ if attr.check_name(sym::alloc_error_handler) => (sym::oom, attr.span),
157-
_ => return None,
158-
})
159-
})
160-
}
161-
162-
/// Traverses and collects all the lang items in all crates.
163-
pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems {
164-
// Initialize the collector.
165-
let mut collector = LanguageItemCollector::new(tcx);
166-
167-
// Collect lang items in other crates.
168-
for &cnum in tcx.crates().iter() {
169-
for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
170-
collector.collect_item(item_index, def_id);
171-
}
172-
}
173-
174-
// Collect lang items in this crate.
175-
tcx.hir().krate().visit_all_item_likes(&mut collector);
176-
177-
// Extract out the found lang items.
178-
let LanguageItemCollector { mut items, .. } = collector;
179-
180-
// Find all required but not-yet-defined lang items.
181-
weak_lang_items::check_crate(tcx, &mut items);
182-
183-
items
184-
}
185-
18619
impl<'tcx> TyCtxt<'tcx> {
18720
/// Returns the `DefId` for a given `LangItem`.
18821
/// If not found, fatally aborts compilation.

src/librustc/middle/weak_lang_items.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
141141
}
142142

143143
fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
144-
if let Some((lang_item, _)) = lang_items::extract(&i.attrs) {
144+
if let Some((lang_item, _)) = rustc_lang_items::lang_items::extract(&i.attrs) {
145145
self.register(lang_item, i.span);
146146
}
147147
intravisit::walk_foreign_item(self, i)

src/librustc/ty/context.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2716,10 +2716,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
27162716
assert_eq!(id, LOCAL_CRATE);
27172717
tcx.crate_name
27182718
};
2719-
providers.get_lang_items = |tcx, id| {
2720-
assert_eq!(id, LOCAL_CRATE);
2721-
tcx.arena.alloc(middle::lang_items::collect(tcx))
2722-
};
27232719
providers.maybe_unused_trait_import = |tcx, id| tcx.maybe_unused_trait_imports.contains(&id);
27242720
providers.maybe_unused_extern_crates = |tcx, cnum| {
27252721
assert_eq!(cnum, LOCAL_CRATE);

src/librustc_passes/lang_items.rs

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//! Detecting language items.
2+
//!
3+
//! Language items are items that represent concepts intrinsic to the language
4+
//! itself. Examples are:
5+
//!
6+
//! * Traits that specify "kinds"; e.g., `Sync`, `Send`.
7+
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
8+
//! * Functions called by the compiler itself.
9+
10+
use rustc::middle::cstore::ExternCrate;
11+
use rustc::middle::weak_lang_items;
12+
use rustc::ty::TyCtxt;
13+
14+
use rustc_errors::struct_span_err;
15+
use rustc_hir as hir;
16+
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
17+
use rustc_hir::itemlikevisit::ItemLikeVisitor;
18+
use rustc_lang_items::lang_items::{extract, ITEM_REFS};
19+
use rustc_lang_items::{LangItem, LanguageItems, Target};
20+
21+
use rustc::ty::query::Providers;
22+
23+
struct LanguageItemCollector<'tcx> {
24+
items: LanguageItems,
25+
tcx: TyCtxt<'tcx>,
26+
}
27+
28+
impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
29+
fn visit_item(&mut self, item: &hir::Item<'_>) {
30+
if let Some((value, span)) = extract(&item.attrs) {
31+
let actual_target = Target::from_item(item);
32+
match ITEM_REFS.get(&*value.as_str()).cloned() {
33+
// Known lang item with attribute on correct target.
34+
Some((item_index, expected_target)) if actual_target == expected_target => {
35+
let def_id = self.tcx.hir().local_def_id(item.hir_id);
36+
self.collect_item(item_index, def_id);
37+
}
38+
// Known lang item with attribute on incorrect target.
39+
Some((_, expected_target)) => {
40+
struct_span_err!(
41+
self.tcx.sess,
42+
span,
43+
E0718,
44+
"`{}` language item must be applied to a {}",
45+
value,
46+
expected_target,
47+
)
48+
.span_label(
49+
span,
50+
format!(
51+
"attribute should be applied to a {}, not a {}",
52+
expected_target, actual_target,
53+
),
54+
)
55+
.emit();
56+
}
57+
// Unknown lang item.
58+
_ => {
59+
struct_span_err!(
60+
self.tcx.sess,
61+
span,
62+
E0522,
63+
"definition of an unknown language item: `{}`",
64+
value
65+
)
66+
.span_label(span, format!("definition of unknown language item `{}`", value))
67+
.emit();
68+
}
69+
}
70+
}
71+
}
72+
73+
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
74+
// At present, lang items are always items, not trait items.
75+
}
76+
77+
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
78+
// At present, lang items are always items, not impl items.
79+
}
80+
}
81+
82+
impl LanguageItemCollector<'tcx> {
83+
fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
84+
LanguageItemCollector { tcx, items: LanguageItems::new() }
85+
}
86+
87+
fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
88+
// Check for duplicates.
89+
if let Some(original_def_id) = self.items.items[item_index] {
90+
if original_def_id != item_def_id {
91+
let name = LangItem::from_u32(item_index as u32).unwrap().name();
92+
let mut err = match self.tcx.hir().span_if_local(item_def_id) {
93+
Some(span) => struct_span_err!(
94+
self.tcx.sess,
95+
span,
96+
E0152,
97+
"found duplicate lang item `{}`",
98+
name
99+
),
100+
None => match self.tcx.extern_crate(item_def_id) {
101+
Some(ExternCrate { dependency_of, .. }) => {
102+
self.tcx.sess.struct_err(&format!(
103+
"duplicate lang item in crate `{}` (which `{}` depends on): `{}`.",
104+
self.tcx.crate_name(item_def_id.krate),
105+
self.tcx.crate_name(*dependency_of),
106+
name
107+
))
108+
}
109+
_ => self.tcx.sess.struct_err(&format!(
110+
"duplicate lang item in crate `{}`: `{}`.",
111+
self.tcx.crate_name(item_def_id.krate),
112+
name
113+
)),
114+
},
115+
};
116+
if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
117+
err.span_note(span, "the lang item is first defined here");
118+
} else {
119+
match self.tcx.extern_crate(original_def_id) {
120+
Some(ExternCrate { dependency_of, .. }) => {
121+
err.note(&format!(
122+
"the lang item is first defined in crate `{}` (which `{}` depends on)",
123+
self.tcx.crate_name(original_def_id.krate),
124+
self.tcx.crate_name(*dependency_of)
125+
));
126+
}
127+
_ => {
128+
err.note(&format!(
129+
"the lang item is first defined in crate `{}`.",
130+
self.tcx.crate_name(original_def_id.krate)
131+
));
132+
}
133+
}
134+
}
135+
err.emit();
136+
}
137+
}
138+
139+
// Matched.
140+
self.items.items[item_index] = Some(item_def_id);
141+
}
142+
}
143+
144+
/// Traverses and collects all the lang items in all crates.
145+
fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems {
146+
// Initialize the collector.
147+
let mut collector = LanguageItemCollector::new(tcx);
148+
149+
// Collect lang items in other crates.
150+
for &cnum in tcx.crates().iter() {
151+
for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
152+
collector.collect_item(item_index, def_id);
153+
}
154+
}
155+
156+
// Collect lang items in this crate.
157+
tcx.hir().krate().visit_all_item_likes(&mut collector);
158+
159+
// Extract out the found lang items.
160+
let LanguageItemCollector { mut items, .. } = collector;
161+
162+
// Find all required but not-yet-defined lang items.
163+
weak_lang_items::check_crate(tcx, &mut items);
164+
165+
items
166+
}
167+
168+
pub fn provide(providers: &mut Providers<'_>) {
169+
providers.get_lang_items = |tcx, id| {
170+
assert_eq!(id, LOCAL_CRATE);
171+
tcx.arena.alloc(collect(tcx))
172+
};
173+
}

src/librustc_passes/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod diagnostic_items;
2323
pub mod entry;
2424
pub mod hir_stats;
2525
mod intrinsicck;
26+
mod lang_items;
2627
pub mod layout_test;
2728
mod lib_features;
2829
mod liveness;
@@ -37,6 +38,7 @@ pub fn provide(providers: &mut Providers<'_>) {
3738
check_const::provide(providers);
3839
diagnostic_items::provide(providers);
3940
entry::provide(providers);
41+
lang_items::provide(providers);
4042
lib_features::provide(providers);
4143
loops::provide(providers);
4244
liveness::provide(providers);

0 commit comments

Comments
 (0)