]> git.proxmox.com Git - rustc.git/blob - src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / hir-def / src / lang_item.rs
1 //! Collects lang items: items marked with `#[lang = "..."]` attribute.
2 //!
3 //! This attribute to tell the compiler about semi built-in std library
4 //! features, such as Fn family of traits.
5 use hir_expand::name::Name;
6 use rustc_hash::FxHashMap;
7 use syntax::SmolStr;
8 use triomphe::Arc;
9
10 use crate::{
11 db::DefDatabase, path::Path, AdtId, AssocItemId, AttrDefId, CrateId, EnumId, EnumVariantId,
12 FunctionId, ImplId, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
13 };
14
15 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16 pub enum LangItemTarget {
17 EnumId(EnumId),
18 Function(FunctionId),
19 ImplDef(ImplId),
20 Static(StaticId),
21 Struct(StructId),
22 Union(UnionId),
23 TypeAlias(TypeAliasId),
24 Trait(TraitId),
25 EnumVariant(EnumVariantId),
26 }
27
28 impl LangItemTarget {
29 pub fn as_enum(self) -> Option<EnumId> {
30 match self {
31 LangItemTarget::EnumId(id) => Some(id),
32 _ => None,
33 }
34 }
35
36 pub fn as_function(self) -> Option<FunctionId> {
37 match self {
38 LangItemTarget::Function(id) => Some(id),
39 _ => None,
40 }
41 }
42
43 pub fn as_impl_def(self) -> Option<ImplId> {
44 match self {
45 LangItemTarget::ImplDef(id) => Some(id),
46 _ => None,
47 }
48 }
49
50 pub fn as_static(self) -> Option<StaticId> {
51 match self {
52 LangItemTarget::Static(id) => Some(id),
53 _ => None,
54 }
55 }
56
57 pub fn as_struct(self) -> Option<StructId> {
58 match self {
59 LangItemTarget::Struct(id) => Some(id),
60 _ => None,
61 }
62 }
63
64 pub fn as_trait(self) -> Option<TraitId> {
65 match self {
66 LangItemTarget::Trait(id) => Some(id),
67 _ => None,
68 }
69 }
70
71 pub fn as_enum_variant(self) -> Option<EnumVariantId> {
72 match self {
73 LangItemTarget::EnumVariant(id) => Some(id),
74 _ => None,
75 }
76 }
77 }
78
79 #[derive(Default, Debug, Clone, PartialEq, Eq)]
80 pub struct LangItems {
81 items: FxHashMap<LangItem, LangItemTarget>,
82 }
83
84 impl LangItems {
85 pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
86 self.items.get(&item).copied()
87 }
88
89 /// Salsa query. This will look for lang items in a specific crate.
90 pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> {
91 let _p = profile::span("crate_lang_items_query");
92
93 let mut lang_items = LangItems::default();
94
95 let crate_def_map = db.crate_def_map(krate);
96
97 for (_, module_data) in crate_def_map.modules() {
98 for impl_def in module_data.scope.impls() {
99 lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
100 for assoc in db.impl_data(impl_def).items.iter().copied() {
101 match assoc {
102 AssocItemId::FunctionId(f) => {
103 lang_items.collect_lang_item(db, f, LangItemTarget::Function)
104 }
105 AssocItemId::TypeAliasId(t) => {
106 lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
107 }
108 AssocItemId::ConstId(_) => (),
109 }
110 }
111 }
112
113 for def in module_data.scope.declarations() {
114 match def {
115 ModuleDefId::TraitId(trait_) => {
116 lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
117 db.trait_data(trait_).items.iter().for_each(|&(_, assoc_id)| {
118 if let AssocItemId::FunctionId(f) = assoc_id {
119 lang_items.collect_lang_item(db, f, LangItemTarget::Function);
120 }
121 });
122 }
123 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
124 lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
125 db.enum_data(e).variants.iter().for_each(|(local_id, _)| {
126 lang_items.collect_lang_item(
127 db,
128 EnumVariantId { parent: e, local_id },
129 LangItemTarget::EnumVariant,
130 );
131 });
132 }
133 ModuleDefId::AdtId(AdtId::StructId(s)) => {
134 lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
135 }
136 ModuleDefId::AdtId(AdtId::UnionId(u)) => {
137 lang_items.collect_lang_item(db, u, LangItemTarget::Union);
138 }
139 ModuleDefId::FunctionId(f) => {
140 lang_items.collect_lang_item(db, f, LangItemTarget::Function);
141 }
142 ModuleDefId::StaticId(s) => {
143 lang_items.collect_lang_item(db, s, LangItemTarget::Static);
144 }
145 ModuleDefId::TypeAliasId(t) => {
146 lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
147 }
148 _ => {}
149 }
150 }
151 }
152
153 Arc::new(lang_items)
154 }
155
156 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
157 /// traversing its dependencies.
158 pub(crate) fn lang_item_query(
159 db: &dyn DefDatabase,
160 start_crate: CrateId,
161 item: LangItem,
162 ) -> Option<LangItemTarget> {
163 let _p = profile::span("lang_item_query");
164 let lang_items = db.crate_lang_items(start_crate);
165 let start_crate_target = lang_items.items.get(&item);
166 if let Some(&target) = start_crate_target {
167 return Some(target);
168 }
169 db.crate_graph()[start_crate]
170 .dependencies
171 .iter()
172 .find_map(|dep| db.lang_item(dep.crate_id, item))
173 }
174
175 fn collect_lang_item<T>(
176 &mut self,
177 db: &dyn DefDatabase,
178 item: T,
179 constructor: fn(T) -> LangItemTarget,
180 ) where
181 T: Into<AttrDefId> + Copy,
182 {
183 let _p = profile::span("collect_lang_item");
184 if let Some(lang_item) = db.lang_attr(item.into()) {
185 self.items.entry(lang_item).or_insert_with(|| constructor(item));
186 }
187 }
188 }
189
190 pub(crate) fn lang_attr_query(db: &dyn DefDatabase, item: AttrDefId) -> Option<LangItem> {
191 let attrs = db.attrs(item);
192 attrs.by_key("lang").string_value().and_then(|it| LangItem::from_str(&it))
193 }
194
195 pub enum GenericRequirement {
196 None,
197 Minimum(usize),
198 Exact(usize),
199 }
200
201 macro_rules! language_item_table {
202 (
203 $( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
204 ) => {
205
206 /// A representation of all the valid language items in Rust.
207 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
208 pub enum LangItem {
209 $(
210 #[doc = concat!("The `", stringify!($name), "` lang item.")]
211 $(#[$attr])*
212 $variant,
213 )*
214 }
215
216 impl LangItem {
217 pub fn name(self) -> SmolStr {
218 match self {
219 $( LangItem::$variant => SmolStr::new(stringify!($name)), )*
220 }
221 }
222
223 /// Opposite of [`LangItem::name`]
224 pub fn from_str(name: &str) -> Option<Self> {
225 match name {
226 $( stringify!($name) => Some(LangItem::$variant), )*
227 _ => None,
228 }
229 }
230 }
231 }
232 }
233
234 impl LangItem {
235 /// Opposite of [`LangItem::name`]
236 pub fn from_name(name: &hir_expand::name::Name) -> Option<Self> {
237 Self::from_str(name.as_str()?)
238 }
239
240 pub fn path(&self, db: &dyn DefDatabase, start_crate: CrateId) -> Option<Path> {
241 let t = db.lang_item(start_crate, *self)?;
242 Some(Path::LangItem(t, None))
243 }
244
245 pub fn ty_rel_path(
246 &self,
247 db: &dyn DefDatabase,
248 start_crate: CrateId,
249 seg: Name,
250 ) -> Option<Path> {
251 let t = db.lang_item(start_crate, *self)?;
252 Some(Path::LangItem(t, Some(seg)))
253 }
254 }
255
256 language_item_table! {
257 // Variant name, Name, Getter method name, Target Generic requirements;
258 Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
259 Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
260 /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
261 StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
262 /// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize).
263 StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait, GenericRequirement::None;
264 Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
265 Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
266 Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
267 DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
268 /// The associated item of the [`DiscriminantKind`] trait.
269 Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None;
270
271 PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None;
272 Metadata, sym::metadata_type, metadata_type, Target::AssocTy, GenericRequirement::None;
273 DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;
274
275 Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
276
277 FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, Target::Trait, GenericRequirement::Exact(0);
278 FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
279
280 Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
281 Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;
282
283 CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
284 DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
285
286 // language items relating to transmutability
287 TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
288 TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3);
289
290 Add, sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1);
291 Sub, sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
292 Mul, sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1);
293 Div, sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1);
294 Rem, sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1);
295 Neg, sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0);
296 Not, sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0);
297 BitXor, sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
298 BitAnd, sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
299 BitOr, sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
300 Shl, sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
301 Shr, sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
302 AddAssign, sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
303 SubAssign, sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1);
304 MulAssign, sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1);
305 DivAssign, sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1);
306 RemAssign, sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1);
307 BitXorAssign, sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
308 BitAndAssign, sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1);
309 BitOrAssign, sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
310 ShlAssign, sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1);
311 ShrAssign, sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1);
312 Index, sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1);
313 IndexMut, sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
314
315 UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
316 VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
317
318 Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);
319 DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
320 DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
321 Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
322
323 Fn, kw::fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
324 FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
325 FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
326
327 FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
328
329 Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
330 GeneratorState, sym::generator_state, gen_state, Target::Enum, GenericRequirement::None;
331 Generator, sym::generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1);
332 Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
333 Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
334
335 PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
336 PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
337 CVoid, sym::c_void, c_void, Target::Enum, GenericRequirement::None;
338
339 // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
340 // various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
341 //
342 // The `begin_unwind` lang item has a predefined symbol name and is sort of a "weak lang item"
343 // in the sense that a crate is not required to have it defined to use it, but a final product
344 // is required to define it somewhere. Additionally, there are restrictions on crates that use
345 // a weak lang item, but do not have it defined.
346 Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0);
347 PanicNounwind, sym::panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0);
348 PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
349 PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
350 ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
351 PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0);
352 PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0);
353 PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None;
354 PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
355 PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
356 PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0);
357 /// libstd panic entry point. Necessary for const eval to be able to catch it
358 BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
359
360 // Lang items needed for `format_args!()`.
361 FormatAlignment, sym::format_alignment, format_alignment, Target::Enum, GenericRequirement::None;
362 FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None;
363 FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None;
364 FormatCount, sym::format_count, format_count, Target::Enum, GenericRequirement::None;
365 FormatPlaceholder, sym::format_placeholder, format_placeholder, Target::Struct, GenericRequirement::None;
366 FormatUnsafeArg, sym::format_unsafe_arg, format_unsafe_arg, Target::Struct, GenericRequirement::None;
367
368 ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
369 BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
370 DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
371 AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
372
373 Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
374
375 EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None;
376 EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None;
377
378 OwnedBox, sym::owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1);
379
380 PhantomData, sym::phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1);
381
382 ManuallyDrop, sym::manually_drop, manually_drop, Target::Struct, GenericRequirement::None;
383
384 MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union, GenericRequirement::None;
385
386 /// Align offset for stride != 1; must not panic.
387 AlignOffset, sym::align_offset, align_offset_fn, Target::Fn, GenericRequirement::None;
388
389 Termination, sym::termination, termination, Target::Trait, GenericRequirement::None;
390
391 Try, sym::Try, try_trait, Target::Trait, GenericRequirement::None;
392
393 Tuple, sym::tuple_trait, tuple_trait, Target::Trait, GenericRequirement::Exact(0);
394
395 SliceLen, sym::slice_len_fn, slice_len_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
396
397 // Language items from AST lowering
398 TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
399 TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
400 TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
401 TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
402
403 PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
404
405 ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
406
407 Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None;
408 PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
409 PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;
410
411 // FIXME(swatinem): the following lang items are used for async lowering and
412 // should become obsolete eventually.
413 ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
414 GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
415
416 Context, sym::Context, context, Target::Struct, GenericRequirement::None;
417 FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
418
419 Option, sym::Option, option_type, Target::Enum, GenericRequirement::None;
420 OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
421 OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;
422
423 ResultOk, sym::Ok, result_ok_variant, Target::Variant, GenericRequirement::None;
424 ResultErr, sym::Err, result_err_variant, Target::Variant, GenericRequirement::None;
425
426 ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None;
427 ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None;
428
429 IntoFutureIntoFuture, sym::into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
430 IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
431 IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
432
433 PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
434
435 RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct, GenericRequirement::None;
436 RangeFull, sym::RangeFull, range_full_struct, Target::Struct, GenericRequirement::None;
437 RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, Target::Struct, GenericRequirement::None;
438 RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent), GenericRequirement::None;
439 Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None;
440 RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
441 RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
442
443 String, sym::String, string, Target::Struct, GenericRequirement::None;
444 CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
445 }