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. "Sync", "Send".
18 // * Traits that represent operators; e.g. "Add", "Sub", "Index".
20 // * Functions called by the compiler itself.
22 pub use self::LangItem
::*;
25 use metadata
::csearch
::each_lang_item
;
27 use middle
::weak_lang_items
;
28 use util
::nodemap
::FnvHashMap
;
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
;
38 use std
::iter
::Enumerate
;
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
{
45 $
( $variant
:ident
, $name
:expr
, $method
:ident
; )*
50 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
56 pub struct LanguageItems
{
57 pub items
: Vec
<Option
<ast
::DefId
>>,
58 pub missing
: Vec
<LangItem
>,
62 pub fn new() -> LanguageItems
{
63 fn foo(_
: LangItem
) -> Option
<ast
::DefId
> { None }
66 items
: vec
!($
(foo($variant
)),*),
71 pub fn items
<'a
>(&'a
self) -> Enumerate
<slice
::Iter
<'a
, Option
<ast
::DefId
>>> {
72 self.items
.iter().enumerate()
75 pub fn item_name(index
: usize) -> &'
static str {
76 let item
: Option
<LangItem
> = LangItem
::from_u32(index
as u32);
78 $
( Some($variant
) => $name
, )*
83 pub fn require(&self, it
: LangItem
) -> Result
<ast
::DefId
, String
> {
84 match self.items
[it
as usize] {
87 Err(format
!("requires `{}` lang_item",
88 LanguageItems
::item_name(it
as usize)))
93 pub fn require_owned_box(&self) -> Result
<ast
::DefId
, String
> {
94 self.require(OwnedBoxLangItem
)
97 pub fn from_builtin_kind(&self, bound
: ty
::BuiltinBound
)
98 -> Result
<ast
::DefId
, String
>
101 ty
::BoundSend
=> self.require(SendTraitLangItem
),
102 ty
::BoundSized
=> self.require(SizedTraitLangItem
),
103 ty
::BoundCopy
=> self.require(CopyTraitLangItem
),
104 ty
::BoundSync
=> self.require(SyncTraitLangItem
),
108 pub fn to_builtin_kind(&self, id
: ast
::DefId
) -> Option
<ty
::BuiltinBound
> {
109 if Some(id
) == self.send_trait() {
111 } else if Some(id
) == self.sized_trait() {
113 } else if Some(id
) == self.copy_trait() {
115 } else if Some(id
) == self.sync_trait() {
122 pub fn fn_trait_kind(&self, id
: ast
::DefId
) -> Option
<ty
::ClosureKind
> {
124 (self.fn_trait(), ty
::FnClosureKind
),
125 (self.fn_mut_trait(), ty
::FnMutClosureKind
),
126 (self.fn_once_trait(), ty
::FnOnceClosureKind
),
129 for &(opt_def_id
, kind
) in &def_id_kinds
{
130 if Some(id
) == opt_def_id
{
140 pub fn $
method(&self) -> Option
<ast
::DefId
> {
141 self.items
[$variant
as usize]
146 struct LanguageItemCollector
<'a
> {
147 items
: LanguageItems
,
149 session
: &'a Session
,
151 item_refs
: FnvHashMap
<&'
static str, usize>,
154 impl<'a
, 'v
> Visitor
<'v
> for LanguageItemCollector
<'a
> {
155 fn visit_item(&mut self, item
: &ast
::Item
) {
156 if let Some(value
) = extract(&item
.attrs
) {
157 let item_index
= self.item_refs
.get(&value
[..]).cloned();
159 if let Some(item_index
) = item_index
{
160 self.collect_item(item_index
, local_def(item
.id
), item
.span
)
164 visit
::walk_item(self, item
);
168 impl<'a
> LanguageItemCollector
<'a
> {
169 pub fn new(session
: &'a Session
) -> LanguageItemCollector
<'a
> {
170 let mut item_refs
= FnvHashMap();
172 $
( item_refs
.insert($name
, $variant
as usize); )*
174 LanguageItemCollector
{
176 items
: LanguageItems
::new(),
181 pub fn collect_item(&mut self, item_index
: usize,
182 item_def_id
: ast
::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
));
195 self.items
.items
[item_index
] = Some(item_def_id
);
198 pub fn collect_local_language_items(&mut self, krate
: &ast
::Crate
) {
199 visit
::walk_crate(self, krate
);
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
= ast
::DefId { krate: crate_number, node: node_id }
;
207 self.collect_item(item_index
, def_id
, DUMMY_SP
);
213 pub fn collect(&mut self, krate
: &ast
::Crate
) {
214 self.collect_local_language_items(krate
);
215 self.collect_external_language_items();
219 pub fn extract(attrs
: &[ast
::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());
232 pub fn collect_language_items(krate
: &ast
::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();
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
;
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
;
272 DropTraitLangItem
, "drop", drop_trait
;
274 CoerceUnsizedTraitLangItem
, "coerce_unsized", coerce_unsized_trait
;
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
;
295 UnsafeCellTypeLangItem
, "unsafe_cell", unsafe_cell_type
;
297 DerefTraitLangItem
, "deref", deref_trait
;
298 DerefMutTraitLangItem
, "deref_mut", deref_mut_trait
;
300 FnTraitLangItem
, "fn", fn_trait
;
301 FnMutTraitLangItem
, "fn_mut", fn_mut_trait
;
302 FnOnceTraitLangItem
, "fn_once", fn_once_trait
;
304 EqTraitLangItem
, "eq", eq_trait
;
305 OrdTraitLangItem
, "ord", ord_trait
;
307 StrEqFnLangItem
, "str_eq", str_eq_fn
;
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.
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
;
322 ExchangeMallocFnLangItem
, "exchange_malloc", exchange_malloc_fn
;
323 ExchangeFreeFnLangItem
, "exchange_free", exchange_free_fn
;
324 StrDupUniqFnLangItem
, "strdup_uniq", strdup_uniq_fn
;
326 StartFnLangItem
, "start", start_fn
;
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
;
333 ExchangeHeapLangItem
, "exchange_heap", exchange_heap
;
334 OwnedBoxLangItem
, "owned_box", owned_box
;
336 PhantomDataItem
, "phantom_data", phantom_data
;
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
;
346 NoCopyItem
, "no_copy_bound", no_copy_bound
;
348 NonZeroItem
, "non_zero", non_zero
;
350 StackExhaustedLangItem
, "stack_exhausted", stack_exhausted
;
352 DebugTraitLangItem
, "debug_trait", debug_trait
;