]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/lang_items.rs
Update to use new librustc_error_codes library
[rust.git] / src / librustc / middle / lang_items.rs
1 //! Detecting language items.
2 //!
3 //! Language items are items that represent concepts intrinsic to the language
4 //! itself. Examples are:
5 //!
6 //! * Traits that specify "kinds"; e.g., `Sync`, `Send`.
7 //! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
8 //! * Functions called by the compiler itself.
9
10 pub use self::LangItem::*;
11
12 use crate::hir::def_id::DefId;
13 use crate::hir::check_attr::Target;
14 use crate::ty::{self, TyCtxt};
15 use crate::middle::weak_lang_items;
16 use crate::middle::cstore::ExternCrate;
17 use crate::util::nodemap::FxHashMap;
18
19 use syntax::ast;
20 use syntax::symbol::{Symbol, sym};
21 use syntax_pos::Span;
22 use rustc_macros::HashStable;
23 use crate::hir::itemlikevisit::ItemLikeVisitor;
24 use crate::hir;
25
26 use rustc_error_codes::*;
27
28 // The actual lang items defined come at the end of this file in one handy table.
29 // So you probably just want to nip down to the end.
30 macro_rules! language_item_table {
31     (
32         $( $variant:ident, $name:expr, $method:ident, $target:path; )*
33     ) => {
34
35 enum_from_u32! {
36     /// A representation of all the valid language items in Rust.
37     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
38     pub enum LangItem {
39         $($variant,)*
40     }
41 }
42
43 impl LangItem {
44     /// Returns the `name` in `#[lang = "$name"]`.
45     /// For example, `LangItem::EqTraitLangItem`,
46     /// that is `#[lang = "eq"]` would result in `"eq"`.
47     fn name(self) -> &'static str {
48         match self {
49             $( $variant => $name, )*
50         }
51     }
52 }
53
54 #[derive(HashStable)]
55 pub struct LanguageItems {
56     /// Mappings from lang items to their possibly found `DefId`s.
57     /// The index corresponds to the order in `LangItem`.
58     pub items: Vec<Option<DefId>>,
59     /// Lang items that were not found during collection.
60     pub missing: Vec<LangItem>,
61 }
62
63 impl LanguageItems {
64     /// Construct an empty collection of lang items and no missing ones.
65     pub fn new() -> Self {
66         fn init_none(_: LangItem) -> Option<DefId> { None }
67
68         Self {
69             items: vec![$(init_none($variant)),*],
70             missing: Vec::new(),
71         }
72     }
73
74     /// Returns the mappings to the possibly found `DefId`s for each lang item.
75     pub fn items(&self) -> &[Option<DefId>] {
76         &*self.items
77     }
78
79     /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
80     /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
81     /// returns an error message as a string.
82     pub fn require(&self, it: LangItem) -> Result<DefId, String> {
83         self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name()))
84     }
85
86     /// Returns the kind of closure that `id`, which is one of the `Fn*` traits, corresponds to.
87     /// If `id` is not one of the `Fn*` traits, `None` is returned.
88     pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
89         match Some(id) {
90             x if x == self.fn_trait() => Some(ty::ClosureKind::Fn),
91             x if x == self.fn_mut_trait() => Some(ty::ClosureKind::FnMut),
92             x if x == self.fn_once_trait() => Some(ty::ClosureKind::FnOnce),
93             _ => None
94         }
95     }
96
97     $(
98         /// Returns the corresponding `DefId` for the lang item
99         #[doc = $name]
100         /// if it exists.
101         #[allow(dead_code)]
102         pub fn $method(&self) -> Option<DefId> {
103             self.items[$variant as usize]
104         }
105     )*
106 }
107
108 struct LanguageItemCollector<'tcx> {
109     items: LanguageItems,
110     tcx: TyCtxt<'tcx>,
111     /// A mapping from the name of the lang item to its order and the form it must be of.
112     item_refs: FxHashMap<&'static str, (usize, Target)>,
113 }
114
115 impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
116     fn visit_item(&mut self, item: &hir::Item) {
117         if let Some((value, span)) = extract(&item.attrs) {
118             let actual_target = Target::from_item(item);
119             match self.item_refs.get(&*value.as_str()).cloned() {
120                 // Known lang item with attribute on correct target.
121                 Some((item_index, expected_target)) if actual_target == expected_target => {
122                     let def_id = self.tcx.hir().local_def_id(item.hir_id);
123                     self.collect_item(item_index, def_id);
124                 },
125                 // Known lang item with attribute on incorrect target.
126                 Some((_, expected_target)) => {
127                     struct_span_err!(
128                         self.tcx.sess, span, E0718,
129                         "`{}` language item must be applied to a {}",
130                         value, expected_target,
131                     ).span_label(
132                         span,
133                         format!(
134                             "attribute should be applied to a {}, not a {}",
135                             expected_target, actual_target,
136                         ),
137                     ).emit();
138                 },
139                 // Unknown lang item.
140                 _ => {
141                     struct_span_err!(
142                         self.tcx.sess, span, E0522,
143                         "definition of an unknown language item: `{}`",
144                         value
145                     ).span_label(
146                         span,
147                         format!("definition of unknown language item `{}`", value)
148                     ).emit();
149                 },
150             }
151         }
152     }
153
154     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
155         // At present, lang items are always items, not trait items.
156     }
157
158     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
159         // At present, lang items are always items, not impl items.
160     }
161 }
162
163 impl LanguageItemCollector<'tcx> {
164     fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
165         let mut item_refs = FxHashMap::default();
166
167         $( item_refs.insert($name, ($variant as usize, $target)); )*
168
169         LanguageItemCollector {
170             tcx,
171             items: LanguageItems::new(),
172             item_refs,
173         }
174     }
175
176     fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
177         // Check for duplicates.
178         if let Some(original_def_id) = self.items.items[item_index] {
179             if original_def_id != item_def_id {
180                 let name = LangItem::from_u32(item_index as u32).unwrap().name();
181                 let mut err = match self.tcx.hir().span_if_local(item_def_id) {
182                     Some(span) => struct_span_err!(
183                         self.tcx.sess,
184                         span,
185                         E0152,
186                         "duplicate lang item found: `{}`.",
187                         name),
188                     None => {
189                         match self.tcx.extern_crate(item_def_id) {
190                             Some(ExternCrate {dependency_of, ..}) => {
191                                 self.tcx.sess.struct_err(&format!(
192                                 "duplicate lang item in crate `{}` (which `{}` depends on): `{}`.",
193                                 self.tcx.crate_name(item_def_id.krate),
194                                 self.tcx.crate_name(*dependency_of),
195                                 name))
196                             },
197                             _ => {
198                                 self.tcx.sess.struct_err(&format!(
199                                 "duplicate lang item in crate `{}`: `{}`.",
200                                 self.tcx.crate_name(item_def_id.krate),
201                                 name))
202                             }
203                         }
204                     },
205                 };
206                 if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
207                     span_note!(&mut err, span, "first defined here.");
208                 } else {
209                     match self.tcx.extern_crate(original_def_id) {
210                         Some(ExternCrate {dependency_of, ..}) => {
211                             err.note(&format!(
212                             "first defined in crate `{}` (which `{}` depends on).",
213                                       self.tcx.crate_name(original_def_id.krate),
214                                       self.tcx.crate_name(*dependency_of)));
215                         },
216                         _ => {
217                             err.note(&format!("first defined in crate `{}`.",
218                                       self.tcx.crate_name(original_def_id.krate)));
219                         }
220                     }
221                 }
222                 err.emit();
223             }
224         }
225
226         // Matched.
227         self.items.items[item_index] = Some(item_def_id);
228     }
229 }
230
231 /// Extracts the first `lang = "$name"` out of a list of attributes.
232 /// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
233 /// are also extracted out when found.
234 pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
235     attrs.iter().find_map(|attr| Some(match attr {
236         _ if attr.check_name(sym::lang) => (attr.value_str()?, attr.span),
237         _ if attr.check_name(sym::panic_handler) => (sym::panic_impl, attr.span),
238         _ if attr.check_name(sym::alloc_error_handler) => (sym::oom, attr.span),
239         _ => return None,
240     }))
241 }
242
243 /// Traverses and collects all the lang items in all crates.
244 pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems {
245     // Initialize the collector.
246     let mut collector = LanguageItemCollector::new(tcx);
247
248     // Collect lang items in other crates.
249     for &cnum in tcx.crates().iter() {
250         for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
251             collector.collect_item(item_index, def_id);
252         }
253     }
254
255     // Collect lang items in this crate.
256     tcx.hir().krate().visit_all_item_likes(&mut collector);
257
258     // Extract out the found lang items.
259     let LanguageItemCollector { mut items, .. } = collector;
260
261     // Find all required but not-yet-defined lang items.
262     weak_lang_items::check_crate(tcx, &mut items);
263
264     items
265 }
266
267 // End of the macro
268     }
269 }
270
271 language_item_table! {
272 //  Variant name,                Name,                 Method name,             Target;
273     BoolImplItem,                "bool",               bool_impl,               Target::Impl;
274     CharImplItem,                "char",               char_impl,               Target::Impl;
275     StrImplItem,                 "str",                str_impl,                Target::Impl;
276     SliceImplItem,               "slice",              slice_impl,              Target::Impl;
277     SliceU8ImplItem,             "slice_u8",           slice_u8_impl,           Target::Impl;
278     StrAllocImplItem,            "str_alloc",          str_alloc_impl,          Target::Impl;
279     SliceAllocImplItem,          "slice_alloc",        slice_alloc_impl,        Target::Impl;
280     SliceU8AllocImplItem,        "slice_u8_alloc",     slice_u8_alloc_impl,     Target::Impl;
281     ConstPtrImplItem,            "const_ptr",          const_ptr_impl,          Target::Impl;
282     MutPtrImplItem,              "mut_ptr",            mut_ptr_impl,            Target::Impl;
283     I8ImplItem,                  "i8",                 i8_impl,                 Target::Impl;
284     I16ImplItem,                 "i16",                i16_impl,                Target::Impl;
285     I32ImplItem,                 "i32",                i32_impl,                Target::Impl;
286     I64ImplItem,                 "i64",                i64_impl,                Target::Impl;
287     I128ImplItem,                "i128",               i128_impl,               Target::Impl;
288     IsizeImplItem,               "isize",              isize_impl,              Target::Impl;
289     U8ImplItem,                  "u8",                 u8_impl,                 Target::Impl;
290     U16ImplItem,                 "u16",                u16_impl,                Target::Impl;
291     U32ImplItem,                 "u32",                u32_impl,                Target::Impl;
292     U64ImplItem,                 "u64",                u64_impl,                Target::Impl;
293     U128ImplItem,                "u128",               u128_impl,               Target::Impl;
294     UsizeImplItem,               "usize",              usize_impl,              Target::Impl;
295     F32ImplItem,                 "f32",                f32_impl,                Target::Impl;
296     F64ImplItem,                 "f64",                f64_impl,                Target::Impl;
297     F32RuntimeImplItem,          "f32_runtime",        f32_runtime_impl,        Target::Impl;
298     F64RuntimeImplItem,          "f64_runtime",        f64_runtime_impl,        Target::Impl;
299
300     SizedTraitLangItem,          "sized",              sized_trait,             Target::Trait;
301     UnsizeTraitLangItem,         "unsize",             unsize_trait,            Target::Trait;
302     // trait injected by #[derive(PartialEq)], (i.e. "Partial EQ").
303     StructuralPeqTraitLangItem,  "structural_peq",     structural_peq_trait,    Target::Trait;
304     // trait injected by #[derive(Eq)], (i.e. "Total EQ"; no, I will not apologize).
305     StructuralTeqTraitLangItem,  "structural_teq",     structural_teq_trait,    Target::Trait;
306     CopyTraitLangItem,           "copy",               copy_trait,              Target::Trait;
307     CloneTraitLangItem,          "clone",              clone_trait,             Target::Trait;
308     SyncTraitLangItem,           "sync",               sync_trait,              Target::Trait;
309     FreezeTraitLangItem,         "freeze",             freeze_trait,            Target::Trait;
310
311     DropTraitLangItem,           "drop",               drop_trait,              Target::Trait;
312
313     CoerceUnsizedTraitLangItem,  "coerce_unsized",     coerce_unsized_trait,    Target::Trait;
314     DispatchFromDynTraitLangItem,"dispatch_from_dyn",  dispatch_from_dyn_trait, Target::Trait;
315
316     AddTraitLangItem,            "add",                add_trait,               Target::Trait;
317     SubTraitLangItem,            "sub",                sub_trait,               Target::Trait;
318     MulTraitLangItem,            "mul",                mul_trait,               Target::Trait;
319     DivTraitLangItem,            "div",                div_trait,               Target::Trait;
320     RemTraitLangItem,            "rem",                rem_trait,               Target::Trait;
321     NegTraitLangItem,            "neg",                neg_trait,               Target::Trait;
322     NotTraitLangItem,            "not",                not_trait,               Target::Trait;
323     BitXorTraitLangItem,         "bitxor",             bitxor_trait,            Target::Trait;
324     BitAndTraitLangItem,         "bitand",             bitand_trait,            Target::Trait;
325     BitOrTraitLangItem,          "bitor",              bitor_trait,             Target::Trait;
326     ShlTraitLangItem,            "shl",                shl_trait,               Target::Trait;
327     ShrTraitLangItem,            "shr",                shr_trait,               Target::Trait;
328     AddAssignTraitLangItem,      "add_assign",         add_assign_trait,        Target::Trait;
329     SubAssignTraitLangItem,      "sub_assign",         sub_assign_trait,        Target::Trait;
330     MulAssignTraitLangItem,      "mul_assign",         mul_assign_trait,        Target::Trait;
331     DivAssignTraitLangItem,      "div_assign",         div_assign_trait,        Target::Trait;
332     RemAssignTraitLangItem,      "rem_assign",         rem_assign_trait,        Target::Trait;
333     BitXorAssignTraitLangItem,   "bitxor_assign",      bitxor_assign_trait,     Target::Trait;
334     BitAndAssignTraitLangItem,   "bitand_assign",      bitand_assign_trait,     Target::Trait;
335     BitOrAssignTraitLangItem,    "bitor_assign",       bitor_assign_trait,      Target::Trait;
336     ShlAssignTraitLangItem,      "shl_assign",         shl_assign_trait,        Target::Trait;
337     ShrAssignTraitLangItem,      "shr_assign",         shr_assign_trait,        Target::Trait;
338     IndexTraitLangItem,          "index",              index_trait,             Target::Trait;
339     IndexMutTraitLangItem,       "index_mut",          index_mut_trait,         Target::Trait;
340
341     UnsafeCellTypeLangItem,      "unsafe_cell",        unsafe_cell_type,        Target::Struct;
342     VaListTypeLangItem,          "va_list",            va_list,                 Target::Struct;
343
344     DerefTraitLangItem,          "deref",              deref_trait,             Target::Trait;
345     DerefMutTraitLangItem,       "deref_mut",          deref_mut_trait,         Target::Trait;
346     ReceiverTraitLangItem,       "receiver",           receiver_trait,          Target::Trait;
347
348     FnTraitLangItem,             "fn",                 fn_trait,                Target::Trait;
349     FnMutTraitLangItem,          "fn_mut",             fn_mut_trait,            Target::Trait;
350     FnOnceTraitLangItem,         "fn_once",            fn_once_trait,           Target::Trait;
351
352     FutureTraitLangItem,         "future_trait",       future_trait,            Target::Trait;
353     GeneratorStateLangItem,      "generator_state",    gen_state,               Target::Enum;
354     GeneratorTraitLangItem,      "generator",          gen_trait,               Target::Trait;
355     UnpinTraitLangItem,          "unpin",              unpin_trait,             Target::Trait;
356     PinTypeLangItem,             "pin",                pin_type,                Target::Struct;
357
358     // Don't be fooled by the naming here: this lang item denotes `PartialEq`, not `Eq`.
359     EqTraitLangItem,             "eq",                 eq_trait,                Target::Trait;
360     PartialOrdTraitLangItem,     "partial_ord",        partial_ord_trait,       Target::Trait;
361     OrdTraitLangItem,            "ord",                ord_trait,               Target::Trait;
362
363     // A number of panic-related lang items. The `panic` item corresponds to
364     // divide-by-zero and various panic cases with `match`. The
365     // `panic_bounds_check` item is for indexing arrays.
366     //
367     // The `begin_unwind` lang item has a predefined symbol name and is sort of
368     // a "weak lang item" in the sense that a crate is not required to have it
369     // defined to use it, but a final product is required to define it
370     // somewhere. Additionally, there are restrictions on crates that use a weak
371     // lang item, but do not have it defined.
372     PanicFnLangItem,             "panic",              panic_fn,                Target::Fn;
373     PanicBoundsCheckFnLangItem,  "panic_bounds_check", panic_bounds_check_fn,   Target::Fn;
374     PanicInfoLangItem,           "panic_info",         panic_info,              Target::Struct;
375     PanicLocationLangItem,       "panic_location",     panic_location,          Target::Struct;
376     PanicImplLangItem,           "panic_impl",         panic_impl,              Target::Fn;
377     // Libstd panic entry point. Necessary for const eval to be able to catch it
378     BeginPanicFnLangItem,        "begin_panic",        begin_panic_fn,          Target::Fn;
379
380     ExchangeMallocFnLangItem,    "exchange_malloc",    exchange_malloc_fn,      Target::Fn;
381     BoxFreeFnLangItem,           "box_free",           box_free_fn,             Target::Fn;
382     DropInPlaceFnLangItem,       "drop_in_place",      drop_in_place_fn,        Target::Fn;
383     OomLangItem,                 "oom",                oom,                     Target::Fn;
384     AllocLayoutLangItem,         "alloc_layout",       alloc_layout,            Target::Struct;
385
386     StartFnLangItem,             "start",              start_fn,                Target::Fn;
387
388     EhPersonalityLangItem,       "eh_personality",     eh_personality,          Target::Fn;
389     EhUnwindResumeLangItem,      "eh_unwind_resume",   eh_unwind_resume,        Target::Fn;
390     EhCatchTypeinfoLangItem,     "eh_catch_typeinfo",  eh_catch_typeinfo,       Target::Static;
391
392     OwnedBoxLangItem,            "owned_box",          owned_box,               Target::Struct;
393
394     PhantomDataItem,             "phantom_data",       phantom_data,            Target::Struct;
395
396     ManuallyDropItem,            "manually_drop",      manually_drop,           Target::Struct;
397
398     MaybeUninitLangItem,         "maybe_uninit",       maybe_uninit,            Target::Union;
399
400     // Align offset for stride != 1; must not panic.
401     AlignOffsetLangItem,         "align_offset",       align_offset_fn,         Target::Fn;
402
403     TerminationTraitLangItem,    "termination",        termination,             Target::Trait;
404
405     Arc,                         "arc",                arc,                     Target::Struct;
406     Rc,                          "rc",                 rc,                      Target::Struct;
407 }
408
409 impl<'tcx> TyCtxt<'tcx> {
410     /// Returns the `DefId` for a given `LangItem`.
411     /// If not found, fatally aborts compilation.
412     pub fn require_lang_item(&self, lang_item: LangItem, span: Option<Span>) -> DefId {
413         self.lang_items().require(lang_item).unwrap_or_else(|msg| {
414             if let Some(span) = span {
415                 self.sess.span_fatal(span, &msg)
416             } else {
417                 self.sess.fatal(&msg)
418             }
419         })
420     }
421 }