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