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.
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.
11 // Detecting language items.
13 // Language items are items that represent concepts intrinsic to the language
14 // itself. Examples are:
16 // * Traits that specify "kinds"; e.g. "Freeze", "Send".
18 // * Traits that represent operators; e.g. "Add", "Sub", "Index".
20 // * Functions called by the compiler itself.
23 use driver::session::Session;
24 use metadata::csearch::each_lang_item;
25 use metadata::cstore::iter_crate_data;
26 use syntax::ast::{Crate, def_id, MetaItem};
27 use syntax::ast_util::local_def;
28 use syntax::attr::AttrMetaMethods;
29 use syntax::ast::{item};
31 use syntax::visit::Visitor;
33 use std::hashmap::HashMap;
36 FreezeTraitLangItem, // 0
37 SendTraitLangItem, // 1
38 SizedTraitLangItem, // 2
40 DropTraitLangItem, // 3
42 AddTraitLangItem, // 4
43 SubTraitLangItem, // 5
44 MulTraitLangItem, // 6
45 DivTraitLangItem, // 7
46 RemTraitLangItem, // 8
47 NegTraitLangItem, // 9
48 NotTraitLangItem, // 10
49 BitXorTraitLangItem, // 11
50 BitAndTraitLangItem, // 12
51 BitOrTraitLangItem, // 13
52 ShlTraitLangItem, // 14
53 ShrTraitLangItem, // 15
54 IndexTraitLangItem, // 16
56 EqTraitLangItem, // 17
57 OrdTraitLangItem, // 18
59 StrEqFnLangItem, // 19
60 UniqStrEqFnLangItem, // 20
61 LogTypeFnLangItem, // 21
63 FailBoundsCheckFnLangItem, // 23
64 ExchangeMallocFnLangItem, // 24
65 ClosureExchangeMallocFnLangItem, // 25
66 ExchangeFreeFnLangItem, // 26
67 MallocFnLangItem, // 27
69 BorrowAsImmFnLangItem, // 29
70 BorrowAsMutFnLangItem, // 30
71 ReturnToMutFnLangItem, // 31
72 CheckNotBorrowedFnLangItem, // 32
73 StrDupUniqFnLangItem, // 33
74 RecordBorrowFnLangItem, // 34
75 UnrecordBorrowFnLangItem, // 35
77 StartFnLangItem, // 36
79 TyDescStructLangItem, // 37
80 TyVisitorTraitLangItem, // 38
81 OpaqueStructLangItem, // 39
84 pub struct LanguageItems {
85 items: [Option<def_id>, ..41]
89 pub fn new() -> LanguageItems {
95 pub fn each_item(&self, f: &fn(Option<def_id>, uint) -> bool) -> bool {
96 self.items.iter().enumerate().advance(|(i, &item)| f(item, i))
99 pub fn item_name(index: uint) -> &'static str {
127 23 => "fail_bounds_check",
128 24 => "exchange_malloc",
129 25 => "closure_exchange_malloc",
130 26 => "exchange_free",
133 29 => "borrow_as_imm",
134 30 => "borrow_as_mut",
135 31 => "return_to_mut",
136 32 => "check_not_borrowed",
138 34 => "record_borrow",
139 35 => "unrecord_borrow",
151 // FIXME #4621: Method macros sure would be nice here.
153 pub fn require(&self, it: LangItem) -> Result<def_id, ~str> {
154 match self.items[it as uint] {
156 None => Err(fmt!("requires `%s` lang_item",
157 LanguageItems::item_name(it as uint)))
161 pub fn freeze_trait(&self) -> Option<def_id> {
162 self.items[FreezeTraitLangItem as uint]
164 pub fn send_trait(&self) -> Option<def_id> {
165 self.items[SendTraitLangItem as uint]
167 pub fn sized_trait(&self) -> Option<def_id> {
168 self.items[SizedTraitLangItem as uint]
171 pub fn drop_trait(&self) -> Option<def_id> {
172 self.items[DropTraitLangItem as uint]
175 pub fn add_trait(&self) -> Option<def_id> {
176 self.items[AddTraitLangItem as uint]
178 pub fn sub_trait(&self) -> Option<def_id> {
179 self.items[SubTraitLangItem as uint]
181 pub fn mul_trait(&self) -> Option<def_id> {
182 self.items[MulTraitLangItem as uint]
184 pub fn div_trait(&self) -> Option<def_id> {
185 self.items[DivTraitLangItem as uint]
187 pub fn rem_trait(&self) -> Option<def_id> {
188 self.items[RemTraitLangItem as uint]
190 pub fn neg_trait(&self) -> Option<def_id> {
191 self.items[NegTraitLangItem as uint]
193 pub fn not_trait(&self) -> Option<def_id> {
194 self.items[NotTraitLangItem as uint]
196 pub fn bitxor_trait(&self) -> Option<def_id> {
197 self.items[BitXorTraitLangItem as uint]
199 pub fn bitand_trait(&self) -> Option<def_id> {
200 self.items[BitAndTraitLangItem as uint]
202 pub fn bitor_trait(&self) -> Option<def_id> {
203 self.items[BitOrTraitLangItem as uint]
205 pub fn shl_trait(&self) -> Option<def_id> {
206 self.items[ShlTraitLangItem as uint]
208 pub fn shr_trait(&self) -> Option<def_id> {
209 self.items[ShrTraitLangItem as uint]
211 pub fn index_trait(&self) -> Option<def_id> {
212 self.items[IndexTraitLangItem as uint]
215 pub fn eq_trait(&self) -> Option<def_id> {
216 self.items[EqTraitLangItem as uint]
218 pub fn ord_trait(&self) -> Option<def_id> {
219 self.items[OrdTraitLangItem as uint]
222 pub fn str_eq_fn(&self) -> Option<def_id> {
223 self.items[StrEqFnLangItem as uint]
225 pub fn uniq_str_eq_fn(&self) -> Option<def_id> {
226 self.items[UniqStrEqFnLangItem as uint]
228 pub fn log_type_fn(&self) -> Option<def_id> {
229 self.items[LogTypeFnLangItem as uint]
231 pub fn fail_fn(&self) -> Option<def_id> {
232 self.items[FailFnLangItem as uint]
234 pub fn fail_bounds_check_fn(&self) -> Option<def_id> {
235 self.items[FailBoundsCheckFnLangItem as uint]
237 pub fn exchange_malloc_fn(&self) -> Option<def_id> {
238 self.items[ExchangeMallocFnLangItem as uint]
240 pub fn closure_exchange_malloc_fn(&self) -> Option<def_id> {
241 self.items[ClosureExchangeMallocFnLangItem as uint]
243 pub fn exchange_free_fn(&self) -> Option<def_id> {
244 self.items[ExchangeFreeFnLangItem as uint]
246 pub fn malloc_fn(&self) -> Option<def_id> {
247 self.items[MallocFnLangItem as uint]
249 pub fn free_fn(&self) -> Option<def_id> {
250 self.items[FreeFnLangItem as uint]
252 pub fn borrow_as_imm_fn(&self) -> Option<def_id> {
253 self.items[BorrowAsImmFnLangItem as uint]
255 pub fn borrow_as_mut_fn(&self) -> Option<def_id> {
256 self.items[BorrowAsMutFnLangItem as uint]
258 pub fn return_to_mut_fn(&self) -> Option<def_id> {
259 self.items[ReturnToMutFnLangItem as uint]
261 pub fn check_not_borrowed_fn(&self) -> Option<def_id> {
262 self.items[CheckNotBorrowedFnLangItem as uint]
264 pub fn strdup_uniq_fn(&self) -> Option<def_id> {
265 self.items[StrDupUniqFnLangItem as uint]
267 pub fn record_borrow_fn(&self) -> Option<def_id> {
268 self.items[RecordBorrowFnLangItem as uint]
270 pub fn unrecord_borrow_fn(&self) -> Option<def_id> {
271 self.items[UnrecordBorrowFnLangItem as uint]
273 pub fn start_fn(&self) -> Option<def_id> {
274 self.items[StartFnLangItem as uint]
276 pub fn ty_desc(&self) -> Option<def_id> {
277 self.items[TyDescStructLangItem as uint]
279 pub fn ty_visitor(&self) -> Option<def_id> {
280 self.items[TyVisitorTraitLangItem as uint]
282 pub fn opaque(&self) -> Option<def_id> {
283 self.items[OpaqueStructLangItem as uint]
287 struct LanguageItemCollector<'self> {
288 items: LanguageItems,
293 item_refs: HashMap<@str, uint>,
296 struct LanguageItemVisitor<'self> {
297 this: *mut LanguageItemCollector<'self>,
300 impl<'self> Visitor<()> for LanguageItemVisitor<'self> {
302 fn visit_item(&mut self, item:@item, _:()) {
304 for attribute in item.attrs.iter() {
306 (*self.this).match_and_collect_meta_item(
313 visit::walk_item(self, item, ());
317 impl<'self> LanguageItemCollector<'self> {
318 pub fn new<'a>(crate: &'a Crate, session: Session)
319 -> LanguageItemCollector<'a> {
320 let mut item_refs = HashMap::new();
322 item_refs.insert(@"freeze", FreezeTraitLangItem as uint);
323 item_refs.insert(@"send", SendTraitLangItem as uint);
324 item_refs.insert(@"sized", SizedTraitLangItem as uint);
326 item_refs.insert(@"drop", DropTraitLangItem as uint);
328 item_refs.insert(@"add", AddTraitLangItem as uint);
329 item_refs.insert(@"sub", SubTraitLangItem as uint);
330 item_refs.insert(@"mul", MulTraitLangItem as uint);
331 item_refs.insert(@"div", DivTraitLangItem as uint);
332 item_refs.insert(@"rem", RemTraitLangItem as uint);
333 item_refs.insert(@"neg", NegTraitLangItem as uint);
334 item_refs.insert(@"not", NotTraitLangItem as uint);
335 item_refs.insert(@"bitxor", BitXorTraitLangItem as uint);
336 item_refs.insert(@"bitand", BitAndTraitLangItem as uint);
337 item_refs.insert(@"bitor", BitOrTraitLangItem as uint);
338 item_refs.insert(@"shl", ShlTraitLangItem as uint);
339 item_refs.insert(@"shr", ShrTraitLangItem as uint);
340 item_refs.insert(@"index", IndexTraitLangItem as uint);
342 item_refs.insert(@"eq", EqTraitLangItem as uint);
343 item_refs.insert(@"ord", OrdTraitLangItem as uint);
345 item_refs.insert(@"str_eq", StrEqFnLangItem as uint);
346 item_refs.insert(@"uniq_str_eq", UniqStrEqFnLangItem as uint);
347 item_refs.insert(@"log_type", LogTypeFnLangItem as uint);
348 item_refs.insert(@"fail_", FailFnLangItem as uint);
349 item_refs.insert(@"fail_bounds_check",
350 FailBoundsCheckFnLangItem as uint);
351 item_refs.insert(@"exchange_malloc", ExchangeMallocFnLangItem as uint);
352 item_refs.insert(@"closure_exchange_malloc", ClosureExchangeMallocFnLangItem as uint);
353 item_refs.insert(@"exchange_free", ExchangeFreeFnLangItem as uint);
354 item_refs.insert(@"malloc", MallocFnLangItem as uint);
355 item_refs.insert(@"free", FreeFnLangItem as uint);
356 item_refs.insert(@"borrow_as_imm", BorrowAsImmFnLangItem as uint);
357 item_refs.insert(@"borrow_as_mut", BorrowAsMutFnLangItem as uint);
358 item_refs.insert(@"return_to_mut", ReturnToMutFnLangItem as uint);
359 item_refs.insert(@"check_not_borrowed",
360 CheckNotBorrowedFnLangItem as uint);
361 item_refs.insert(@"strdup_uniq", StrDupUniqFnLangItem as uint);
362 item_refs.insert(@"record_borrow", RecordBorrowFnLangItem as uint);
363 item_refs.insert(@"unrecord_borrow", UnrecordBorrowFnLangItem as uint);
364 item_refs.insert(@"start", StartFnLangItem as uint);
365 item_refs.insert(@"ty_desc", TyDescStructLangItem as uint);
366 item_refs.insert(@"ty_visitor", TyVisitorTraitLangItem as uint);
367 item_refs.insert(@"opaque", OpaqueStructLangItem as uint);
369 LanguageItemCollector {
372 items: LanguageItems::new(),
377 pub fn match_and_collect_meta_item(&mut self,
379 meta_item: &MetaItem) {
380 match meta_item.name_str_pair() {
381 Some((key, value)) => {
382 self.match_and_collect_item(item_def_id, key, value);
388 pub fn collect_item(&mut self, item_index: uint, item_def_id: def_id) {
389 // Check for duplicates.
390 match self.items.items[item_index] {
391 Some(original_def_id) if original_def_id != item_def_id => {
392 self.session.err(fmt!("duplicate entry for `%s`",
393 LanguageItems::item_name(item_index)));
401 self.items.items[item_index] = Some(item_def_id);
404 pub fn match_and_collect_item(&mut self,
409 return; // Didn't match.
412 let item_index = self.item_refs.find(&value).map_move(|x| *x);
413 // prevent borrow checker from considering ^~~~~~~~~~~
414 // self to be borrowed (annoying)
417 Some(item_index) => {
418 self.collect_item(item_index, item_def_id);
427 pub fn collect_local_language_items(&mut self) {
428 let this: *mut LanguageItemCollector = &mut *self;
429 let mut v = LanguageItemVisitor { this: this };
430 visit::walk_crate(&mut v, self.crate, ());
433 pub fn collect_external_language_items(&mut self) {
434 let crate_store = self.session.cstore;
435 do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
436 do each_lang_item(crate_store, crate_number)
437 |node_id, item_index| {
438 let def_id = def_id { crate: crate_number, node: node_id };
439 self.collect_item(item_index, def_id);
445 pub fn collect(&mut self) {
446 self.collect_local_language_items();
447 self.collect_external_language_items();
451 pub fn collect_language_items(crate: &Crate,
454 let mut collector = LanguageItemCollector::new(crate, session);
456 let LanguageItemCollector { items, _ } = collector;
457 session.abort_if_errors();