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. "Share", "Send".
17 //
18 // * Traits that represent operators; e.g. "Add", "Sub", "Index".
19 //
20 // * Functions called by the compiler itself.
21
22
23 use driver::session::Session;
24 use metadata::csearch::each_lang_item;
25 use middle::ty;
26 use syntax::ast;
27 use syntax::ast_util::local_def;
28 use syntax::attr::AttrMetaMethods;
29 use syntax::parse::token::InternedString;
30 use syntax::visit::Visitor;
31 use syntax::visit;
32
33 use collections::HashMap;
34 use std::iter::Enumerate;
35 use std::slice;
36
37 // The actual lang items defined come at the end of this file in one handy table.
38 // So you probably just want to nip down to the end.
39 macro_rules! lets_do_this {
40 (
41 $( $variant:ident, $name:expr, $method:ident; )*
42 ) => {
43
44 #[deriving(FromPrimitive)]
45 pub enum LangItem {
46 $($variant),*
47 }
48
49 pub struct LanguageItems {
50 pub items: Vec<Option<ast::DefId>> ,
51 }
52
53 impl LanguageItems {
54 pub fn new() -> LanguageItems {
55 fn foo(_: LangItem) -> Option<ast::DefId> { None }
56
57 LanguageItems {
58 items: vec!($(foo($variant)),*)
59 }
60 }
61
62 pub fn items<'a>(&'a self) -> Enumerate<slice::Items<'a, Option<ast::DefId>>> {
63 self.items.iter().enumerate()
64 }
65
66 pub fn item_name(index: uint) -> &'static str {
67 let item: Option<LangItem> = FromPrimitive::from_uint(index);
68 match item {
69 $( Some($variant) => $name, )*
70 None => "???"
71 }
72 }
73
74 pub fn require(&self, it: LangItem) -> Result<ast::DefId, ~str> {
75 match self.items.get(it as uint) {
76 &Some(id) => Ok(id),
77 &None => {
78 Err(format!("requires `{}` lang_item",
79 LanguageItems::item_name(it as uint)))
80 }
81 }
82 }
83
84 pub fn to_builtin_kind(&self, id: ast::DefId) -> Option<ty::BuiltinBound> {
85 if Some(id) == self.send_trait() {
86 Some(ty::BoundSend)
87 } else if Some(id) == self.sized_trait() {
88 Some(ty::BoundSized)
89 } else if Some(id) == self.copy_trait() {
90 Some(ty::BoundCopy)
91 } else if Some(id) == self.share_trait() {
92 Some(ty::BoundShare)
93 } else {
94 None
95 }
96 }
97
98 $(
99 #[allow(dead_code)]
100 pub fn $method(&self) -> Option<ast::DefId> {
101 *self.items.get($variant as uint)
102 }
103 )*
104 }
105
106 struct LanguageItemCollector<'a> {
107 items: LanguageItems,
108
109 session: &'a Session,
110
111 item_refs: HashMap<&'static str, uint>,
112 }
113
114 impl<'a> Visitor<()> for LanguageItemCollector<'a> {
115 fn visit_item(&mut self, item: &ast::Item, _: ()) {
116 match extract(item.attrs.as_slice()) {
117 Some(value) => {
118 let item_index = self.item_refs.find_equiv(&value).map(|x| *x);
119
120 match item_index {
121 Some(item_index) => {
122 self.collect_item(item_index, local_def(item.id))
123 }
124 None => {}
125 }
126 }
127 None => {}
128 }
129
130 visit::walk_item(self, item, ());
131 }
132 }
133
134 impl<'a> LanguageItemCollector<'a> {
135 pub fn new(session: &'a Session) -> LanguageItemCollector<'a> {
136 let mut item_refs = HashMap::new();
137
138 $( item_refs.insert($name, $variant as uint); )*
139
140 LanguageItemCollector {
141 session: session,
142 items: LanguageItems::new(),
143 item_refs: item_refs
144 }
145 }
146
147 pub fn collect_item(&mut self, item_index: uint, item_def_id: ast::DefId) {
148 // Check for duplicates.
149 match self.items.items.get(item_index) {
150 &Some(original_def_id) if original_def_id != item_def_id => {
151 self.session.err(format!("duplicate entry for `{}`",
152 LanguageItems::item_name(item_index)));
153 }
154 &Some(_) | &None => {
155 // OK.
156 }
157 }
158
159 // Matched.
160 *self.items.items.get_mut(item_index) = Some(item_def_id);
161 }
162
163 pub fn collect_local_language_items(&mut self, krate: &ast::Crate) {
164 visit::walk_crate(self, krate, ());
165 }
166
167 pub fn collect_external_language_items(&mut self) {
168 let crate_store = &self.session.cstore;
169 crate_store.iter_crate_data(|crate_number, _crate_metadata| {
170 each_lang_item(crate_store, crate_number, |node_id, item_index| {
171 let def_id = ast::DefId { krate: crate_number, node: node_id };
172 self.collect_item(item_index, def_id);
173 true
174 });
175 })
176 }
177
178 pub fn collect(&mut self, krate: &ast::Crate) {
179 self.collect_local_language_items(krate);
180 self.collect_external_language_items();
181 }
182 }
183
184 pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
185 for attribute in attrs.iter() {
186 match attribute.name_str_pair() {
187 Some((ref key, ref value)) if key.equiv(&("lang")) => {
188 return Some((*value).clone());
189 }
190 Some(..) | None => {}
191 }
192 }
193
194 return None;
195 }
196
197 pub fn collect_language_items(krate: &ast::Crate,
198 session: &Session) -> LanguageItems {
199 let mut collector = LanguageItemCollector::new(session);
200 collector.collect(krate);
201 let LanguageItemCollector { items, .. } = collector;
202 session.abort_if_errors();
203 items
204 }
205
206 // End of the macro
207 }
208 }
209
210 lets_do_this! {
211 // Variant name, Name, Method name;
212 SendTraitLangItem, "send", send_trait;
213 SizedTraitLangItem, "sized", sized_trait;
214 CopyTraitLangItem, "copy", copy_trait;
215 ShareTraitLangItem, "share", share_trait;
216
217 DropTraitLangItem, "drop", drop_trait;
218
219 AddTraitLangItem, "add", add_trait;
220 SubTraitLangItem, "sub", sub_trait;
221 MulTraitLangItem, "mul", mul_trait;
222 DivTraitLangItem, "div", div_trait;
223 RemTraitLangItem, "rem", rem_trait;
224 NegTraitLangItem, "neg", neg_trait;
225 NotTraitLangItem, "not", not_trait;
226 BitXorTraitLangItem, "bitxor", bitxor_trait;
227 BitAndTraitLangItem, "bitand", bitand_trait;
228 BitOrTraitLangItem, "bitor", bitor_trait;
229 ShlTraitLangItem, "shl", shl_trait;
230 ShrTraitLangItem, "shr", shr_trait;
231 IndexTraitLangItem, "index", index_trait;
232
233 UnsafeTypeLangItem, "unsafe", unsafe_type;
234
235 DerefTraitLangItem, "deref", deref_trait;
236 DerefMutTraitLangItem, "deref_mut", deref_mut_trait;
237
238 EqTraitLangItem, "eq", eq_trait;
239 OrdTraitLangItem, "ord", ord_trait;
240
241 StrEqFnLangItem, "str_eq", str_eq_fn;
242 UniqStrEqFnLangItem, "uniq_str_eq", uniq_str_eq_fn;
243 FailFnLangItem, "fail_", fail_fn;
244 FailBoundsCheckFnLangItem, "fail_bounds_check", fail_bounds_check_fn;
245 ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
246 ClosureExchangeMallocFnLangItem, "closure_exchange_malloc", closure_exchange_malloc_fn;
247 ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
248 MallocFnLangItem, "malloc", malloc_fn;
249 FreeFnLangItem, "free", free_fn;
250 StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn;
251
252 StartFnLangItem, "start", start_fn;
253
254 TyDescStructLangItem, "ty_desc", ty_desc;
255 TyVisitorTraitLangItem, "ty_visitor", ty_visitor;
256 OpaqueStructLangItem, "opaque", opaque;
257
258 TypeIdLangItem, "type_id", type_id;
259
260 EhPersonalityLangItem, "eh_personality", eh_personality_fn;
261
262 ManagedHeapLangItem, "managed_heap", managed_heap;
263 ExchangeHeapLangItem, "exchange_heap", exchange_heap;
264 GcLangItem, "gc", gc;
265 OwnedBoxLangItem, "owned_box", owned_box;
266
267 CovariantTypeItem, "covariant_type", covariant_type;
268 ContravariantTypeItem, "contravariant_type", contravariant_type;
269 InvariantTypeItem, "invariant_type", invariant_type;
270
271 CovariantLifetimeItem, "covariant_lifetime", covariant_lifetime;
272 ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime;
273 InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime;
274
275 NoSendItem, "no_send_bound", no_send_bound;
276 NoCopyItem, "no_copy_bound", no_copy_bound;
277 NoShareItem, "no_share_bound", no_share_bound;
278 ManagedItem, "managed_bound", managed_bound;
279 }
librustc/middle/lang_items.rs:55:8-55:8 -fn- definition:
fn foo(_: LangItem) -> Option<ast::DefId> { None }
LanguageItems {
items: vec!($(foo($variant)),*)
references:- 53librustc/middle/lang_items.rs:105:1-105:1 -struct- definition:
struct LanguageItemCollector<'a> {
items: LanguageItems,
session: &'a Session,
references:- 5200: collector.collect(krate);
201: let LanguageItemCollector { items, .. } = collector;
202: session.abort_if_errors();
librustc/middle/lang_items.rs:48:1-48:1 -struct- definition:
pub struct LanguageItems {
pub items: Vec<Option<ast::DefId>> ,
}
references:- 1057: LanguageItems {
58: items: vec!($(foo($variant)),*)
--
106: struct LanguageItemCollector<'a> {
107: items: LanguageItems,
--
197: pub fn collect_language_items(krate: &ast::Crate,
198: session: &Session) -> LanguageItems {
199: let mut collector = LanguageItemCollector::new(session);
librustc/middle/ty.rs:
288: pub normalized_cache: RefCell<HashMap<t, t>>,
289: pub lang_items: middle::lang_items::LanguageItems,
290: // A mapping of fake provided method def_ids to the default implementation
--
1077: region_maps: middle::region::RegionMaps,
1078: lang_items: middle::lang_items::LanguageItems)
1079: -> ctxt {
librustc/middle/resolve.rs:
858: session: &'a Session,
859: lang_items: &'a LanguageItems,
--
5380: pub fn resolve_crate(session: &Session,
5381: lang_items: &LanguageItems,
5382: krate: &Crate)
librustc/middle/lang_items.rs:44:27-44:27 -enum- definition:
pub enum LangItem {
$($variant),*
}
references:- 945: pub enum LangItem {
--
74: pub fn require(&self, it: LangItem) -> Result<ast::DefId, ~str> {
75: match self.items.get(it as uint) {
librustc/middle/trans/common.rs:
858: msg: &str,
859: li: LangItem)
860: -> ast::DefId {
librustc/middle/trans/base.rs:
365: t: ty::t,
366: alloc_fn: LangItem,
367: size: ValueRef)