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