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", "Copy", "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, lit_str, meta_item}
;
27 use syntax
::ast
::{meta_list, meta_name_value, meta_word}
;
28 use syntax
::ast_util
::local_def
;
29 use syntax
::visit
::{default_simple_visitor, mk_simple_visitor, SimpleVisitor}
;
30 use syntax
::visit
::visit_crate
;
32 use std
::hashmap
::HashMap
;
35 FreezeTraitLangItem
, // 0
36 CopyTraitLangItem
, // 1
37 SendTraitLangItem
, // 2
38 SizedTraitLangItem
, // 3
40 DropTraitLangItem
, // 4
42 AddTraitLangItem
, // 5
43 SubTraitLangItem
, // 6
44 MulTraitLangItem
, // 7
45 DivTraitLangItem
, // 8
46 RemTraitLangItem
, // 9
47 NegTraitLangItem
, // 10
48 NotTraitLangItem
, // 11
49 BitXorTraitLangItem
, // 11
50 BitAndTraitLangItem
, // 13
51 BitOrTraitLangItem
, // 14
52 ShlTraitLangItem
, // 15
53 ShrTraitLangItem
, // 16
54 IndexTraitLangItem
, // 17
56 EqTraitLangItem
, // 18
57 OrdTraitLangItem
, // 19
59 StrEqFnLangItem
, // 20
60 UniqStrEqFnLangItem
, // 21
61 AnnihilateFnLangItem
, // 22
62 LogTypeFnLangItem
, // 23
64 FailBoundsCheckFnLangItem
, // 25
65 ExchangeMallocFnLangItem
, // 26
66 ClosureExchangeMallocFnLangItem
, // 27
67 ExchangeFreeFnLangItem
, // 28
68 MallocFnLangItem
, // 29
70 BorrowAsImmFnLangItem
, // 31
71 BorrowAsMutFnLangItem
, // 32
72 ReturnToMutFnLangItem
, // 33
73 CheckNotBorrowedFnLangItem
, // 34
74 StrDupUniqFnLangItem
, // 35
75 RecordBorrowFnLangItem
, // 36
76 UnrecordBorrowFnLangItem
, // 37
78 StartFnLangItem
, // 38
80 TyDescStructLangItem
, // 39
81 TyVisitorTraitLangItem
, // 40
82 OpaqueStructLangItem
, // 41
85 pub struct LanguageItems
{
86 items
: [Option
<def_id
>, ..42]
90 pub fn new() -> LanguageItems
{
96 pub fn each_item(&self, f
: &fn(def_id
: def_id
, i
: uint
) -> bool
) -> bool
{
97 self.items
.iter().enumerate().advance(|(i
, &item
)| f(item
.get(), i
))
100 pub fn item_name(index
: uint
) -> &'
static str {
130 25 => "fail_bounds_check",
131 26 => "exchange_malloc",
132 27 => "closure_exchange_malloc",
133 28 => "exchange_free",
136 31 => "borrow_as_imm",
137 32 => "borrow_as_mut",
138 33 => "return_to_mut",
139 34 => "check_not_borrowed",
141 36 => "record_borrow",
142 37 => "unrecord_borrow",
154 // FIXME #4621: Method macros sure would be nice here.
156 pub fn freeze_trait(&self) -> def_id
{
157 self.items
[FreezeTraitLangItem
as uint
].get()
159 pub fn copy_trait(&self) -> def_id
{
160 self.items
[CopyTraitLangItem
as uint
].get()
162 pub fn send_trait(&self) -> def_id
{
163 self.items
[SendTraitLangItem
as uint
].get()
165 pub fn sized_trait(&self) -> def_id
{
166 self.items
[SizedTraitLangItem
as uint
].get()
169 pub fn drop_trait(&self) -> def_id
{
170 self.items
[DropTraitLangItem
as uint
].get()
173 pub fn add_trait(&self) -> def_id
{
174 self.items
[AddTraitLangItem
as uint
].get()
176 pub fn sub_trait(&self) -> def_id
{
177 self.items
[SubTraitLangItem
as uint
].get()
179 pub fn mul_trait(&self) -> def_id
{
180 self.items
[MulTraitLangItem
as uint
].get()
182 pub fn div_trait(&self) -> def_id
{
183 self.items
[DivTraitLangItem
as uint
].get()
185 pub fn rem_trait(&self) -> def_id
{
186 self.items
[RemTraitLangItem
as uint
].get()
188 pub fn neg_trait(&self) -> def_id
{
189 self.items
[NegTraitLangItem
as uint
].get()
191 pub fn not_trait(&self) -> def_id
{
192 self.items
[NotTraitLangItem
as uint
].get()
194 pub fn bitxor_trait(&self) -> def_id
{
195 self.items
[BitXorTraitLangItem
as uint
].get()
197 pub fn bitand_trait(&self) -> def_id
{
198 self.items
[BitAndTraitLangItem
as uint
].get()
200 pub fn bitor_trait(&self) -> def_id
{
201 self.items
[BitOrTraitLangItem
as uint
].get()
203 pub fn shl_trait(&self) -> def_id
{
204 self.items
[ShlTraitLangItem
as uint
].get()
206 pub fn shr_trait(&self) -> def_id
{
207 self.items
[ShrTraitLangItem
as uint
].get()
209 pub fn index_trait(&self) -> def_id
{
210 self.items
[IndexTraitLangItem
as uint
].get()
213 pub fn eq_trait(&self) -> def_id
{
214 self.items
[EqTraitLangItem
as uint
].get()
216 pub fn ord_trait(&self) -> def_id
{
217 self.items
[OrdTraitLangItem
as uint
].get()
220 pub fn str_eq_fn(&self) -> def_id
{
221 self.items
[StrEqFnLangItem
as uint
].get()
223 pub fn uniq_str_eq_fn(&self) -> def_id
{
224 self.items
[UniqStrEqFnLangItem
as uint
].get()
226 pub fn annihilate_fn(&self) -> def_id
{
227 self.items
[AnnihilateFnLangItem
as uint
].get()
229 pub fn log_type_fn(&self) -> def_id
{
230 self.items
[LogTypeFnLangItem
as uint
].get()
232 pub fn fail_fn(&self) -> def_id
{
233 self.items
[FailFnLangItem
as uint
].get()
235 pub fn fail_bounds_check_fn(&self) -> def_id
{
236 self.items
[FailBoundsCheckFnLangItem
as uint
].get()
238 pub fn exchange_malloc_fn(&self) -> def_id
{
239 self.items
[ExchangeMallocFnLangItem
as uint
].get()
241 pub fn closure_exchange_malloc_fn(&self) -> def_id
{
242 self.items
[ClosureExchangeMallocFnLangItem
as uint
].get()
244 pub fn exchange_free_fn(&self) -> def_id
{
245 self.items
[ExchangeFreeFnLangItem
as uint
].get()
247 pub fn malloc_fn(&self) -> def_id
{
248 self.items
[MallocFnLangItem
as uint
].get()
250 pub fn free_fn(&self) -> def_id
{
251 self.items
[FreeFnLangItem
as uint
].get()
253 pub fn borrow_as_imm_fn(&self) -> def_id
{
254 self.items
[BorrowAsImmFnLangItem
as uint
].get()
256 pub fn borrow_as_mut_fn(&self) -> def_id
{
257 self.items
[BorrowAsMutFnLangItem
as uint
].get()
259 pub fn return_to_mut_fn(&self) -> def_id
{
260 self.items
[ReturnToMutFnLangItem
as uint
].get()
262 pub fn check_not_borrowed_fn(&self) -> def_id
{
263 self.items
[CheckNotBorrowedFnLangItem
as uint
].get()
265 pub fn strdup_uniq_fn(&self) -> def_id
{
266 self.items
[StrDupUniqFnLangItem
as uint
].get()
268 pub fn record_borrow_fn(&self) -> def_id
{
269 self.items
[RecordBorrowFnLangItem
as uint
].get()
271 pub fn unrecord_borrow_fn(&self) -> def_id
{
272 self.items
[UnrecordBorrowFnLangItem
as uint
].get()
274 pub fn start_fn(&self) -> def_id
{
275 self.items
[StartFnLangItem
as uint
].get()
277 pub fn ty_desc(&const self) -> def_id
{
278 self.items
[TyDescStructLangItem
as uint
].get()
280 pub fn ty_visitor(&const self) -> def_id
{
281 self.items
[TyVisitorTraitLangItem
as uint
].get()
283 pub fn opaque(&const self) -> def_id
{
284 self.items
[OpaqueStructLangItem
as uint
].get()
288 struct LanguageItemCollector
<'
self> {
289 items
: LanguageItems
,
294 item_refs
: HashMap
<@
str, uint
>,
297 impl<'
self> LanguageItemCollector
<'
self> {
298 pub fn new
<'a
>(crate: &'a
crate, session
: Session
)
299 -> LanguageItemCollector
<'a
> {
300 let mut item_refs
= HashMap
::new();
302 item_refs
.insert(@
"freeze", FreezeTraitLangItem
as uint
);
303 item_refs
.insert(@
"copy", CopyTraitLangItem
as uint
);
304 item_refs
.insert(@
"send", SendTraitLangItem
as uint
);
305 item_refs
.insert(@
"sized", SizedTraitLangItem
as uint
);
307 item_refs
.insert(@
"drop", DropTraitLangItem
as uint
);
309 item_refs
.insert(@
"add", AddTraitLangItem
as uint
);
310 item_refs
.insert(@
"sub", SubTraitLangItem
as uint
);
311 item_refs
.insert(@
"mul", MulTraitLangItem
as uint
);
312 item_refs
.insert(@
"div", DivTraitLangItem
as uint
);
313 item_refs
.insert(@
"rem", RemTraitLangItem
as uint
);
314 item_refs
.insert(@
"neg", NegTraitLangItem
as uint
);
315 item_refs
.insert(@
"not", NotTraitLangItem
as uint
);
316 item_refs
.insert(@
"bitxor", BitXorTraitLangItem
as uint
);
317 item_refs
.insert(@
"bitand", BitAndTraitLangItem
as uint
);
318 item_refs
.insert(@
"bitor", BitOrTraitLangItem
as uint
);
319 item_refs
.insert(@
"shl", ShlTraitLangItem
as uint
);
320 item_refs
.insert(@
"shr", ShrTraitLangItem
as uint
);
321 item_refs
.insert(@
"index", IndexTraitLangItem
as uint
);
323 item_refs
.insert(@
"eq", EqTraitLangItem
as uint
);
324 item_refs
.insert(@
"ord", OrdTraitLangItem
as uint
);
326 item_refs
.insert(@
"str_eq", StrEqFnLangItem
as uint
);
327 item_refs
.insert(@
"uniq_str_eq", UniqStrEqFnLangItem
as uint
);
328 item_refs
.insert(@
"annihilate", AnnihilateFnLangItem
as uint
);
329 item_refs
.insert(@
"log_type", LogTypeFnLangItem
as uint
);
330 item_refs
.insert(@
"fail_", FailFnLangItem
as uint
);
331 item_refs
.insert(@
"fail_bounds_check",
332 FailBoundsCheckFnLangItem
as uint
);
333 item_refs
.insert(@
"exchange_malloc", ExchangeMallocFnLangItem
as uint
);
334 item_refs
.insert(@
"closure_exchange_malloc", ClosureExchangeMallocFnLangItem
as uint
);
335 item_refs
.insert(@
"exchange_free", ExchangeFreeFnLangItem
as uint
);
336 item_refs
.insert(@
"malloc", MallocFnLangItem
as uint
);
337 item_refs
.insert(@
"free", FreeFnLangItem
as uint
);
338 item_refs
.insert(@
"borrow_as_imm", BorrowAsImmFnLangItem
as uint
);
339 item_refs
.insert(@
"borrow_as_mut", BorrowAsMutFnLangItem
as uint
);
340 item_refs
.insert(@
"return_to_mut", ReturnToMutFnLangItem
as uint
);
341 item_refs
.insert(@
"check_not_borrowed",
342 CheckNotBorrowedFnLangItem
as uint
);
343 item_refs
.insert(@
"strdup_uniq", StrDupUniqFnLangItem
as uint
);
344 item_refs
.insert(@
"record_borrow", RecordBorrowFnLangItem
as uint
);
345 item_refs
.insert(@
"unrecord_borrow", UnrecordBorrowFnLangItem
as uint
);
346 item_refs
.insert(@
"start", StartFnLangItem
as uint
);
347 item_refs
.insert(@
"ty_desc", TyDescStructLangItem
as uint
);
348 item_refs
.insert(@
"ty_visitor", TyVisitorTraitLangItem
as uint
);
349 item_refs
.insert(@
"opaque", OpaqueStructLangItem
as uint
);
351 LanguageItemCollector
{
354 items
: LanguageItems
::new(),
359 pub fn match_and_collect_meta_item(&mut self,
361 meta_item
: &meta_item
) {
362 match meta_item
.node
{
363 meta_name_value(key
, literal
) => {
366 self.match_and_collect_item(item_def_id
, key
, value
);
371 meta_word(*) | meta_list(*) => {}
// Skip.
375 pub fn collect_item(&mut self, item_index
: uint
, item_def_id
: def_id
) {
376 // Check for duplicates.
377 match self.items
.items
[item_index
] {
378 Some(original_def_id
) if original_def_id
!= item_def_id
=> {
379 self.session
.err(fmt
!("duplicate entry for `%s`",
380 LanguageItems
::item_name(item_index
)));
388 self.items
.items
[item_index
] = Some(item_def_id
);
391 pub fn match_and_collect_item(&mut self,
396 return; // Didn't match.
399 let item_index
= self.item_refs
.find(&value
).map(|x
| **x
);
400 // prevent borrow checker from considering ^~~~~~~~~~~
401 // self to be borrowed (annoying)
404 Some(item_index
) => {
405 self.collect_item(item_index
, item_def_id
);
414 pub fn collect_local_language_items(&mut self) {
415 let this
: *mut LanguageItemCollector
= &mut *self;
416 visit_crate(self.crate, ((), mk_simple_visitor(@SimpleVisitor
{
418 for item
.attrs
.iter().advance
|attribute
| {
420 (*this
).match_and_collect_meta_item(
427 .. *default_simple_visitor()
431 pub fn collect_external_language_items(&mut self) {
432 let crate_store
= self.session
.cstore
;
433 do iter_crate_data(crate_store
) |crate_number
, _crate_metadata
| {
434 for each_lang_item(crate_store
, crate_number
)
435 |node_id
, item_index
| {
436 let def_id
= def_id { crate: crate_number, node: node_id }
;
437 self.collect_item(item_index
, def_id
);
442 pub fn check_completeness(&self) {
443 for self.item_refs
.iter().advance
|(&key
, &item_ref
)| {
444 match self.items
.items
[item_ref
] {
446 self.session
.err(fmt
!("no item found for `%s`", key
));
455 pub fn collect(&mut self) {
456 self.collect_local_language_items();
457 self.collect_external_language_items();
458 self.check_completeness();
462 pub fn collect_language_items(crate: &crate,
465 let mut collector
= LanguageItemCollector
::new(crate, session
);
467 let LanguageItemCollector { items, _ }
= collector
;
468 session
.abort_if_errors();