Skip to content

Commit 450ad65

Browse files
authored
Rollup merge of rust-lang#60634 - Centril:lang-items-docs, r=oli-obk
Document + Cleanup lang_items.rs Byproduct of work on rust-lang#60607. r? @oli-obk
2 parents d20b692 + 47768b2 commit 450ad65

File tree

1 file changed

+60
-37
lines changed

1 file changed

+60
-37
lines changed

src/librustc/middle/lang_items.rs

+60-37
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
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-
//
8-
// * Traits that represent operators; e.g., "Add", "Sub", "Index".
9-
//
10-
// * Functions called by the compiler itself.
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+
//!
8+
//! * Traits that represent operators; e.g., "Add", "Sub", "Index".
9+
//!
10+
//! * Functions called by the compiler itself.
1111
1212
pub use self::LangItem::*;
1313

@@ -32,13 +32,17 @@ macro_rules! language_item_table {
3232
) => {
3333

3434
enum_from_u32! {
35+
/// A representation of all the valid language items in Rust.
3536
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
3637
pub enum LangItem {
3738
$($variant,)*
3839
}
3940
}
4041

4142
impl LangItem {
43+
/// Returns the `name` in `#[lang = "$name"]`.
44+
/// For example, `LangItem::EqTraitLangItem`,
45+
/// that is `#[lang = "eq"]` would result in `"eq"`.
4246
fn name(self) -> &'static str {
4347
match self {
4448
$( $variant => $name, )*
@@ -48,28 +52,38 @@ impl LangItem {
4852

4953
#[derive(HashStable)]
5054
pub struct LanguageItems {
55+
/// Mappings from lang items to their possibly found `DefId`s.
56+
/// The index corresponds to the order in `LangItem`.
5157
pub items: Vec<Option<DefId>>,
58+
/// Lang items that were not found during collection.
5259
pub missing: Vec<LangItem>,
5360
}
5461

5562
impl LanguageItems {
56-
pub fn new() -> LanguageItems {
57-
fn foo(_: LangItem) -> Option<DefId> { None }
63+
/// Construct an empty collection of lang items and no missing ones.
64+
pub fn new() -> Self {
65+
fn init_none(_: LangItem) -> Option<DefId> { None }
5866

59-
LanguageItems {
60-
items: vec![$(foo($variant)),*],
67+
Self {
68+
items: vec![$(init_none($variant)),*],
6169
missing: Vec::new(),
6270
}
6371
}
6472

73+
/// Returns the mappings to the possibly found `DefId`s for each lang item.
6574
pub fn items(&self) -> &[Option<DefId>] {
6675
&*self.items
6776
}
6877

78+
/// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
79+
/// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
80+
/// returns an error message as a string.
6981
pub fn require(&self, it: LangItem) -> Result<DefId, String> {
7082
self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name()))
7183
}
7284

85+
/// Returns the kind of closure that `id`, which is one of the `Fn*` traits, corresponds to.
86+
/// If `id` is not one of the `Fn*` traits, `None` is returned.
7387
pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
7488
match Some(id) {
7589
x if x == self.fn_trait() => Some(ty::ClosureKind::Fn),
@@ -80,6 +94,9 @@ impl LanguageItems {
8094
}
8195

8296
$(
97+
/// Returns the corresponding `DefId` for the lang item
98+
#[doc = $name]
99+
/// if it exists.
83100
#[allow(dead_code)]
84101
pub fn $method(&self) -> Option<DefId> {
85102
self.items[$variant as usize]
@@ -90,6 +107,7 @@ impl LanguageItems {
90107
struct LanguageItemCollector<'a, 'tcx: 'a> {
91108
items: LanguageItems,
92109
tcx: TyCtxt<'a, 'tcx, 'tcx>,
110+
/// A mapping from the name of the lang item to its order and the form it must be of.
93111
item_refs: FxHashMap<&'static str, (usize, Target)>,
94112
}
95113

@@ -105,32 +123,28 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
105123
},
106124
// Known lang item with attribute on incorrect target.
107125
Some((_, expected_target)) => {
108-
let mut err = struct_span_err!(
126+
struct_span_err!(
109127
self.tcx.sess, span, E0718,
110128
"`{}` language item must be applied to a {}",
111129
value, expected_target,
112-
);
113-
err.span_label(
130+
).span_label(
114131
span,
115132
format!(
116133
"attribute should be applied to a {}, not a {}",
117134
expected_target, actual_target,
118135
),
119-
);
120-
err.emit();
136+
).emit();
121137
},
122138
// Unknown lang item.
123139
_ => {
124-
let mut err = struct_span_err!(
140+
struct_span_err!(
125141
self.tcx.sess, span, E0522,
126142
"definition of an unknown language item: `{}`",
127143
value
128-
);
129-
err.span_label(
144+
).span_label(
130145
span,
131146
format!("definition of unknown language item `{}`", value)
132-
);
133-
err.emit();
147+
).emit();
134148
},
135149
}
136150
}
@@ -190,32 +204,39 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
190204
}
191205
}
192206

207+
/// Extract the first `lang = "$name"` out of a list of attributes.
208+
/// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
209+
/// are also extracted out when found.
193210
pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
194-
for attribute in attrs {
195-
if attribute.check_name("lang") {
196-
if let Some(value) = attribute.value_str() {
197-
return Some((value, attribute.span));
198-
}
199-
} else if attribute.check_name("panic_handler") {
200-
return Some((Symbol::intern("panic_impl"), attribute.span))
201-
} else if attribute.check_name("alloc_error_handler") {
202-
return Some((Symbol::intern("oom"), attribute.span))
203-
}
204-
}
205-
206-
None
211+
attrs.iter().find_map(|attr| Some(match attr {
212+
_ if attr.check_name("lang") => (attr.value_str()?, attr.span),
213+
_ if attr.check_name("panic_handler") => (Symbol::intern("panic_impl"), attr.span),
214+
_ if attr.check_name("alloc_error_handler") => (Symbol::intern("oom"), attr.span),
215+
_ => return None,
216+
}))
207217
}
208218

219+
/// Traverse and collect all the lang items in all crates.
209220
pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
221+
// Initialize the collector.
210222
let mut collector = LanguageItemCollector::new(tcx);
223+
224+
// Collect lang items in other crates.
211225
for &cnum in tcx.crates().iter() {
212226
for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
213227
collector.collect_item(item_index, def_id);
214228
}
215229
}
230+
231+
// Collect lang items in this crate.
216232
tcx.hir().krate().visit_all_item_likes(&mut collector);
233+
234+
// Extract out the found lang items.
217235
let LanguageItemCollector { mut items, .. } = collector;
236+
237+
// Find all required but not-yet-defined lang items.
218238
weak_lang_items::check_crate(tcx, &mut items);
239+
219240
items
220241
}
221242

@@ -382,6 +403,8 @@ language_item_table! {
382403
}
383404

384405
impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
406+
/// Returns the `DefId` for a given `LangItem`.
407+
/// If not found, fatally abort compilation.
385408
pub fn require_lang_item(&self, lang_item: LangItem) -> DefId {
386409
self.lang_items().require(lang_item).unwrap_or_else(|msg| {
387410
self.sess.fatal(&msg)

0 commit comments

Comments
 (0)