]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/lang_items.rs
a34571e4acac77097210f33670bdd6fc427b4a8d
[rust.git] / src / librustc / middle / lang_items.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // Detecting language items.
12 //
13 // Language items are items that represent concepts intrinsic to the language
14 // itself. Examples are:
15 //
16 // * Traits that specify "kinds"; e.g. "Sync", "Send".
17 //
18 // * Traits that represent operators; e.g. "Add", "Sub", "Index".
19 //
20 // * Functions called by the compiler itself.
21
22 pub use self::LangItem::*;
23
24 use session::Session;
25 use metadata::csearch::each_lang_item;
26 use middle::def_id::DefId;
27 use middle::ty;
28 use middle::weak_lang_items;
29 use util::nodemap::FnvHashMap;
30
31 use rustc_front::attr::AttrMetaMethods;
32 use syntax::codemap::{DUMMY_SP, Span};
33 use syntax::parse::token::InternedString;
34 use rustc_front::visit::Visitor;
35 use rustc_front::visit;
36 use rustc_front::hir;
37
38 use std::iter::Enumerate;
39 use std::slice;
40
41 // The actual lang items defined come at the end of this file in one handy table.
42 // So you probably just want to nip down to the end.
43 macro_rules! lets_do_this {
44     (
45         $( $variant:ident, $name:expr, $method:ident; )*
46     ) => {
47
48
49 enum_from_u32! {
50     #[derive(Copy, Clone, PartialEq, Eq, Hash)]
51     pub enum LangItem {
52         $($variant,)*
53     }
54 }
55
56 pub struct LanguageItems {
57     pub items: Vec<Option<DefId>>,
58     pub missing: Vec<LangItem>,
59 }
60
61 impl LanguageItems {
62     pub fn new() -> LanguageItems {
63         fn foo(_: LangItem) -> Option<DefId> { None }
64
65         LanguageItems {
66             items: vec!($(foo($variant)),*),
67             missing: Vec::new(),
68         }
69     }
70
71     pub fn items<'a>(&'a self) -> Enumerate<slice::Iter<'a, Option<DefId>>> {
72         self.items.iter().enumerate()
73     }
74
75     pub fn item_name(index: usize) -> &'static str {
76         let item: Option<LangItem> = LangItem::from_u32(index as u32);
77         match item {
78             $( Some($variant) => $name, )*
79             None => "???"
80         }
81     }
82
83     pub fn require(&self, it: LangItem) -> Result<DefId, String> {
84         match self.items[it as usize] {
85             Some(id) => Ok(id),
86             None => {
87                 Err(format!("requires `{}` lang_item",
88                             LanguageItems::item_name(it as usize)))
89             }
90         }
91     }
92
93     pub fn require_owned_box(&self) -> Result<DefId, String> {
94         self.require(OwnedBoxLangItem)
95     }
96
97     pub fn from_builtin_kind(&self, bound: ty::BuiltinBound)
98                              -> Result<DefId, String>
99     {
100         match bound {
101             ty::BoundSend => self.require(SendTraitLangItem),
102             ty::BoundSized => self.require(SizedTraitLangItem),
103             ty::BoundCopy => self.require(CopyTraitLangItem),
104             ty::BoundSync => self.require(SyncTraitLangItem),
105         }
106     }
107
108     pub fn to_builtin_kind(&self, id: DefId) -> Option<ty::BuiltinBound> {
109         if Some(id) == self.send_trait() {
110             Some(ty::BoundSend)
111         } else if Some(id) == self.sized_trait() {
112             Some(ty::BoundSized)
113         } else if Some(id) == self.copy_trait() {
114             Some(ty::BoundCopy)
115         } else if Some(id) == self.sync_trait() {
116             Some(ty::BoundSync)
117         } else {
118             None
119         }
120     }
121
122     pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
123         let def_id_kinds = [
124             (self.fn_trait(), ty::FnClosureKind),
125             (self.fn_mut_trait(), ty::FnMutClosureKind),
126             (self.fn_once_trait(), ty::FnOnceClosureKind),
127             ];
128
129         for &(opt_def_id, kind) in &def_id_kinds {
130             if Some(id) == opt_def_id {
131                 return Some(kind);
132             }
133         }
134
135         None
136     }
137
138     $(
139         #[allow(dead_code)]
140         pub fn $method(&self) -> Option<DefId> {
141             self.items[$variant as usize]
142         }
143     )*
144 }
145
146 struct LanguageItemCollector<'a> {
147     items: LanguageItems,
148
149     session: &'a Session,
150
151     item_refs: FnvHashMap<&'static str, usize>,
152 }
153
154 impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
155     fn visit_item(&mut self, item: &hir::Item) {
156         if let Some(value) = extract(&item.attrs) {
157             let item_index = self.item_refs.get(&value[..]).cloned();
158
159             if let Some(item_index) = item_index {
160                 self.collect_item(item_index, DefId::local(item.id), item.span)
161             }
162         }
163
164         visit::walk_item(self, item);
165     }
166 }
167
168 impl<'a> LanguageItemCollector<'a> {
169     pub fn new(session: &'a Session) -> LanguageItemCollector<'a> {
170         let mut item_refs = FnvHashMap();
171
172         $( item_refs.insert($name, $variant as usize); )*
173
174         LanguageItemCollector {
175             session: session,
176             items: LanguageItems::new(),
177             item_refs: item_refs
178         }
179     }
180
181     pub fn collect_item(&mut self, item_index: usize,
182                         item_def_id: DefId, span: Span) {
183         // Check for duplicates.
184         match self.items.items[item_index] {
185             Some(original_def_id) if original_def_id != item_def_id => {
186                 span_err!(self.session, span, E0152,
187                     "duplicate entry for `{}`", LanguageItems::item_name(item_index));
188             }
189             Some(_) | None => {
190                 // OK.
191             }
192         }
193
194         // Matched.
195         self.items.items[item_index] = Some(item_def_id);
196     }
197
198     pub fn collect_local_language_items(&mut self, krate: &hir::Crate) {
199         visit::walk_crate(self, krate);
200     }
201
202     pub fn collect_external_language_items(&mut self) {
203         let crate_store = &self.session.cstore;
204         crate_store.iter_crate_data(|crate_number, _crate_metadata| {
205             each_lang_item(crate_store, crate_number, |node_id, item_index| {
206                 let def_id = DefId { krate: crate_number, node: node_id };
207                 self.collect_item(item_index, def_id, DUMMY_SP);
208                 true
209             });
210         })
211     }
212
213     pub fn collect(&mut self, krate: &hir::Crate) {
214         self.collect_local_language_items(krate);
215         self.collect_external_language_items();
216     }
217 }
218
219 pub fn extract(attrs: &[hir::Attribute]) -> Option<InternedString> {
220     for attribute in attrs {
221         match attribute.value_str() {
222             Some(ref value) if attribute.check_name("lang") => {
223                 return Some(value.clone());
224             }
225             _ => {}
226         }
227     }
228
229     return None;
230 }
231
232 pub fn collect_language_items(krate: &hir::Crate,
233                               session: &Session) -> LanguageItems {
234     let mut collector = LanguageItemCollector::new(session);
235     collector.collect(krate);
236     let LanguageItemCollector { mut items, .. } = collector;
237     weak_lang_items::check_crate(krate, session, &mut items);
238     session.abort_if_errors();
239     items
240 }
241
242 // End of the macro
243     }
244 }
245
246 lets_do_this! {
247 //  Variant name,                    Name,                      Method name;
248     CharImplItem,                    "char",                    char_impl;
249     StrImplItem,                     "str",                     str_impl;
250     SliceImplItem,                   "slice",                   slice_impl;
251     ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
252     MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
253     I8ImplItem,                      "i8",                      i8_impl;
254     I16ImplItem,                     "i16",                     i16_impl;
255     I32ImplItem,                     "i32",                     i32_impl;
256     I64ImplItem,                     "i64",                     i64_impl;
257     IsizeImplItem,                   "isize",                   isize_impl;
258     U8ImplItem,                      "u8",                      u8_impl;
259     U16ImplItem,                     "u16",                     u16_impl;
260     U32ImplItem,                     "u32",                     u32_impl;
261     U64ImplItem,                     "u64",                     u64_impl;
262     UsizeImplItem,                   "usize",                   usize_impl;
263     F32ImplItem,                     "f32",                     f32_impl;
264     F64ImplItem,                     "f64",                     f64_impl;
265
266     SendTraitLangItem,               "send",                    send_trait;
267     SizedTraitLangItem,              "sized",                   sized_trait;
268     UnsizeTraitLangItem,             "unsize",                  unsize_trait;
269     CopyTraitLangItem,               "copy",                    copy_trait;
270     SyncTraitLangItem,               "sync",                    sync_trait;
271
272     DropTraitLangItem,               "drop",                    drop_trait;
273
274     CoerceUnsizedTraitLangItem,      "coerce_unsized",          coerce_unsized_trait;
275
276     AddTraitLangItem,                "add",                     add_trait;
277     SubTraitLangItem,                "sub",                     sub_trait;
278     MulTraitLangItem,                "mul",                     mul_trait;
279     DivTraitLangItem,                "div",                     div_trait;
280     RemTraitLangItem,                "rem",                     rem_trait;
281     NegTraitLangItem,                "neg",                     neg_trait;
282     NotTraitLangItem,                "not",                     not_trait;
283     BitXorTraitLangItem,             "bitxor",                  bitxor_trait;
284     BitAndTraitLangItem,             "bitand",                  bitand_trait;
285     BitOrTraitLangItem,              "bitor",                   bitor_trait;
286     ShlTraitLangItem,                "shl",                     shl_trait;
287     ShrTraitLangItem,                "shr",                     shr_trait;
288     IndexTraitLangItem,              "index",                   index_trait;
289     IndexMutTraitLangItem,           "index_mut",               index_mut_trait;
290     RangeStructLangItem,             "range",                   range_struct;
291     RangeFromStructLangItem,         "range_from",              range_from_struct;
292     RangeToStructLangItem,           "range_to",                range_to_struct;
293     RangeFullStructLangItem,         "range_full",              range_full_struct;
294
295     UnsafeCellTypeLangItem,          "unsafe_cell",             unsafe_cell_type;
296
297     DerefTraitLangItem,              "deref",                   deref_trait;
298     DerefMutTraitLangItem,           "deref_mut",               deref_mut_trait;
299
300     FnTraitLangItem,                 "fn",                      fn_trait;
301     FnMutTraitLangItem,              "fn_mut",                  fn_mut_trait;
302     FnOnceTraitLangItem,             "fn_once",                 fn_once_trait;
303
304     EqTraitLangItem,                 "eq",                      eq_trait;
305     OrdTraitLangItem,                "ord",                     ord_trait;
306
307     StrEqFnLangItem,                 "str_eq",                  str_eq_fn;
308
309     // A number of panic-related lang items. The `panic` item corresponds to
310     // divide-by-zero and various panic cases with `match`. The
311     // `panic_bounds_check` item is for indexing arrays.
312     //
313     // The `begin_unwind` lang item has a predefined symbol name and is sort of
314     // a "weak lang item" in the sense that a crate is not required to have it
315     // defined to use it, but a final product is required to define it
316     // somewhere. Additionally, there are restrictions on crates that use a weak
317     // lang item, but do not have it defined.
318     PanicFnLangItem,                 "panic",                   panic_fn;
319     PanicBoundsCheckFnLangItem,      "panic_bounds_check",      panic_bounds_check_fn;
320     PanicFmtLangItem,                "panic_fmt",               panic_fmt;
321
322     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
323     ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
324     StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;
325
326     StartFnLangItem,                 "start",                   start_fn;
327
328     EhPersonalityLangItem,           "eh_personality",          eh_personality;
329     EhPersonalityCatchLangItem,      "eh_personality_catch",    eh_personality_catch;
330     EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
331     MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;
332
333     ExchangeHeapLangItem,            "exchange_heap",           exchange_heap;
334     OwnedBoxLangItem,                "owned_box",               owned_box;
335
336     PhantomDataItem,                 "phantom_data",            phantom_data;
337
338     // Deprecated:
339     CovariantTypeItem,               "covariant_type",          covariant_type;
340     ContravariantTypeItem,           "contravariant_type",      contravariant_type;
341     InvariantTypeItem,               "invariant_type",          invariant_type;
342     CovariantLifetimeItem,           "covariant_lifetime",      covariant_lifetime;
343     ContravariantLifetimeItem,       "contravariant_lifetime",  contravariant_lifetime;
344     InvariantLifetimeItem,           "invariant_lifetime",      invariant_lifetime;
345
346     NoCopyItem,                      "no_copy_bound",           no_copy_bound;
347
348     NonZeroItem,                     "non_zero",                non_zero;
349
350     DebugTraitLangItem,              "debug_trait",             debug_trait;
351 }