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
::*;
24 use dep_graph
::DepNode
;
25 use hir
::map
as hir_map
;
27 use hir
::def_id
::DefId
;
29 use middle
::weak_lang_items
;
30 use util
::nodemap
::FnvHashMap
;
33 use syntax
::parse
::token
::InternedString
;
34 use hir
::intravisit
::Visitor
;
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
! language_item_table
{
41 $
( $variant
:ident
, $name
:expr
, $method
:ident
; )*
46 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
52 pub struct LanguageItems
{
53 pub items
: Vec
<Option
<DefId
>>,
54 pub missing
: Vec
<LangItem
>,
58 pub fn new() -> LanguageItems
{
59 fn foo(_
: LangItem
) -> Option
<DefId
> { None }
62 items
: vec
!($
(foo($variant
)),*),
67 pub fn items(&self) -> &[Option
<DefId
>] {
71 pub fn item_name(index
: usize) -> &'
static str {
72 let item
: Option
<LangItem
> = LangItem
::from_u32(index
as u32);
74 $
( Some($variant
) => $name
, )*
79 pub fn require(&self, it
: LangItem
) -> Result
<DefId
, String
> {
80 match self.items
[it
as usize] {
83 Err(format
!("requires `{}` lang_item",
84 LanguageItems
::item_name(it
as usize)))
89 pub fn require_owned_box(&self) -> Result
<DefId
, String
> {
90 self.require(OwnedBoxLangItem
)
93 pub fn from_builtin_kind(&self, bound
: ty
::BuiltinBound
)
94 -> Result
<DefId
, String
>
97 ty
::BoundSend
=> self.require(SendTraitLangItem
),
98 ty
::BoundSized
=> self.require(SizedTraitLangItem
),
99 ty
::BoundCopy
=> self.require(CopyTraitLangItem
),
100 ty
::BoundSync
=> self.require(SyncTraitLangItem
),
104 pub fn to_builtin_kind(&self, id
: DefId
) -> Option
<ty
::BuiltinBound
> {
105 if Some(id
) == self.send_trait() {
107 } else if Some(id
) == self.sized_trait() {
109 } else if Some(id
) == self.copy_trait() {
111 } else if Some(id
) == self.sync_trait() {
118 pub fn fn_trait_kind(&self, id
: DefId
) -> Option
<ty
::ClosureKind
> {
120 (self.fn_trait(), ty
::ClosureKind
::Fn
),
121 (self.fn_mut_trait(), ty
::ClosureKind
::FnMut
),
122 (self.fn_once_trait(), ty
::ClosureKind
::FnOnce
),
125 for &(opt_def_id
, kind
) in &def_id_kinds
{
126 if Some(id
) == opt_def_id
{
136 pub fn $
method(&self) -> Option
<DefId
> {
137 self.items
[$variant
as usize]
142 struct LanguageItemCollector
<'a
, 'tcx
: 'a
> {
143 items
: LanguageItems
,
145 ast_map
: &'a hir_map
::Map
<'tcx
>,
147 session
: &'a Session
,
149 item_refs
: FnvHashMap
<&'
static str, usize>,
152 impl<'a
, 'v
, 'tcx
> Visitor
<'v
> for LanguageItemCollector
<'a
, 'tcx
> {
153 fn visit_item(&mut self, item
: &hir
::Item
) {
154 if let Some(value
) = extract(&item
.attrs
) {
155 let item_index
= self.item_refs
.get(&value
[..]).cloned();
157 if let Some(item_index
) = item_index
{
158 self.collect_item(item_index
, self.ast_map
.local_def_id(item
.id
))
160 let span
= self.ast_map
.span(item
.id
);
161 span_err
!(self.session
, span
, E0522
,
162 "definition of an unknown language item: `{}`.",
169 impl<'a
, 'tcx
> LanguageItemCollector
<'a
, 'tcx
> {
170 pub fn new(session
: &'a Session
, ast_map
: &'a hir_map
::Map
<'tcx
>)
171 -> LanguageItemCollector
<'a
, 'tcx
> {
172 let mut item_refs
= FnvHashMap();
174 $
( item_refs
.insert($name
, $variant
as usize); )*
176 LanguageItemCollector
{
179 items
: LanguageItems
::new(),
180 item_refs
: item_refs
,
184 pub fn collect_item(&mut self, item_index
: usize,
185 item_def_id
: DefId
) {
186 // Check for duplicates.
187 match self.items
.items
[item_index
] {
188 Some(original_def_id
) if original_def_id
!= item_def_id
=> {
189 let cstore
= &self.session
.cstore
;
190 let name
= LanguageItems
::item_name(item_index
);
191 let mut err
= match self.ast_map
.span_if_local(item_def_id
) {
192 Some(span
) => struct_span_err
!(
196 "duplicate lang item found: `{}`.",
198 None
=> self.session
.struct_err(&format
!(
199 "duplicate lang item in crate `{}`: `{}`.",
200 cstore
.crate_name(item_def_id
.krate
),
203 if let Some(span
) = self.ast_map
.span_if_local(original_def_id
) {
204 span_note
!(&mut err
, span
,
205 "first defined here.");
207 err
.note(&format
!("first defined in crate `{}`.",
208 cstore
.crate_name(original_def_id
.krate
)));
218 self.items
.items
[item_index
] = Some(item_def_id
);
221 pub fn collect_local_language_items(&mut self, krate
: &hir
::Crate
) {
222 krate
.visit_all_items(self);
225 pub fn collect_external_language_items(&mut self) {
226 let cstore
= &self.session
.cstore
;
228 for cnum
in cstore
.crates() {
229 for (index
, item_index
) in cstore
.lang_items(cnum
) {
230 let def_id
= DefId { krate: cnum, index: index }
;
231 self.collect_item(item_index
, def_id
);
236 pub fn collect(&mut self, krate
: &hir
::Crate
) {
237 self.collect_external_language_items();
238 self.collect_local_language_items(krate
);
242 pub fn extract(attrs
: &[ast
::Attribute
]) -> Option
<InternedString
> {
243 for attribute
in attrs
{
244 match attribute
.value_str() {
245 Some(ref value
) if attribute
.check_name("lang") => {
246 return Some(value
.clone());
255 pub fn collect_language_items(session
: &Session
,
258 let _task
= map
.dep_graph
.in_task(DepNode
::CollectLanguageItems
);
259 let krate
: &hir
::Crate
= map
.krate();
260 let mut collector
= LanguageItemCollector
::new(session
, map
);
261 collector
.collect(krate
);
262 let LanguageItemCollector { mut items, .. }
= collector
;
263 weak_lang_items
::check_crate(krate
, session
, &mut items
);
271 language_item_table
! {
272 // Variant name, Name, Method name;
273 CharImplItem
, "char", char_impl
;
274 StrImplItem
, "str", str_impl
;
275 SliceImplItem
, "slice", slice_impl
;
276 ConstPtrImplItem
, "const_ptr", const_ptr_impl
;
277 MutPtrImplItem
, "mut_ptr", mut_ptr_impl
;
278 I8ImplItem
, "i8", i8_impl
;
279 I16ImplItem
, "i16", i16_impl
;
280 I32ImplItem
, "i32", i32_impl
;
281 I64ImplItem
, "i64", i64_impl
;
282 IsizeImplItem
, "isize", isize_impl
;
283 U8ImplItem
, "u8", u8_impl
;
284 U16ImplItem
, "u16", u16_impl
;
285 U32ImplItem
, "u32", u32_impl
;
286 U64ImplItem
, "u64", u64_impl
;
287 UsizeImplItem
, "usize", usize_impl
;
288 F32ImplItem
, "f32", f32_impl
;
289 F64ImplItem
, "f64", f64_impl
;
291 SendTraitLangItem
, "send", send_trait
;
292 SizedTraitLangItem
, "sized", sized_trait
;
293 UnsizeTraitLangItem
, "unsize", unsize_trait
;
294 CopyTraitLangItem
, "copy", copy_trait
;
295 SyncTraitLangItem
, "sync", sync_trait
;
297 DropTraitLangItem
, "drop", drop_trait
;
299 CoerceUnsizedTraitLangItem
, "coerce_unsized", coerce_unsized_trait
;
301 AddTraitLangItem
, "add", add_trait
;
302 SubTraitLangItem
, "sub", sub_trait
;
303 MulTraitLangItem
, "mul", mul_trait
;
304 DivTraitLangItem
, "div", div_trait
;
305 RemTraitLangItem
, "rem", rem_trait
;
306 NegTraitLangItem
, "neg", neg_trait
;
307 NotTraitLangItem
, "not", not_trait
;
308 BitXorTraitLangItem
, "bitxor", bitxor_trait
;
309 BitAndTraitLangItem
, "bitand", bitand_trait
;
310 BitOrTraitLangItem
, "bitor", bitor_trait
;
311 ShlTraitLangItem
, "shl", shl_trait
;
312 ShrTraitLangItem
, "shr", shr_trait
;
313 AddAssignTraitLangItem
, "add_assign", add_assign_trait
;
314 SubAssignTraitLangItem
, "sub_assign", sub_assign_trait
;
315 MulAssignTraitLangItem
, "mul_assign", mul_assign_trait
;
316 DivAssignTraitLangItem
, "div_assign", div_assign_trait
;
317 RemAssignTraitLangItem
, "rem_assign", rem_assign_trait
;
318 BitXorAssignTraitLangItem
, "bitxor_assign", bitxor_assign_trait
;
319 BitAndAssignTraitLangItem
, "bitand_assign", bitand_assign_trait
;
320 BitOrAssignTraitLangItem
, "bitor_assign", bitor_assign_trait
;
321 ShlAssignTraitLangItem
, "shl_assign", shl_assign_trait
;
322 ShrAssignTraitLangItem
, "shr_assign", shr_assign_trait
;
323 IndexTraitLangItem
, "index", index_trait
;
324 IndexMutTraitLangItem
, "index_mut", index_mut_trait
;
326 UnsafeCellTypeLangItem
, "unsafe_cell", unsafe_cell_type
;
328 DerefTraitLangItem
, "deref", deref_trait
;
329 DerefMutTraitLangItem
, "deref_mut", deref_mut_trait
;
331 FnTraitLangItem
, "fn", fn_trait
;
332 FnMutTraitLangItem
, "fn_mut", fn_mut_trait
;
333 FnOnceTraitLangItem
, "fn_once", fn_once_trait
;
335 EqTraitLangItem
, "eq", eq_trait
;
336 OrdTraitLangItem
, "ord", ord_trait
;
338 StrEqFnLangItem
, "str_eq", str_eq_fn
;
340 // A number of panic-related lang items. The `panic` item corresponds to
341 // divide-by-zero and various panic cases with `match`. The
342 // `panic_bounds_check` item is for indexing arrays.
344 // The `begin_unwind` lang item has a predefined symbol name and is sort of
345 // a "weak lang item" in the sense that a crate is not required to have it
346 // defined to use it, but a final product is required to define it
347 // somewhere. Additionally, there are restrictions on crates that use a weak
348 // lang item, but do not have it defined.
349 PanicFnLangItem
, "panic", panic_fn
;
350 PanicBoundsCheckFnLangItem
, "panic_bounds_check", panic_bounds_check_fn
;
351 PanicFmtLangItem
, "panic_fmt", panic_fmt
;
353 ExchangeMallocFnLangItem
, "exchange_malloc", exchange_malloc_fn
;
354 ExchangeFreeFnLangItem
, "exchange_free", exchange_free_fn
;
355 BoxFreeFnLangItem
, "box_free", box_free_fn
;
356 StrDupUniqFnLangItem
, "strdup_uniq", strdup_uniq_fn
;
358 StartFnLangItem
, "start", start_fn
;
360 EhPersonalityLangItem
, "eh_personality", eh_personality
;
361 EhUnwindResumeLangItem
, "eh_unwind_resume", eh_unwind_resume
;
362 MSVCTryFilterLangItem
, "msvc_try_filter", msvc_try_filter
;
364 OwnedBoxLangItem
, "owned_box", owned_box
;
366 PhantomDataItem
, "phantom_data", phantom_data
;
369 CovariantTypeItem
, "covariant_type", covariant_type
;
370 ContravariantTypeItem
, "contravariant_type", contravariant_type
;
371 InvariantTypeItem
, "invariant_type", invariant_type
;
372 CovariantLifetimeItem
, "covariant_lifetime", covariant_lifetime
;
373 ContravariantLifetimeItem
, "contravariant_lifetime", contravariant_lifetime
;
374 InvariantLifetimeItem
, "invariant_lifetime", invariant_lifetime
;
376 NoCopyItem
, "no_copy_bound", no_copy_bound
;
378 NonZeroItem
, "non_zero", non_zero
;
380 DebugTraitLangItem
, "debug_trait", debug_trait
;