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 hir
::map
as hir_map
;
26 use hir
::def_id
::DefId
;
28 use middle
::weak_lang_items
;
29 use util
::nodemap
::FxHashMap
;
32 use syntax
::symbol
::Symbol
;
33 use hir
::itemlikevisit
::ItemLikeVisitor
;
36 // The actual lang items defined come at the end of this file in one handy table.
37 // So you probably just want to nip down to the end.
38 macro_rules
! language_item_table
{
40 $
( $variant
:ident
, $name
:expr
, $method
:ident
; )*
45 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
51 pub struct LanguageItems
{
52 pub items
: Vec
<Option
<DefId
>>,
53 pub missing
: Vec
<LangItem
>,
57 pub fn new() -> LanguageItems
{
58 fn foo(_
: LangItem
) -> Option
<DefId
> { None }
61 items
: vec
![$
(foo($variant
)),*],
66 pub fn items(&self) -> &[Option
<DefId
>] {
70 pub fn item_name(index
: usize) -> &'
static str {
71 let item
: Option
<LangItem
> = LangItem
::from_u32(index
as u32);
73 $
( Some($variant
) => $name
, )*
78 pub fn require(&self, it
: LangItem
) -> Result
<DefId
, String
> {
79 match self.items
[it
as usize] {
82 Err(format
!("requires `{}` lang_item",
83 LanguageItems
::item_name(it
as usize)))
88 pub fn require_owned_box(&self) -> Result
<DefId
, String
> {
89 self.require(OwnedBoxLangItem
)
92 pub fn fn_trait_kind(&self, id
: DefId
) -> Option
<ty
::ClosureKind
> {
94 (self.fn_trait(), ty
::ClosureKind
::Fn
),
95 (self.fn_mut_trait(), ty
::ClosureKind
::FnMut
),
96 (self.fn_once_trait(), ty
::ClosureKind
::FnOnce
),
99 for &(opt_def_id
, kind
) in &def_id_kinds
{
100 if Some(id
) == opt_def_id
{
110 pub fn $
method(&self) -> Option
<DefId
> {
111 self.items
[$variant
as usize]
116 struct LanguageItemCollector
<'a
, 'tcx
: 'a
> {
117 items
: LanguageItems
,
119 hir_map
: &'a hir_map
::Map
<'tcx
>,
121 session
: &'a Session
,
123 item_refs
: FxHashMap
<&'
static str, usize>,
126 impl<'a
, 'v
, 'tcx
> ItemLikeVisitor
<'v
> for LanguageItemCollector
<'a
, 'tcx
> {
127 fn visit_item(&mut self, item
: &hir
::Item
) {
128 if let Some(value
) = extract(&item
.attrs
) {
129 let item_index
= self.item_refs
.get(&*value
.as_str()).cloned();
131 if let Some(item_index
) = item_index
{
132 self.collect_item(item_index
, self.hir_map
.local_def_id(item
.id
))
134 let span
= self.hir_map
.span(item
.id
);
135 span_err
!(self.session
, span
, E0522
,
136 "definition of an unknown language item: `{}`.",
142 fn visit_trait_item(&mut self, _trait_item
: &hir
::TraitItem
) {
143 // at present, lang items are always items, not trait items
146 fn visit_impl_item(&mut self, _impl_item
: &hir
::ImplItem
) {
147 // at present, lang items are always items, not impl items
151 impl<'a
, 'tcx
> LanguageItemCollector
<'a
, 'tcx
> {
152 pub fn new(session
: &'a Session
, hir_map
: &'a hir_map
::Map
<'tcx
>)
153 -> LanguageItemCollector
<'a
, 'tcx
> {
154 let mut item_refs
= FxHashMap();
156 $
( item_refs
.insert($name
, $variant
as usize); )*
158 LanguageItemCollector
{
161 items
: LanguageItems
::new(),
162 item_refs
: item_refs
,
166 pub fn collect_item(&mut self, item_index
: usize,
167 item_def_id
: DefId
) {
168 // Check for duplicates.
169 match self.items
.items
[item_index
] {
170 Some(original_def_id
) if original_def_id
!= item_def_id
=> {
171 let cstore
= &self.session
.cstore
;
172 let name
= LanguageItems
::item_name(item_index
);
173 let mut err
= match self.hir_map
.span_if_local(item_def_id
) {
174 Some(span
) => struct_span_err
!(
178 "duplicate lang item found: `{}`.",
180 None
=> self.session
.struct_err(&format
!(
181 "duplicate lang item in crate `{}`: `{}`.",
182 cstore
.crate_name(item_def_id
.krate
),
185 if let Some(span
) = self.hir_map
.span_if_local(original_def_id
) {
186 span_note
!(&mut err
, span
,
187 "first defined here.");
189 err
.note(&format
!("first defined in crate `{}`.",
190 cstore
.crate_name(original_def_id
.krate
)));
200 self.items
.items
[item_index
] = Some(item_def_id
);
203 pub fn collect_local_language_items(&mut self, krate
: &hir
::Crate
) {
204 krate
.visit_all_item_likes(self);
207 pub fn collect_external_language_items(&mut self) {
208 let cstore
= &self.session
.cstore
;
210 for cnum
in cstore
.crates() {
211 for (index
, item_index
) in cstore
.lang_items(cnum
) {
212 let def_id
= DefId { krate: cnum, index: index }
;
213 self.collect_item(item_index
, def_id
);
218 pub fn collect(&mut self, krate
: &hir
::Crate
) {
219 self.collect_external_language_items();
220 self.collect_local_language_items(krate
);
224 pub fn extract(attrs
: &[ast
::Attribute
]) -> Option
<Symbol
> {
225 for attribute
in attrs
{
226 if attribute
.check_name("lang") {
227 if let Some(value
) = attribute
.value_str() {
236 pub fn collect_language_items(session
: &Session
,
239 let krate
: &hir
::Crate
= map
.krate();
240 let mut collector
= LanguageItemCollector
::new(session
, map
);
241 collector
.collect(krate
);
242 let LanguageItemCollector { mut items, .. }
= collector
;
243 weak_lang_items
::check_crate(krate
, session
, &mut items
);
251 language_item_table
! {
252 // Variant name, Name, Method name;
253 CharImplItem
, "char", char_impl
;
254 StrImplItem
, "str", str_impl
;
255 SliceImplItem
, "slice", slice_impl
;
256 ConstPtrImplItem
, "const_ptr", const_ptr_impl
;
257 MutPtrImplItem
, "mut_ptr", mut_ptr_impl
;
258 I8ImplItem
, "i8", i8_impl
;
259 I16ImplItem
, "i16", i16_impl
;
260 I32ImplItem
, "i32", i32_impl
;
261 I64ImplItem
, "i64", i64_impl
;
262 I128ImplItem
, "i128", i128_impl
;
263 IsizeImplItem
, "isize", isize_impl
;
264 U8ImplItem
, "u8", u8_impl
;
265 U16ImplItem
, "u16", u16_impl
;
266 U32ImplItem
, "u32", u32_impl
;
267 U64ImplItem
, "u64", u64_impl
;
268 U128ImplItem
, "u128", u128_impl
;
269 UsizeImplItem
, "usize", usize_impl
;
270 F32ImplItem
, "f32", f32_impl
;
271 F64ImplItem
, "f64", f64_impl
;
273 SendTraitLangItem
, "send", send_trait
;
274 SizedTraitLangItem
, "sized", sized_trait
;
275 UnsizeTraitLangItem
, "unsize", unsize_trait
;
276 CopyTraitLangItem
, "copy", copy_trait
;
277 SyncTraitLangItem
, "sync", sync_trait
;
278 FreezeTraitLangItem
, "freeze", freeze_trait
;
280 DropTraitLangItem
, "drop", drop_trait
;
282 CoerceUnsizedTraitLangItem
, "coerce_unsized", coerce_unsized_trait
;
284 AddTraitLangItem
, "add", add_trait
;
285 SubTraitLangItem
, "sub", sub_trait
;
286 MulTraitLangItem
, "mul", mul_trait
;
287 DivTraitLangItem
, "div", div_trait
;
288 RemTraitLangItem
, "rem", rem_trait
;
289 NegTraitLangItem
, "neg", neg_trait
;
290 NotTraitLangItem
, "not", not_trait
;
291 BitXorTraitLangItem
, "bitxor", bitxor_trait
;
292 BitAndTraitLangItem
, "bitand", bitand_trait
;
293 BitOrTraitLangItem
, "bitor", bitor_trait
;
294 ShlTraitLangItem
, "shl", shl_trait
;
295 ShrTraitLangItem
, "shr", shr_trait
;
296 AddAssignTraitLangItem
, "add_assign", add_assign_trait
;
297 SubAssignTraitLangItem
, "sub_assign", sub_assign_trait
;
298 MulAssignTraitLangItem
, "mul_assign", mul_assign_trait
;
299 DivAssignTraitLangItem
, "div_assign", div_assign_trait
;
300 RemAssignTraitLangItem
, "rem_assign", rem_assign_trait
;
301 BitXorAssignTraitLangItem
, "bitxor_assign", bitxor_assign_trait
;
302 BitAndAssignTraitLangItem
, "bitand_assign", bitand_assign_trait
;
303 BitOrAssignTraitLangItem
, "bitor_assign", bitor_assign_trait
;
304 ShlAssignTraitLangItem
, "shl_assign", shl_assign_trait
;
305 ShrAssignTraitLangItem
, "shr_assign", shr_assign_trait
;
306 IndexTraitLangItem
, "index", index_trait
;
307 IndexMutTraitLangItem
, "index_mut", index_mut_trait
;
309 UnsafeCellTypeLangItem
, "unsafe_cell", unsafe_cell_type
;
311 DerefTraitLangItem
, "deref", deref_trait
;
312 DerefMutTraitLangItem
, "deref_mut", deref_mut_trait
;
314 FnTraitLangItem
, "fn", fn_trait
;
315 FnMutTraitLangItem
, "fn_mut", fn_mut_trait
;
316 FnOnceTraitLangItem
, "fn_once", fn_once_trait
;
318 EqTraitLangItem
, "eq", eq_trait
;
319 OrdTraitLangItem
, "ord", ord_trait
;
321 StrEqFnLangItem
, "str_eq", str_eq_fn
;
323 // A number of panic-related lang items. The `panic` item corresponds to
324 // divide-by-zero and various panic cases with `match`. The
325 // `panic_bounds_check` item is for indexing arrays.
327 // The `begin_unwind` lang item has a predefined symbol name and is sort of
328 // a "weak lang item" in the sense that a crate is not required to have it
329 // defined to use it, but a final product is required to define it
330 // somewhere. Additionally, there are restrictions on crates that use a weak
331 // lang item, but do not have it defined.
332 PanicFnLangItem
, "panic", panic_fn
;
333 PanicBoundsCheckFnLangItem
, "panic_bounds_check", panic_bounds_check_fn
;
334 PanicFmtLangItem
, "panic_fmt", panic_fmt
;
336 ExchangeMallocFnLangItem
, "exchange_malloc", exchange_malloc_fn
;
337 BoxFreeFnLangItem
, "box_free", box_free_fn
;
338 DropInPlaceFnLangItem
, "drop_in_place", drop_in_place_fn
;
340 StartFnLangItem
, "start", start_fn
;
342 EhPersonalityLangItem
, "eh_personality", eh_personality
;
343 EhUnwindResumeLangItem
, "eh_unwind_resume", eh_unwind_resume
;
344 MSVCTryFilterLangItem
, "msvc_try_filter", msvc_try_filter
;
346 OwnedBoxLangItem
, "owned_box", owned_box
;
348 PhantomDataItem
, "phantom_data", phantom_data
;
351 CovariantTypeItem
, "covariant_type", covariant_type
;
352 ContravariantTypeItem
, "contravariant_type", contravariant_type
;
353 InvariantTypeItem
, "invariant_type", invariant_type
;
354 CovariantLifetimeItem
, "covariant_lifetime", covariant_lifetime
;
355 ContravariantLifetimeItem
, "contravariant_lifetime", contravariant_lifetime
;
356 InvariantLifetimeItem
, "invariant_lifetime", invariant_lifetime
;
358 NonZeroItem
, "non_zero", non_zero
;
360 DebugTraitLangItem
, "debug_trait", debug_trait
;
363 impl<'a
, 'tcx
, 'gcx
> ty
::TyCtxt
<'a
, 'tcx
, 'gcx
> {
364 pub fn require_lang_item(&self, lang_item
: LangItem
) -> DefId
{
365 self.lang_items
.require(lang_item
).unwrap_or_else(|msg
| {
366 self.sess
.fatal(&msg
)