1 // Detecting language items.
3 // Language items are items that represent concepts intrinsic to the language
4 // itself. Examples are:
6 // * Traits that specify "kinds"; e.g., "Sync", "Send".
8 // * Traits that represent operators; e.g., "Add", "Sub", "Index".
10 // * Functions called by the compiler itself.
12 pub use self::LangItem
::*;
14 use crate::hir
::def_id
::DefId
;
15 use crate::hir
::check_attr
::Target
;
16 use crate::ty
::{self, TyCtxt}
;
17 use crate::middle
::weak_lang_items
;
18 use crate::util
::nodemap
::FxHashMap
;
21 use syntax
::symbol
::Symbol
;
23 use rustc_macros
::HashStable
;
24 use crate::hir
::itemlikevisit
::ItemLikeVisitor
;
27 // The actual lang items defined come at the end of this file in one handy table.
28 // So you probably just want to nip down to the end.
29 macro_rules
! language_item_table
{
31 $
( $variant
:ident
, $name
:expr
, $method
:ident
, $target
:path
; )*
35 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
42 fn name(self) -> &'
static str {
44 $
( $variant
=> $name
, )*
50 pub struct LanguageItems
{
51 pub items
: Vec
<Option
<DefId
>>,
52 pub missing
: Vec
<LangItem
>,
56 pub fn new() -> LanguageItems
{
57 fn foo(_
: LangItem
) -> Option
<DefId
> { None }
60 items
: vec
![$
(foo($variant
)),*],
65 pub fn items(&self) -> &[Option
<DefId
>] {
69 pub fn require(&self, it
: LangItem
) -> Result
<DefId
, String
> {
70 self.items
[it
as usize].ok_or_else(|| format
!("requires `{}` lang_item", it
.name()))
73 pub fn fn_trait_kind(&self, id
: DefId
) -> Option
<ty
::ClosureKind
> {
75 x
if x
== self.fn_trait() => Some(ty
::ClosureKind
::Fn
),
76 x
if x
== self.fn_mut_trait() => Some(ty
::ClosureKind
::FnMut
),
77 x
if x
== self.fn_once_trait() => Some(ty
::ClosureKind
::FnOnce
),
84 pub fn $
method(&self) -> Option
<DefId
> {
85 self.items
[$variant
as usize]
90 struct LanguageItemCollector
<'a
, 'tcx
: 'a
> {
92 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
93 item_refs
: FxHashMap
<&'
static str, (usize, Target
)>,
96 impl<'a
, 'v
, 'tcx
> ItemLikeVisitor
<'v
> for LanguageItemCollector
<'a
, 'tcx
> {
97 fn visit_item(&mut self, item
: &hir
::Item
) {
98 if let Some((value
, span
)) = extract(&item
.attrs
) {
99 let actual_target
= Target
::from_item(item
);
100 match self.item_refs
.get(&*value
.as_str()).cloned() {
101 // Known lang item with attribute on correct target.
102 Some((item_index
, expected_target
)) if actual_target
== expected_target
=> {
103 let def_id
= self.tcx
.hir().local_def_id_from_hir_id(item
.hir_id
);
104 self.collect_item(item_index
, def_id
);
106 // Known lang item with attribute on incorrect target.
107 Some((_
, expected_target
)) => {
108 let mut err
= struct_span_err
!(
109 self.tcx
.sess
, span
, E0718
,
110 "`{}` language item must be applied to a {}",
111 value
, expected_target
,
116 "attribute should be applied to a {}, not a {}",
117 expected_target
, actual_target
,
122 // Unknown lang item.
124 let mut err
= struct_span_err
!(
125 self.tcx
.sess
, span
, E0522
,
126 "definition of an unknown language item: `{}`",
131 format
!("definition of unknown language item `{}`", value
)
139 fn visit_trait_item(&mut self, _trait_item
: &hir
::TraitItem
) {
140 // at present, lang items are always items, not trait items
143 fn visit_impl_item(&mut self, _impl_item
: &hir
::ImplItem
) {
144 // at present, lang items are always items, not impl items
148 impl<'a
, 'tcx
> LanguageItemCollector
<'a
, 'tcx
> {
149 fn new(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) -> LanguageItemCollector
<'a
, 'tcx
> {
150 let mut item_refs
= FxHashMap
::default();
152 $
( item_refs
.insert($name
, ($variant
as usize, $target
)); )*
154 LanguageItemCollector
{
156 items
: LanguageItems
::new(),
161 fn collect_item(&mut self, item_index
: usize, item_def_id
: DefId
) {
162 // Check for duplicates.
163 if let Some(original_def_id
) = self.items
.items
[item_index
] {
164 if original_def_id
!= item_def_id
{
165 let name
= LangItem
::from_u32(item_index
as u32).unwrap().name();
166 let mut err
= match self.tcx
.hir().span_if_local(item_def_id
) {
167 Some(span
) => struct_span_err
!(
171 "duplicate lang item found: `{}`.",
173 None
=> self.tcx
.sess
.struct_err(&format
!(
174 "duplicate lang item in crate `{}`: `{}`.",
175 self.tcx
.crate_name(item_def_id
.krate
),
178 if let Some(span
) = self.tcx
.hir().span_if_local(original_def_id
) {
179 span_note
!(&mut err
, span
, "first defined here.");
181 err
.note(&format
!("first defined in crate `{}`.",
182 self.tcx
.crate_name(original_def_id
.krate
)));
189 self.items
.items
[item_index
] = Some(item_def_id
);
193 pub fn extract(attrs
: &[ast
::Attribute
]) -> Option
<(Symbol
, Span
)> {
194 for attribute
in attrs
{
195 if attribute
.check_name("lang") {
196 if let Some(value
) = attribute
.value_str() {
197 return Some((value
, attribute
.span
));
199 } else if attribute
.check_name("panic_handler") {
200 return Some((Symbol
::intern("panic_impl"), attribute
.span
))
201 } else if attribute
.check_name("alloc_error_handler") {
202 return Some((Symbol
::intern("oom"), attribute
.span
))
209 pub fn collect
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) -> LanguageItems
{
210 let mut collector
= LanguageItemCollector
::new(tcx
);
211 for &cnum
in tcx
.crates().iter() {
212 for &(def_id
, item_index
) in tcx
.defined_lang_items(cnum
).iter() {
213 collector
.collect_item(item_index
, def_id
);
216 tcx
.hir().krate().visit_all_item_likes(&mut collector
);
217 let LanguageItemCollector { mut items, .. }
= collector
;
218 weak_lang_items
::check_crate(tcx
, &mut items
);
226 language_item_table
! {
227 // Variant name, Name, Method name, Target;
228 CharImplItem
, "char", char_impl
, Target
::Impl
;
229 StrImplItem
, "str", str_impl
, Target
::Impl
;
230 SliceImplItem
, "slice", slice_impl
, Target
::Impl
;
231 SliceU8ImplItem
, "slice_u8", slice_u8_impl
, Target
::Impl
;
232 StrAllocImplItem
, "str_alloc", str_alloc_impl
, Target
::Impl
;
233 SliceAllocImplItem
, "slice_alloc", slice_alloc_impl
, Target
::Impl
;
234 SliceU8AllocImplItem
, "slice_u8_alloc", slice_u8_alloc_impl
, Target
::Impl
;
235 ConstPtrImplItem
, "const_ptr", const_ptr_impl
, Target
::Impl
;
236 MutPtrImplItem
, "mut_ptr", mut_ptr_impl
, Target
::Impl
;
237 I8ImplItem
, "i8", i8_impl
, Target
::Impl
;
238 I16ImplItem
, "i16", i16_impl
, Target
::Impl
;
239 I32ImplItem
, "i32", i32_impl
, Target
::Impl
;
240 I64ImplItem
, "i64", i64_impl
, Target
::Impl
;
241 I128ImplItem
, "i128", i128_impl
, Target
::Impl
;
242 IsizeImplItem
, "isize", isize_impl
, Target
::Impl
;
243 U8ImplItem
, "u8", u8_impl
, Target
::Impl
;
244 U16ImplItem
, "u16", u16_impl
, Target
::Impl
;
245 U32ImplItem
, "u32", u32_impl
, Target
::Impl
;
246 U64ImplItem
, "u64", u64_impl
, Target
::Impl
;
247 U128ImplItem
, "u128", u128_impl
, Target
::Impl
;
248 UsizeImplItem
, "usize", usize_impl
, Target
::Impl
;
249 F32ImplItem
, "f32", f32_impl
, Target
::Impl
;
250 F64ImplItem
, "f64", f64_impl
, Target
::Impl
;
251 F32RuntimeImplItem
, "f32_runtime", f32_runtime_impl
, Target
::Impl
;
252 F64RuntimeImplItem
, "f64_runtime", f64_runtime_impl
, Target
::Impl
;
254 SizedTraitLangItem
, "sized", sized_trait
, Target
::Trait
;
255 UnsizeTraitLangItem
, "unsize", unsize_trait
, Target
::Trait
;
256 CopyTraitLangItem
, "copy", copy_trait
, Target
::Trait
;
257 CloneTraitLangItem
, "clone", clone_trait
, Target
::Trait
;
258 SyncTraitLangItem
, "sync", sync_trait
, Target
::Trait
;
259 FreezeTraitLangItem
, "freeze", freeze_trait
, Target
::Trait
;
261 DropTraitLangItem
, "drop", drop_trait
, Target
::Trait
;
263 CoerceUnsizedTraitLangItem
, "coerce_unsized", coerce_unsized_trait
, Target
::Trait
;
264 DispatchFromDynTraitLangItem
,"dispatch_from_dyn", dispatch_from_dyn_trait
, Target
::Trait
;
266 AddTraitLangItem
, "add", add_trait
, Target
::Trait
;
267 SubTraitLangItem
, "sub", sub_trait
, Target
::Trait
;
268 MulTraitLangItem
, "mul", mul_trait
, Target
::Trait
;
269 DivTraitLangItem
, "div", div_trait
, Target
::Trait
;
270 RemTraitLangItem
, "rem", rem_trait
, Target
::Trait
;
271 NegTraitLangItem
, "neg", neg_trait
, Target
::Trait
;
272 NotTraitLangItem
, "not", not_trait
, Target
::Trait
;
273 BitXorTraitLangItem
, "bitxor", bitxor_trait
, Target
::Trait
;
274 BitAndTraitLangItem
, "bitand", bitand_trait
, Target
::Trait
;
275 BitOrTraitLangItem
, "bitor", bitor_trait
, Target
::Trait
;
276 ShlTraitLangItem
, "shl", shl_trait
, Target
::Trait
;
277 ShrTraitLangItem
, "shr", shr_trait
, Target
::Trait
;
278 AddAssignTraitLangItem
, "add_assign", add_assign_trait
, Target
::Trait
;
279 SubAssignTraitLangItem
, "sub_assign", sub_assign_trait
, Target
::Trait
;
280 MulAssignTraitLangItem
, "mul_assign", mul_assign_trait
, Target
::Trait
;
281 DivAssignTraitLangItem
, "div_assign", div_assign_trait
, Target
::Trait
;
282 RemAssignTraitLangItem
, "rem_assign", rem_assign_trait
, Target
::Trait
;
283 BitXorAssignTraitLangItem
, "bitxor_assign", bitxor_assign_trait
, Target
::Trait
;
284 BitAndAssignTraitLangItem
, "bitand_assign", bitand_assign_trait
, Target
::Trait
;
285 BitOrAssignTraitLangItem
, "bitor_assign", bitor_assign_trait
, Target
::Trait
;
286 ShlAssignTraitLangItem
, "shl_assign", shl_assign_trait
, Target
::Trait
;
287 ShrAssignTraitLangItem
, "shr_assign", shr_assign_trait
, Target
::Trait
;
288 IndexTraitLangItem
, "index", index_trait
, Target
::Trait
;
289 IndexMutTraitLangItem
, "index_mut", index_mut_trait
, Target
::Trait
;
291 UnsafeCellTypeLangItem
, "unsafe_cell", unsafe_cell_type
, Target
::Struct
;
292 VaListTypeLangItem
, "va_list", va_list
, Target
::Struct
;
294 DerefTraitLangItem
, "deref", deref_trait
, Target
::Trait
;
295 DerefMutTraitLangItem
, "deref_mut", deref_mut_trait
, Target
::Trait
;
296 ReceiverTraitLangItem
, "receiver", receiver_trait
, Target
::Trait
;
298 FnTraitLangItem
, "fn", fn_trait
, Target
::Trait
;
299 FnMutTraitLangItem
, "fn_mut", fn_mut_trait
, Target
::Trait
;
300 FnOnceTraitLangItem
, "fn_once", fn_once_trait
, Target
::Trait
;
302 GeneratorStateLangItem
, "generator_state", gen_state
, Target
::Enum
;
303 GeneratorTraitLangItem
, "generator", gen_trait
, Target
::Trait
;
304 UnpinTraitLangItem
, "unpin", unpin_trait
, Target
::Trait
;
305 PinTypeLangItem
, "pin", pin_type
, Target
::Struct
;
307 EqTraitLangItem
, "eq", eq_trait
, Target
::Trait
;
308 PartialOrdTraitLangItem
, "partial_ord", partial_ord_trait
, Target
::Trait
;
309 OrdTraitLangItem
, "ord", ord_trait
, Target
::Trait
;
311 // A number of panic-related lang items. The `panic` item corresponds to
312 // divide-by-zero and various panic cases with `match`. The
313 // `panic_bounds_check` item is for indexing arrays.
315 // The `begin_unwind` lang item has a predefined symbol name and is sort of
316 // a "weak lang item" in the sense that a crate is not required to have it
317 // defined to use it, but a final product is required to define it
318 // somewhere. Additionally, there are restrictions on crates that use a weak
319 // lang item, but do not have it defined.
320 PanicFnLangItem
, "panic", panic_fn
, Target
::Fn
;
321 PanicBoundsCheckFnLangItem
, "panic_bounds_check", panic_bounds_check_fn
, Target
::Fn
;
322 PanicInfoLangItem
, "panic_info", panic_info
, Target
::Struct
;
323 PanicImplLangItem
, "panic_impl", panic_impl
, Target
::Fn
;
324 // Libstd panic entry point. Necessary for const eval to be able to catch it
325 BeginPanicFnLangItem
, "begin_panic", begin_panic_fn
, Target
::Fn
;
327 ExchangeMallocFnLangItem
, "exchange_malloc", exchange_malloc_fn
, Target
::Fn
;
328 BoxFreeFnLangItem
, "box_free", box_free_fn
, Target
::Fn
;
329 DropInPlaceFnLangItem
, "drop_in_place", drop_in_place_fn
, Target
::Fn
;
330 OomLangItem
, "oom", oom
, Target
::Fn
;
331 AllocLayoutLangItem
, "alloc_layout", alloc_layout
, Target
::Struct
;
333 StartFnLangItem
, "start", start_fn
, Target
::Fn
;
335 EhPersonalityLangItem
, "eh_personality", eh_personality
, Target
::Fn
;
336 EhUnwindResumeLangItem
, "eh_unwind_resume", eh_unwind_resume
, Target
::Fn
;
337 MSVCTryFilterLangItem
, "msvc_try_filter", msvc_try_filter
, Target
::Static
;
339 OwnedBoxLangItem
, "owned_box", owned_box
, Target
::Struct
;
341 PhantomDataItem
, "phantom_data", phantom_data
, Target
::Struct
;
343 ManuallyDropItem
, "manually_drop", manually_drop
, Target
::Struct
;
345 DebugTraitLangItem
, "debug_trait", debug_trait
, Target
::Trait
;
347 // A lang item for each of the 128-bit operators we can optionally lower.
348 I128AddFnLangItem
, "i128_add", i128_add_fn
, Target
::Fn
;
349 U128AddFnLangItem
, "u128_add", u128_add_fn
, Target
::Fn
;
350 I128SubFnLangItem
, "i128_sub", i128_sub_fn
, Target
::Fn
;
351 U128SubFnLangItem
, "u128_sub", u128_sub_fn
, Target
::Fn
;
352 I128MulFnLangItem
, "i128_mul", i128_mul_fn
, Target
::Fn
;
353 U128MulFnLangItem
, "u128_mul", u128_mul_fn
, Target
::Fn
;
354 I128DivFnLangItem
, "i128_div", i128_div_fn
, Target
::Fn
;
355 U128DivFnLangItem
, "u128_div", u128_div_fn
, Target
::Fn
;
356 I128RemFnLangItem
, "i128_rem", i128_rem_fn
, Target
::Fn
;
357 U128RemFnLangItem
, "u128_rem", u128_rem_fn
, Target
::Fn
;
358 I128ShlFnLangItem
, "i128_shl", i128_shl_fn
, Target
::Fn
;
359 U128ShlFnLangItem
, "u128_shl", u128_shl_fn
, Target
::Fn
;
360 I128ShrFnLangItem
, "i128_shr", i128_shr_fn
, Target
::Fn
;
361 U128ShrFnLangItem
, "u128_shr", u128_shr_fn
, Target
::Fn
;
362 // And overflow versions for the operators that are checkable.
363 // While MIR calls these Checked*, they return (T,bool), not Option<T>.
364 I128AddoFnLangItem
, "i128_addo", i128_addo_fn
, Target
::Fn
;
365 U128AddoFnLangItem
, "u128_addo", u128_addo_fn
, Target
::Fn
;
366 I128SuboFnLangItem
, "i128_subo", i128_subo_fn
, Target
::Fn
;
367 U128SuboFnLangItem
, "u128_subo", u128_subo_fn
, Target
::Fn
;
368 I128MuloFnLangItem
, "i128_mulo", i128_mulo_fn
, Target
::Fn
;
369 U128MuloFnLangItem
, "u128_mulo", u128_mulo_fn
, Target
::Fn
;
370 I128ShloFnLangItem
, "i128_shlo", i128_shlo_fn
, Target
::Fn
;
371 U128ShloFnLangItem
, "u128_shlo", u128_shlo_fn
, Target
::Fn
;
372 I128ShroFnLangItem
, "i128_shro", i128_shro_fn
, Target
::Fn
;
373 U128ShroFnLangItem
, "u128_shro", u128_shro_fn
, Target
::Fn
;
375 // Align offset for stride != 1, must not panic.
376 AlignOffsetLangItem
, "align_offset", align_offset_fn
, Target
::Fn
;
378 TerminationTraitLangItem
, "termination", termination
, Target
::Trait
;
380 Arc
, "arc", arc
, Target
::Struct
;
381 Rc
, "rc", rc
, Target
::Struct
;
384 impl<'a
, 'tcx
, 'gcx
> TyCtxt
<'a
, 'tcx
, 'gcx
> {
385 pub fn require_lang_item(&self, lang_item
: LangItem
) -> DefId
{
386 self.lang_items().require(lang_item
).unwrap_or_else(|msg
| {
387 self.sess
.fatal(&msg
)