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
::def_id
::DefId
;
25 use ty
::{self, TyCtxt}
;
26 use middle
::weak_lang_items
;
27 use util
::nodemap
::FxHashMap
;
30 use syntax
::symbol
::Symbol
;
31 use hir
::itemlikevisit
::ItemLikeVisitor
;
34 // The actual lang items defined come at the end of this file in one handy table.
35 // So you probably just want to nip down to the end.
36 macro_rules
! language_item_table
{
38 $
( $variant
:ident
, $name
:expr
, $method
:ident
; )*
43 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
50 fn name(self) -> &'
static str {
52 $
( $variant
=> $name
, )*
57 pub struct LanguageItems
{
58 pub items
: Vec
<Option
<DefId
>>,
59 pub missing
: Vec
<LangItem
>,
63 pub fn new() -> LanguageItems
{
64 fn foo(_
: LangItem
) -> Option
<DefId
> { None }
67 items
: vec
![$
(foo($variant
)),*],
72 pub fn items(&self) -> &[Option
<DefId
>] {
76 pub fn require(&self, it
: LangItem
) -> Result
<DefId
, String
> {
77 self.items
[it
as usize].ok_or_else(|| format
!("requires `{}` lang_item", it
.name()))
80 pub fn fn_trait_kind(&self, id
: DefId
) -> Option
<ty
::ClosureKind
> {
82 x
if x
== self.fn_trait() => Some(ty
::ClosureKind
::Fn
),
83 x
if x
== self.fn_mut_trait() => Some(ty
::ClosureKind
::FnMut
),
84 x
if x
== self.fn_once_trait() => Some(ty
::ClosureKind
::FnOnce
),
91 pub fn $
method(&self) -> Option
<DefId
> {
92 self.items
[$variant
as usize]
97 struct LanguageItemCollector
<'a
, 'tcx
: 'a
> {
100 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
102 item_refs
: FxHashMap
<&'
static str, usize>,
105 impl<'a
, 'v
, 'tcx
> ItemLikeVisitor
<'v
> for LanguageItemCollector
<'a
, 'tcx
> {
106 fn visit_item(&mut self, item
: &hir
::Item
) {
107 if let Some(value
) = extract(&item
.attrs
) {
108 let item_index
= self.item_refs
.get(&*value
.as_str()).cloned();
110 if let Some(item_index
) = item_index
{
111 let def_id
= self.tcx
.hir
.local_def_id(item
.id
);
112 self.collect_item(item_index
, def_id
);
114 let span
= self.tcx
.hir
.span(item
.id
);
115 span_err
!(self.tcx
.sess
, span
, E0522
,
116 "definition of an unknown language item: `{}`.",
122 fn visit_trait_item(&mut self, _trait_item
: &hir
::TraitItem
) {
123 // at present, lang items are always items, not trait items
126 fn visit_impl_item(&mut self, _impl_item
: &hir
::ImplItem
) {
127 // at present, lang items are always items, not impl items
131 impl<'a
, 'tcx
> LanguageItemCollector
<'a
, 'tcx
> {
132 fn new(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) -> LanguageItemCollector
<'a
, 'tcx
> {
133 let mut item_refs
= FxHashMap();
135 $
( item_refs
.insert($name
, $variant
as usize); )*
137 LanguageItemCollector
{
139 items
: LanguageItems
::new(),
144 fn collect_item(&mut self, item_index
: usize, item_def_id
: DefId
) {
145 // Check for duplicates.
146 match self.items
.items
[item_index
] {
147 Some(original_def_id
) if original_def_id
!= item_def_id
=> {
148 let name
= LangItem
::from_u32(item_index
as u32).unwrap().name();
149 let mut err
= match self.tcx
.hir
.span_if_local(item_def_id
) {
150 Some(span
) => struct_span_err
!(
154 "duplicate lang item found: `{}`.",
156 None
=> self.tcx
.sess
.struct_err(&format
!(
157 "duplicate lang item in crate `{}`: `{}`.",
158 self.tcx
.crate_name(item_def_id
.krate
),
161 if let Some(span
) = self.tcx
.hir
.span_if_local(original_def_id
) {
162 span_note
!(&mut err
, span
,
163 "first defined here.");
165 err
.note(&format
!("first defined in crate `{}`.",
166 self.tcx
.crate_name(original_def_id
.krate
)));
176 self.items
.items
[item_index
] = Some(item_def_id
);
180 pub fn extract(attrs
: &[ast
::Attribute
]) -> Option
<Symbol
> {
181 for attribute
in attrs
{
182 if attribute
.check_name("lang") {
183 if let Some(value
) = attribute
.value_str() {
192 pub fn collect
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) -> LanguageItems
{
193 let mut collector
= LanguageItemCollector
::new(tcx
);
194 for &cnum
in tcx
.crates().iter() {
195 for &(def_id
, item_index
) in tcx
.defined_lang_items(cnum
).iter() {
196 collector
.collect_item(item_index
, def_id
);
199 tcx
.hir
.krate().visit_all_item_likes(&mut collector
);
200 let LanguageItemCollector { mut items, .. }
= collector
;
201 weak_lang_items
::check_crate(tcx
, &mut items
);
209 language_item_table
! {
210 // Variant name, Name, Method name;
211 CharImplItem
, "char", char_impl
;
212 StrImplItem
, "str", str_impl
;
213 SliceImplItem
, "slice", slice_impl
;
214 SliceU8ImplItem
, "slice_u8", slice_u8_impl
;
215 ConstPtrImplItem
, "const_ptr", const_ptr_impl
;
216 MutPtrImplItem
, "mut_ptr", mut_ptr_impl
;
217 I8ImplItem
, "i8", i8_impl
;
218 I16ImplItem
, "i16", i16_impl
;
219 I32ImplItem
, "i32", i32_impl
;
220 I64ImplItem
, "i64", i64_impl
;
221 I128ImplItem
, "i128", i128_impl
;
222 IsizeImplItem
, "isize", isize_impl
;
223 U8ImplItem
, "u8", u8_impl
;
224 U16ImplItem
, "u16", u16_impl
;
225 U32ImplItem
, "u32", u32_impl
;
226 U64ImplItem
, "u64", u64_impl
;
227 U128ImplItem
, "u128", u128_impl
;
228 UsizeImplItem
, "usize", usize_impl
;
229 F32ImplItem
, "f32", f32_impl
;
230 F64ImplItem
, "f64", f64_impl
;
232 SizedTraitLangItem
, "sized", sized_trait
;
233 UnsizeTraitLangItem
, "unsize", unsize_trait
;
234 CopyTraitLangItem
, "copy", copy_trait
;
235 CloneTraitLangItem
, "clone", clone_trait
;
236 SyncTraitLangItem
, "sync", sync_trait
;
237 FreezeTraitLangItem
, "freeze", freeze_trait
;
239 DropTraitLangItem
, "drop", drop_trait
;
241 CoerceUnsizedTraitLangItem
, "coerce_unsized", coerce_unsized_trait
;
243 AddTraitLangItem
, "add", add_trait
;
244 SubTraitLangItem
, "sub", sub_trait
;
245 MulTraitLangItem
, "mul", mul_trait
;
246 DivTraitLangItem
, "div", div_trait
;
247 RemTraitLangItem
, "rem", rem_trait
;
248 NegTraitLangItem
, "neg", neg_trait
;
249 NotTraitLangItem
, "not", not_trait
;
250 BitXorTraitLangItem
, "bitxor", bitxor_trait
;
251 BitAndTraitLangItem
, "bitand", bitand_trait
;
252 BitOrTraitLangItem
, "bitor", bitor_trait
;
253 ShlTraitLangItem
, "shl", shl_trait
;
254 ShrTraitLangItem
, "shr", shr_trait
;
255 AddAssignTraitLangItem
, "add_assign", add_assign_trait
;
256 SubAssignTraitLangItem
, "sub_assign", sub_assign_trait
;
257 MulAssignTraitLangItem
, "mul_assign", mul_assign_trait
;
258 DivAssignTraitLangItem
, "div_assign", div_assign_trait
;
259 RemAssignTraitLangItem
, "rem_assign", rem_assign_trait
;
260 BitXorAssignTraitLangItem
, "bitxor_assign", bitxor_assign_trait
;
261 BitAndAssignTraitLangItem
, "bitand_assign", bitand_assign_trait
;
262 BitOrAssignTraitLangItem
, "bitor_assign", bitor_assign_trait
;
263 ShlAssignTraitLangItem
, "shl_assign", shl_assign_trait
;
264 ShrAssignTraitLangItem
, "shr_assign", shr_assign_trait
;
265 IndexTraitLangItem
, "index", index_trait
;
266 IndexMutTraitLangItem
, "index_mut", index_mut_trait
;
268 UnsafeCellTypeLangItem
, "unsafe_cell", unsafe_cell_type
;
270 DerefTraitLangItem
, "deref", deref_trait
;
271 DerefMutTraitLangItem
, "deref_mut", deref_mut_trait
;
273 FnTraitLangItem
, "fn", fn_trait
;
274 FnMutTraitLangItem
, "fn_mut", fn_mut_trait
;
275 FnOnceTraitLangItem
, "fn_once", fn_once_trait
;
277 GeneratorStateLangItem
, "generator_state", gen_state
;
278 GeneratorTraitLangItem
, "generator", gen_trait
;
280 EqTraitLangItem
, "eq", eq_trait
;
281 OrdTraitLangItem
, "ord", ord_trait
;
283 // A number of panic-related lang items. The `panic` item corresponds to
284 // divide-by-zero and various panic cases with `match`. The
285 // `panic_bounds_check` item is for indexing arrays.
287 // The `begin_unwind` lang item has a predefined symbol name and is sort of
288 // a "weak lang item" in the sense that a crate is not required to have it
289 // defined to use it, but a final product is required to define it
290 // somewhere. Additionally, there are restrictions on crates that use a weak
291 // lang item, but do not have it defined.
292 PanicFnLangItem
, "panic", panic_fn
;
293 PanicBoundsCheckFnLangItem
, "panic_bounds_check", panic_bounds_check_fn
;
294 PanicFmtLangItem
, "panic_fmt", panic_fmt
;
296 ExchangeMallocFnLangItem
, "exchange_malloc", exchange_malloc_fn
;
297 BoxFreeFnLangItem
, "box_free", box_free_fn
;
298 DropInPlaceFnLangItem
, "drop_in_place", drop_in_place_fn
;
300 StartFnLangItem
, "start", start_fn
;
302 EhPersonalityLangItem
, "eh_personality", eh_personality
;
303 EhUnwindResumeLangItem
, "eh_unwind_resume", eh_unwind_resume
;
304 MSVCTryFilterLangItem
, "msvc_try_filter", msvc_try_filter
;
306 OwnedBoxLangItem
, "owned_box", owned_box
;
308 PhantomDataItem
, "phantom_data", phantom_data
;
310 NonZeroItem
, "non_zero", non_zero
;
312 DebugTraitLangItem
, "debug_trait", debug_trait
;
314 // A lang item for each of the 128-bit operators we can optionally lower.
315 I128AddFnLangItem
, "i128_add", i128_add_fn
;
316 U128AddFnLangItem
, "u128_add", u128_add_fn
;
317 I128SubFnLangItem
, "i128_sub", i128_sub_fn
;
318 U128SubFnLangItem
, "u128_sub", u128_sub_fn
;
319 I128MulFnLangItem
, "i128_mul", i128_mul_fn
;
320 U128MulFnLangItem
, "u128_mul", u128_mul_fn
;
321 I128DivFnLangItem
, "i128_div", i128_div_fn
;
322 U128DivFnLangItem
, "u128_div", u128_div_fn
;
323 I128RemFnLangItem
, "i128_rem", i128_rem_fn
;
324 U128RemFnLangItem
, "u128_rem", u128_rem_fn
;
325 I128ShlFnLangItem
, "i128_shl", i128_shl_fn
;
326 U128ShlFnLangItem
, "u128_shl", u128_shl_fn
;
327 I128ShrFnLangItem
, "i128_shr", i128_shr_fn
;
328 U128ShrFnLangItem
, "u128_shr", u128_shr_fn
;
329 // And overflow versions for the operators that are checkable.
330 // While MIR calls these Checked*, they return (T,bool), not Option<T>.
331 I128AddoFnLangItem
, "i128_addo", i128_addo_fn
;
332 U128AddoFnLangItem
, "u128_addo", u128_addo_fn
;
333 I128SuboFnLangItem
, "i128_subo", i128_subo_fn
;
334 U128SuboFnLangItem
, "u128_subo", u128_subo_fn
;
335 I128MuloFnLangItem
, "i128_mulo", i128_mulo_fn
;
336 U128MuloFnLangItem
, "u128_mulo", u128_mulo_fn
;
337 I128ShloFnLangItem
, "i128_shlo", i128_shlo_fn
;
338 U128ShloFnLangItem
, "u128_shlo", u128_shlo_fn
;
339 I128ShroFnLangItem
, "i128_shro", i128_shro_fn
;
340 U128ShroFnLangItem
, "u128_shro", u128_shro_fn
;
342 TerminationTraitLangItem
, "termination", termination
;
345 impl<'a
, 'tcx
, 'gcx
> TyCtxt
<'a
, 'tcx
, 'gcx
> {
346 pub fn require_lang_item(&self, lang_item
: LangItem
) -> DefId
{
347 self.lang_items().require(lang_item
).unwrap_or_else(|msg
| {
348 self.sess
.fatal(&msg
)