Skip to main content

rapx/
def_id.rs

1//! Resolution of well-known `core`/`std`/`alloc` function paths to their
2//! internal [`DefId`]s.
3//!
4//! This module is the single home for "which standard-library item is this
5//! `DefId`?", used by [`crate::verify::api_classify`] and the alias checker to
6//! match APIs exactly instead of substring-matching a `def_path_str`.  It is
7//! deliberately placed at the crate root (next to [`crate::compat`]) rather
8//! than under `helpers/`, because it owns global state and a one-time
9//! `init(tcx)` hook in the compiler callback.
10//!
11//! # How a lookup works
12//!
13//! 1. The [`intrinsics!`] macro declares a *path table*: each identifier maps
14//!    to one or more candidate `fn_def.name()` strings (typically the `std::`
15//!    re-export plus the `core::`/`alloc::` canonical form, for `#![no_std]`
16//!    crates) and generates a `{id}() -> Option<DefId>` accessor.
17//! 2. [`init`] runs once from [`crate::RapCallback::after_analysis`], iterates
18//!    every `fn_def` of the `core`/`std`/`alloc` crates via `rustc_public`,
19//!    and caches the `path -> DefId` map in a `OnceLock`.
20//! 3. [`contains`] tests whether a call-site `DefId` is in a set of resolved
21//!    ids; [`is_drop_fn`] is a convenience wrapper over the drop family.
22//!
23//! # Path format
24//!
25//! `rustc_public::CrateDef::name()` is `def_path_str` with crate-name
26//! resolution and untrimmed paths, so a re-exported item appears under its
27//! `std::` name and generics are kept: `std::mem::MaybeUninit::<T>::write`,
28//! `std::result::Result::<T, E>::unwrap`, `std::vec::Vec::<T, A>::push`,
29//! `std::ptr::mut_ptr::<impl *mut T>::copy_from`.
30//!
31//! # Limitations
32//!
33//! - In `#![no_std]` builds some intrinsics are absent; [`init`] only warns
34//!   (`rap_warn!`) instead of panicking, so an entry with no matching path
35//!   simply yields `None`.
36
37use indexmap::IndexMap;
38use rustc_hir::def_id::DefId;
39use rustc_middle::ty::TyCtxt;
40use rustc_public::{CrateDef, rustc_internal};
41use rustc_span::sym;
42use std::sync::OnceLock;
43
44static INIT: OnceLock<Intrinsics> = OnceLock::new();
45
46struct Intrinsics {
47    // The key is fn path, starting from `core::` or `std::`. The value is internal def id.
48    map: IndexMap<Box<str>, DefId>,
49}
50
51static TYPES: OnceLock<Types> = OnceLock::new();
52
53/// Resolved `DefId`s of well-known std *types* (ADTs), used by the ADT
54/// type-name classifiers ([`crate::verify::api_classify::is_std_box`],
55/// [`crate::verify::api_classify::is_std_vec`], …).  Each entry collects the
56/// std type's `DefId` (via lang/diagnostic item, or — for `NonNull`, which has
57/// neither — by name-scanning the std crates' `adts()`) *and* any same-named
58/// re-implementations in the local crate (the std-challenge suites re-implement
59/// `Vec`/`NonNull` under the same names).
60struct Types {
61    box_types: Vec<DefId>,
62    cstring_types: Vec<DefId>,
63    vec_types: Vec<DefId>,
64    nonnull_types: Vec<DefId>,
65    maybe_uninit_types: Vec<DefId>,
66    ascii_char_types: Vec<DefId>,
67    ordering_types: Vec<DefId>,
68    iter_types: Vec<DefId>,
69    rc_types: Vec<DefId>,
70    sync_primitive_types: Vec<DefId>,
71    /// `alloc::alloc::exchange_malloc` (`Box::new`'s lang item on toolchains
72    /// that lower `Box::new` to it) — resolved by name scan, since it has no
73    /// lang item on newer toolchains.
74    exchange_malloc: Option<DefId>,
75    /// Negative auto-trait types (`Cell`/`UnsafeCell`/`RefCell`/`Ref`/`RefMut`/
76    /// guards), keyed by short name — used by `ContainNoType` in Send/Sync obligations.
77    negative_types: IndexMap<Box<str>, Vec<DefId>>,
78}
79
80/// Short names of the std `!Send`/`!Sync` negative types resolved by name scan
81/// (those without a lang/diagnostic item).  `UnsafeCell` is resolved via its
82/// `#[lang = "unsafe_cell"]` item instead.
83const NEGATIVE_TYPE_NAMES: &[&str] = &[
84    "Cell",
85    "RefCell",
86    "Ref",
87    "RefMut",
88    "MutexGuard",
89    "RwLockWriteGuard",
90    "MappedMutexGuard",
91];
92
93pub fn init(tcx: TyCtxt) {
94    INIT.get_or_init(|| init_inner(tcx));
95    TYPES.get_or_init(|| init_types(tcx));
96    METHODS.get_or_init(|| init_methods(tcx));
97}
98
99fn init_types(tcx: TyCtxt) -> Types {
100    let mut types = Types {
101        box_types: Vec::new(),
102        cstring_types: Vec::new(),
103        vec_types: Vec::new(),
104        nonnull_types: Vec::new(),
105        maybe_uninit_types: Vec::new(),
106        ascii_char_types: Vec::new(),
107        ordering_types: Vec::new(),
108        iter_types: Vec::new(),
109        rc_types: Vec::new(),
110        sync_primitive_types: Vec::new(),
111        exchange_malloc: None,
112        negative_types: IndexMap::new(),
113    };
114
115    // Real std types via diagnostic/lang items (`NonNull` only before rustc
116    // 1.100, when it was still a diagnostic item).
117    types.box_types.extend(tcx.lang_items().owned_box());
118    types
119        .cstring_types
120        .extend(tcx.get_diagnostic_item(sym::cstring_type));
121    types.vec_types.extend(tcx.get_diagnostic_item(sym::Vec));
122    types.rc_types.extend(tcx.get_diagnostic_item(sym::Rc));
123    // `core::cmp::Ordering` is `#[lang = "Ordering"]`.
124    types
125        .ordering_types
126        .extend(tcx.lang_items().ordering_enum());
127    // `core::mem::MaybeUninit` is `#[lang = "maybe_uninit"]`.
128    types
129        .maybe_uninit_types
130        .extend(tcx.lang_items().maybe_uninit());
131    // `core::cell::UnsafeCell` is `#[lang = "unsafe_cell"]`.
132    if let Some(unsafe_cell) = tcx.lang_items().unsafe_cell_type() {
133        types
134            .negative_types
135            .entry("UnsafeCell".into())
136            .or_default()
137            .push(unsafe_cell);
138    }
139
140    // `core::slice::Iter` is `#[rustc_diagnostic_item = "SliceIter"]` on older
141    // toolchains (the item was dropped once `adts()` became available, so only
142    // referenced when `adts()` is absent). `slice::IterMut` has no diagnostic
143    // item, so resolve it from the self type of its `fn_defs()`-emitted methods.
144    #[cfg(not(rapx_has_public_adts))]
145    {
146        types
147            .iter_types
148            .extend(tcx.get_diagnostic_item(sym::SliceIter));
149        types
150            .nonnull_types
151            .extend(tcx.get_diagnostic_item(sym::NonNull));
152
153        for krate in rustc_public::external_crates()
154            .into_iter()
155            .filter(|k| ["core", "std", "alloc"].iter().any(|n| *n == k.name))
156        {
157            for fn_def in krate.fn_defs() {
158                let name = fn_def.name();
159                let did = rustc_internal::internal(tcx, fn_def.def_id());
160                if name.contains("::IterMut::") {
161                    if let Some(adt_did) = assoc_self_adt_did(tcx, did) {
162                        types.iter_types.push(adt_did);
163                    }
164                }
165                // `std::ascii::Char` has no diagnostic item on toolchains
166                // without `adts()`; resolve it from the self type of its
167                // methods (`core::ascii::Char::from_u8` etc.).
168                if name.contains("::Char::") {
169                    if let Some(adt_did) = assoc_self_adt_did(tcx, did) {
170                        if !types.ascii_char_types.contains(&adt_did) {
171                            types.ascii_char_types.push(adt_did);
172                        }
173                    }
174                }
175                // `alloc::alloc::exchange_malloc` (`Box::new`'s allocator on
176                // some toolchains) has no lang item on newer toolchains; resolve
177                // it by name so `Box::new`'s fresh allocation keeps provenance.
178                if name.contains("exchange_malloc") {
179                    types.exchange_malloc.get_or_insert(did);
180                }
181                // Synchronization primitives have no diagnostic/lang item, so
182                // resolve them from the self type of their methods (the
183                // `adts()`-less fallback path).
184                if is_sync_primitive_method(&name) {
185                    if let Some(adt_did) = assoc_self_adt_did(tcx, did) {
186                        if !types.sync_primitive_types.contains(&adt_did) {
187                            types.sync_primitive_types.push(adt_did);
188                        }
189                    }
190                }
191            }
192        }
193    }
194
195    // Same-named re-implementations in the local crate (the std-challenge
196    // suites re-implement `NonNull`/`Iter`/`IterMut`). Scan local ADTs by name
197    // via `iter_local_def_id`, which works on every toolchain.
198    for local_did in tcx.iter_local_def_id() {
199        let did = local_did.to_def_id();
200        if !matches!(
201            tcx.def_kind(did),
202            rustc_hir::def::DefKind::Struct
203                | rustc_hir::def::DefKind::Enum
204                | rustc_hir::def::DefKind::Union
205        ) {
206            continue;
207        }
208        let name = tcx.def_path_str(did);
209        if name.ends_with("::Vec") || name == "Vec" {
210            types.vec_types.push(did);
211        }
212        if name.ends_with("::Iter")
213            || name == "Iter"
214            || name.ends_with("::IterMut")
215            || name == "IterMut"
216        {
217            types.iter_types.push(did);
218        }
219        if name.ends_with("::NonNull") || name == "NonNull" {
220            types.nonnull_types.push(did);
221        }
222        if name.ends_with("::MaybeUninit") || name == "MaybeUninit" {
223            types.maybe_uninit_types.push(did);
224        }
225        if name.ends_with("::Rc") || name == "Rc" {
226            types.rc_types.push(did);
227        }
228        let short = name.rsplit("::").next().unwrap_or(&name);
229        if is_sync_primitive_short_name(short) {
230            types.sync_primitive_types.push(did);
231        }
232        if let Some(neg) = negative_type_name(short) {
233            types
234                .negative_types
235                .entry(neg.into())
236                .or_default()
237                .push(did);
238        }
239    }
240
241    // External std ADTs with neither a lang nor a diagnostic item: `NonNull`
242    // on newer toolchains (it became `#[lang = "non_null"]`, which has no
243    // `LangItem` variant) and `slice::Iter`/`IterMut` (no diagnostic item).
244    // Resolve by name-scanning the std crates' `adts()`.
245    #[cfg(rapx_has_public_adts)]
246    {
247        for krate in rustc_public::external_crates()
248            .into_iter()
249            .filter(|k| ["core", "std", "alloc"].iter().any(|n| *n == k.name))
250        {
251            for adt in krate.adts() {
252                let name = adt.name();
253                if name.ends_with("::NonNull") {
254                    types
255                        .nonnull_types
256                        .push(rustc_internal::internal(tcx, adt.def_id()));
257                }
258                if name.ends_with("::MaybeUninit") {
259                    types
260                        .maybe_uninit_types
261                        .push(rustc_internal::internal(tcx, adt.def_id()));
262                }
263                if name.ends_with("::AsciiChar")
264                    || name.ends_with("::Char")
265                    || name == "AsciiChar"
266                    || name == "Char"
267                {
268                    types
269                        .ascii_char_types
270                        .push(rustc_internal::internal(tcx, adt.def_id()));
271                }
272                if name.ends_with("::Iter") || name.ends_with("::IterMut") {
273                    types
274                        .iter_types
275                        .push(rustc_internal::internal(tcx, adt.def_id()));
276                }
277                if name.ends_with("::Rc") || name == "Rc" {
278                    types
279                        .rc_types
280                        .push(rustc_internal::internal(tcx, adt.def_id()));
281                }
282                let short = name.rsplit("::").next().unwrap_or(&name);
283                if is_sync_primitive_short_name(short) {
284                    types
285                        .sync_primitive_types
286                        .push(rustc_internal::internal(tcx, adt.def_id()));
287                }
288                if let Some(neg) = negative_type_name(short) {
289                    types
290                        .negative_types
291                        .entry(neg.into())
292                        .or_default()
293                        .push(rustc_internal::internal(tcx, adt.def_id()));
294                }
295            }
296        }
297    }
298
299    types
300}
301
302/// Whether a type's short name denotes a synchronization primitive that guards
303/// its interior mutability (`Mutex`/`RwLock`/`OnceLock`/`OnceCell`/`Atomic*`).
304fn is_sync_primitive_short_name(short: &str) -> bool {
305    matches!(short, "Mutex" | "RwLock" | "OnceLock" | "OnceCell") || short.starts_with("Atomic")
306}
307
308/// The negative-type name for a short type name, if it is one of the std
309/// `!Send`/`!Sync` negative types.
310fn negative_type_name(short: &str) -> Option<&'static str> {
311    NEGATIVE_TYPE_NAMES.iter().copied().find(|&n| n == short)
312}
313
314/// Whether an `fn_def.name()` (e.g. `std::sync::Mutex::<T>::lock`) belongs to a
315/// synchronization primitive's inherent method.  Used to resolve the primitive's
316/// ADT from its methods' self type when `adts()` is unavailable.
317#[cfg(not(rapx_has_public_adts))]
318fn is_sync_primitive_method(name: &str) -> bool {
319    name.contains("::Mutex::")
320        || name.contains("::RwLock::")
321        || name.contains("::OnceLock::")
322        || name.contains("::OnceCell::")
323        || name.contains("::Atomic")
324}
325
326/// `alloc::boxed::Box` (and any local `Box` re-implementation).
327pub fn box_types() -> &'static [DefId] {
328    &TYPES
329        .get()
330        .expect("Type DefIds haven't been initialized.")
331        .box_types
332}
333
334/// `alloc::ffi::CString` (and any local `CString` re-implementation).
335pub fn cstring_types() -> &'static [DefId] {
336    &TYPES
337        .get()
338        .expect("Type DefIds haven't been initialized.")
339        .cstring_types
340}
341
342/// `alloc::vec::Vec` (and any local `Vec` re-implementation).
343pub fn vec_types() -> &'static [DefId] {
344    &TYPES
345        .get()
346        .expect("Type DefIds haven't been initialized.")
347        .vec_types
348}
349
350/// `core::ptr::NonNull` (and any local `NonNull` re-implementation).
351pub fn nonnull_types() -> &'static [DefId] {
352    &TYPES
353        .get()
354        .expect("Type DefIds haven't been initialized.")
355        .nonnull_types
356}
357
358/// `core::mem::MaybeUninit` (and any local re-implementation).
359pub fn maybe_uninit_types() -> &'static [DefId] {
360    &TYPES
361        .get()
362        .expect("Type DefIds haven't been initialized.")
363        .maybe_uninit_types
364}
365
366/// `core::ascii::Char` (`AsciiChar`, the `u8` newtype; and any local
367/// re-implementation).
368pub fn ascii_char_types() -> &'static [DefId] {
369    &TYPES
370        .get()
371        .expect("Type DefIds haven't been initialized.")
372        .ascii_char_types
373}
374
375/// `alloc::alloc::exchange_malloc`, if present on this toolchain.
376pub fn exchange_malloc() -> Option<DefId> {
377    TYPES
378        .get()
379        .expect("Type DefIds haven't been initialized.")
380        .exchange_malloc
381}
382
383/// `core::cmp::Ordering`.
384pub fn ordering_types() -> &'static [DefId] {
385    &TYPES
386        .get()
387        .expect("Type DefIds haven't been initialized.")
388        .ordering_types
389}
390
391/// `core::slice::Iter` / `core::slice::IterMut` (the two-field `ptr`/`end`
392/// slice iterators, plus any local re-implementation).
393pub fn iter_types() -> &'static [DefId] {
394    &TYPES
395        .get()
396        .expect("Type DefIds haven't been initialized.")
397        .iter_types
398}
399
400/// `alloc::rc::Rc` (and any local `Rc` re-implementation) — the non-atomic
401/// reference-counted smart pointer, a `!Send`/`!Sync` negative type.
402pub fn rc_types() -> &'static [DefId] {
403    &TYPES
404        .get()
405        .expect("Type DefIds haven't been initialized.")
406        .rc_types
407}
408
409/// Synchronization primitives (`Mutex`/`RwLock`/`OnceLock`/`OnceCell`/`Atomic*`,
410/// plus any local re-implementation) that guard their interior mutability, used
411/// to discharge the `RefSend` auto-trait obligation.
412pub fn sync_primitive_types() -> &'static [DefId] {
413    &TYPES
414        .get()
415        .expect("Type DefIds haven't been initialized.")
416        .sync_primitive_types
417}
418
419/// Resolve a negative-type name (as written in `std-trait-ensures.json`) to its
420/// resolved `DefId` set.  Unknown names resolve to an empty set (the checker
421/// then reports `Unknown`).
422pub fn negative_type_defs(name: &str) -> &'static [DefId] {
423    match name {
424        "Rc" => rc_types(),
425        "NonNull" => nonnull_types(),
426        _ => TYPES
427            .get()
428            .and_then(|t| t.negative_types.get(name))
429            .map(Vec::as_slice)
430            .unwrap_or(&[]),
431    }
432}
433
434/// Resolved `DefId`s of std *methods* that are matched by *generic name* rather
435/// than a fixed `intrinsics!` path (e.g. `len`, `capacity`, `::abs`,
436/// `::checked_add`, `::split_at`, `Iterator::position`, …). Each group collects
437/// every `fn_def` — from the std crates *and* the local crate (the
438/// std-challenge suites re-implement `Vec`/slice-like types and their methods) —
439/// whose name matches the group's pattern. Callers match a call-site `DefId`
440/// against these sets via [`contains`].
441static METHODS: OnceLock<Methods> = OnceLock::new();
442
443struct Methods {
444    len_fns: Vec<DefId>,
445    capacity_fns: Vec<DefId>,
446    from_raw_parts_fns: Vec<DefId>,
447    from_raw_parts_mut_fns: Vec<DefId>,
448    with_capacity_fns: Vec<DefId>,
449    box_alloc_ctors: Vec<DefId>,
450    vec_ownership_transfer_fns: Vec<DefId>,
451    min_like: Vec<DefId>,
452    max: Vec<DefId>,
453    clamp: Vec<DefId>,
454    abs: Vec<DefId>,
455    neg: Vec<DefId>,
456    sat_unchecked_add: Vec<DefId>,
457    sat_unchecked_mul: Vec<DefId>,
458    checked_add: Vec<DefId>,
459    checked_mul: Vec<DefId>,
460    overflowing_nz: Vec<DefId>,
461    bit_preserving_nz: Vec<DefId>,
462    checked_nonzero_iff: Vec<DefId>,
463    checked_next_pow2: Vec<DefId>,
464    layout_align: Vec<DefId>,
465    split_at: Vec<DefId>,
466    align_to_local: Vec<DefId>,
467    iter_position: Vec<DefId>,
468    strlen: Vec<DefId>,
469    slice_get_unchecked: Vec<DefId>,
470    sliceindex_get_unchecked: Vec<DefId>,
471    slice_range_fns: Vec<DefId>,
472}
473
474fn init_methods(tcx: TyCtxt) -> Methods {
475    let mut methods = Methods {
476        len_fns: Vec::new(),
477        capacity_fns: Vec::new(),
478        from_raw_parts_fns: Vec::new(),
479        from_raw_parts_mut_fns: Vec::new(),
480        with_capacity_fns: Vec::new(),
481        box_alloc_ctors: Vec::new(),
482        vec_ownership_transfer_fns: Vec::new(),
483        min_like: Vec::new(),
484        max: Vec::new(),
485        clamp: Vec::new(),
486        abs: Vec::new(),
487        neg: Vec::new(),
488        sat_unchecked_add: Vec::new(),
489        sat_unchecked_mul: Vec::new(),
490        checked_add: Vec::new(),
491        checked_mul: Vec::new(),
492        overflowing_nz: Vec::new(),
493        bit_preserving_nz: Vec::new(),
494        checked_nonzero_iff: Vec::new(),
495        checked_next_pow2: Vec::new(),
496        layout_align: Vec::new(),
497        split_at: Vec::new(),
498        align_to_local: Vec::new(),
499        iter_position: Vec::new(),
500        strlen: Vec::new(),
501        slice_get_unchecked: Vec::new(),
502        sliceindex_get_unchecked: Vec::new(),
503        slice_range_fns: Vec::new(),
504    };
505
506    for krate in std::iter::once(rustc_public::local_crate())
507        .chain(rustc_public::external_crates())
508        .filter(|k| k.is_local || ["core", "std", "alloc"].iter().any(|n| *n == k.name))
509    {
510        for fn_def in krate.fn_defs() {
511            let name = fn_def.name();
512            let did = rustc_internal::internal(tcx, fn_def.def_id());
513
514            if name.ends_with("::len") {
515                methods.len_fns.push(did);
516            }
517            if name.ends_with("::capacity") {
518                methods.capacity_fns.push(did);
519            }
520            if name.ends_with("::from_raw_parts") || name.ends_with("::from_raw_parts_mut") {
521                methods.from_raw_parts_fns.push(did);
522            }
523            if name.ends_with("::from_raw_parts_mut") {
524                methods.from_raw_parts_mut_fns.push(did);
525            }
526            if name.ends_with("::with_capacity") && name.contains("::Vec::") {
527                methods.with_capacity_fns.push(did);
528            }
529            if name.contains("::Box::")
530                && (name.ends_with("::new")
531                    || name.ends_with("::new_in")
532                    || name.ends_with("::new_uninit")
533                    || name.ends_with("::new_uninit_in")
534                    || name.ends_with("::try_new_uninit")
535                    || name.ends_with("::try_new_uninit_in"))
536            {
537                methods.box_alloc_ctors.push(did);
538            }
539            if (name.ends_with("::from_raw_parts") || name.ends_with("::from_parts"))
540                && (name.contains("Vec") || name.contains("vec::"))
541            {
542                methods.vec_ownership_transfer_fns.push(did);
543            }
544
545            if ((name.contains("::cmp::min") || name.contains("::Ord::min"))
546                && !name.contains("min_by"))
547                || name.ends_with("::midpoint")
548                // Recent nightly lowered `Ord::min`/`Ord::max` for integers to the
549                // `integer_min`/`integer_max` intrinsics (instead of an inline
550                // `if self <= other` branch), so match those here to keep the
551                // `ReturnMin`/`ReturnMax` (ite) modelling working.
552                || name.ends_with("::integer_min")
553            {
554                methods.min_like.push(did);
555            }
556            if (name.contains("::cmp::max") || name.contains("::Ord::max"))
557                && !name.contains("max_by")
558                || name.ends_with("::integer_max")
559            {
560                methods.max.push(did);
561            }
562            if name.ends_with("::clamp") {
563                methods.clamp.push(did);
564            }
565            if name.ends_with("::abs")
566                || name.ends_with("::saturating_abs")
567                || name.ends_with("::wrapping_abs")
568                || name.ends_with("::unsigned_abs")
569            {
570                methods.abs.push(did);
571            }
572            if name.ends_with("::neg")
573                || name.ends_with("::wrapping_neg")
574                || name.ends_with("::saturating_neg")
575            {
576                methods.neg.push(did);
577            }
578            if name.ends_with("::saturating_add") || name.ends_with("::unchecked_add") {
579                methods.sat_unchecked_add.push(did);
580            }
581            if name.ends_with("::saturating_mul") || name.ends_with("::unchecked_mul") {
582                methods.sat_unchecked_mul.push(did);
583            }
584            if name.ends_with("::checked_add") {
585                methods.checked_add.push(did);
586            }
587            if name.ends_with("::checked_mul") {
588                methods.checked_mul.push(did);
589            }
590            if name.ends_with("::overflowing_abs") || name.ends_with("::overflowing_neg") {
591                methods.overflowing_nz.push(did);
592            }
593            if name.contains("::rotate_left")
594                || name.contains("::rotate_right")
595                || name.contains("::swap_bytes")
596                || name.contains("::reverse_bits")
597                || name.contains("::from_be")
598                || name.contains("::from_le")
599                || name.contains("::to_be")
600                || name.contains("::to_le")
601                || name.contains("::count_ones")
602                || name.contains("::isqrt")
603                || name.contains("::saturating_pow")
604            {
605                methods.bit_preserving_nz.push(did);
606            }
607            if name.ends_with("::checked_pow")
608                || name.ends_with("::checked_abs")
609                || name.ends_with("::checked_neg")
610            {
611                methods.checked_nonzero_iff.push(did);
612            }
613            if name.ends_with("::checked_next_power_of_two") {
614                methods.checked_next_pow2.push(did);
615            }
616            if name.ends_with("Layout::align") {
617                methods.layout_align.push(did);
618            }
619            if name.contains("::split_at") {
620                methods.split_at.push(did);
621            }
622            if name.ends_with("align_to_ext") || name.ends_with("align_to_mut_ext") {
623                methods.align_to_local.push(did);
624            }
625            if name.contains("Iterator::position")
626                || name.contains("Iterator::find")
627                || name.contains("Iterator::rposition")
628            {
629                methods.iter_position.push(did);
630            }
631            if name == "strlen" || name.ends_with("::strlen") {
632                methods.strlen.push(did);
633            }
634            if (name.contains("::get_unchecked") || name.contains("::get_unchecked_mut"))
635                && (name.contains("::<impl [T]>::get_unchecked")
636                    || name.contains("::<impl *mut [T]>::get_unchecked")
637                    || name.contains("::<impl *const [T]>::get_unchecked")
638                    || name.contains("::mut_ptr::get_unchecked")
639                    || name.contains("::const_ptr::get_unchecked"))
640            {
641                methods.slice_get_unchecked.push(did);
642            }
643            if (name.contains("::get_unchecked") || name.contains("::get_unchecked_mut"))
644                && name.contains("::SliceIndex")
645            {
646                methods.sliceindex_get_unchecked.push(did);
647            }
648            if name.ends_with("slice::index::range") || name.ends_with("::slice::range") {
649                methods.slice_range_fns.push(did);
650            }
651        }
652    }
653
654    methods
655}
656
657/// `len` query methods (`slice::len`, `str::len`, `Vec::len`, `String::len`,
658/// pointer-slice `len`, and any local re-implementation).
659pub fn len_fns() -> &'static [DefId] {
660    &METHODS
661        .get()
662        .expect("Method DefIds haven't been initialized.")
663        .len_fns
664}
665
666/// `capacity` query methods (`Vec::capacity` and local re-implementations).
667pub fn capacity_fns() -> &'static [DefId] {
668    &METHODS
669        .get()
670        .expect("Method DefIds haven't been initialized.")
671        .capacity_fns
672}
673
674/// `from_raw_parts` constructors (`slice`/`str`/`ptr`/`NonNull`/`Vec`/`String`
675/// and local re-implementations).
676pub fn from_raw_parts_fns() -> &'static [DefId] {
677    &METHODS
678        .get()
679        .expect("Method DefIds haven't been initialized.")
680        .from_raw_parts_fns
681}
682
683/// `from_raw_parts_mut` constructors (`slice`/`ptr`/`NonNull` and local
684/// re-implementations).
685pub fn from_raw_parts_mut_fns() -> &'static [DefId] {
686    &METHODS
687        .get()
688        .expect("Method DefIds haven't been initialized.")
689        .from_raw_parts_mut_fns
690}
691
692/// `Vec::with_capacity` (and local re-implementations).
693pub fn with_capacity_fns() -> &'static [DefId] {
694    &METHODS
695        .get()
696        .expect("Method DefIds haven't been initialized.")
697        .with_capacity_fns
698}
699
700/// `Box::new` / `new_in` / `new_uninit` / `new_uninit_in` (and `try_` variants).
701pub fn box_alloc_ctors() -> &'static [DefId] {
702    &METHODS
703        .get()
704        .expect("Method DefIds haven't been initialized.")
705        .box_alloc_ctors
706}
707
708/// `Vec::from_raw_parts` / `Vec::from_parts` (ownership transfer into a `Vec`).
709pub fn vec_ownership_transfer_fns() -> &'static [DefId] {
710    &METHODS
711        .get()
712        .expect("Method DefIds haven't been initialized.")
713        .vec_ownership_transfer_fns
714}
715
716/// The ADT `DefId` that `def_id`'s associated function belongs to (the impl's
717/// `self` type), used to resolve an ADT that has no lang/diagnostic item from
718/// one of its emitted methods (e.g. `slice::IterMut`).
719#[cfg(not(rapx_has_public_adts))]
720fn assoc_self_adt_did(tcx: TyCtxt, def_id: DefId) -> Option<DefId> {
721    let ty = crate::helpers::name::get_struct_self_ty(tcx, def_id)?;
722    match ty.kind() {
723        rustc_middle::ty::TyKind::Adt(adt, _) => Some(adt.did()),
724        _ => None,
725    }
726}
727
728pub fn min_like_fns() -> &'static [DefId] {
729    &METHODS
730        .get()
731        .expect("Method DefIds haven't been initialized.")
732        .min_like
733}
734pub fn max_fns() -> &'static [DefId] {
735    &METHODS
736        .get()
737        .expect("Method DefIds haven't been initialized.")
738        .max
739}
740pub fn clamp_fns() -> &'static [DefId] {
741    &METHODS
742        .get()
743        .expect("Method DefIds haven't been initialized.")
744        .clamp
745}
746pub fn abs_fns() -> &'static [DefId] {
747    &METHODS
748        .get()
749        .expect("Method DefIds haven't been initialized.")
750        .abs
751}
752pub fn neg_fns() -> &'static [DefId] {
753    &METHODS
754        .get()
755        .expect("Method DefIds haven't been initialized.")
756        .neg
757}
758pub fn sat_unchecked_add_fns() -> &'static [DefId] {
759    &METHODS
760        .get()
761        .expect("Method DefIds haven't been initialized.")
762        .sat_unchecked_add
763}
764pub fn sat_unchecked_mul_fns() -> &'static [DefId] {
765    &METHODS
766        .get()
767        .expect("Method DefIds haven't been initialized.")
768        .sat_unchecked_mul
769}
770pub fn checked_add_fns() -> &'static [DefId] {
771    &METHODS
772        .get()
773        .expect("Method DefIds haven't been initialized.")
774        .checked_add
775}
776pub fn checked_mul_fns() -> &'static [DefId] {
777    &METHODS
778        .get()
779        .expect("Method DefIds haven't been initialized.")
780        .checked_mul
781}
782pub fn overflowing_nz_fns() -> &'static [DefId] {
783    &METHODS
784        .get()
785        .expect("Method DefIds haven't been initialized.")
786        .overflowing_nz
787}
788pub fn bit_preserving_nz_fns() -> &'static [DefId] {
789    &METHODS
790        .get()
791        .expect("Method DefIds haven't been initialized.")
792        .bit_preserving_nz
793}
794pub fn checked_nonzero_iff_fns() -> &'static [DefId] {
795    &METHODS
796        .get()
797        .expect("Method DefIds haven't been initialized.")
798        .checked_nonzero_iff
799}
800pub fn checked_next_pow2_fns() -> &'static [DefId] {
801    &METHODS
802        .get()
803        .expect("Method DefIds haven't been initialized.")
804        .checked_next_pow2
805}
806pub fn layout_align_fns() -> &'static [DefId] {
807    &METHODS
808        .get()
809        .expect("Method DefIds haven't been initialized.")
810        .layout_align
811}
812pub fn split_at_fns() -> &'static [DefId] {
813    &METHODS
814        .get()
815        .expect("Method DefIds haven't been initialized.")
816        .split_at
817}
818pub fn align_to_local_fns() -> &'static [DefId] {
819    &METHODS
820        .get()
821        .expect("Method DefIds haven't been initialized.")
822        .align_to_local
823}
824pub fn iter_position_fns() -> &'static [DefId] {
825    &METHODS
826        .get()
827        .expect("Method DefIds haven't been initialized.")
828        .iter_position
829}
830pub fn strlen_fns() -> &'static [DefId] {
831    &METHODS
832        .get()
833        .expect("Method DefIds haven't been initialized.")
834        .strlen
835}
836pub fn slice_get_unchecked_fns() -> &'static [DefId] {
837    &METHODS
838        .get()
839        .expect("Method DefIds haven't been initialized.")
840        .slice_get_unchecked
841}
842pub fn sliceindex_get_unchecked_fns() -> &'static [DefId] {
843    &METHODS
844        .get()
845        .expect("Method DefIds haven't been initialized.")
846        .sliceindex_get_unchecked
847}
848pub fn slice_range_fns() -> &'static [DefId] {
849    &METHODS
850        .get()
851        .expect("Method DefIds haven't been initialized.")
852        .slice_range_fns
853}
854
855fn init_inner(tcx: TyCtxt) -> Intrinsics {
856    const CRATES: &[&str] = &["core", "std", "alloc"];
857
858    // Map every registered path — both with and without its
859    // `std::`/`core::`/`alloc::` prefix — to its entry index.
860    // `rustc_public::CrateDef::name()` emits the crate prefix only on newer
861    // toolchains, so both forms must resolve to the same entry.
862    let path_to_idx: std::collections::HashMap<&str, usize> = INTRINSICS
863        .iter()
864        .enumerate()
865        .flat_map(|(idx, paths)| {
866            paths.iter().flat_map(move |&p| {
867                std::iter::once(p)
868                    .chain(
869                        ["std::", "core::", "alloc::"]
870                            .into_iter()
871                            .filter_map(move |pfx| p.strip_prefix(pfx)),
872                    )
873                    .map(move |q| (q, idx))
874            })
875        })
876        .collect();
877
878    let mut indices: IndexMap<_, _> = (0..INTRINSICS.len()).map(|idx| (idx, false)).collect();
879    let mut map = IndexMap::<Box<str>, DefId>::with_capacity(INTRINSICS.len());
880
881    let mut try_insert = |name: &str, def_id: rustc_public::DefId| {
882        let Some(&idx) = path_to_idx.get(name) else {
883            return;
884        };
885        assert_eq!(
886            indices.insert(idx, true),
887            Some(false),
888            "DefId for {name} has been found: {:?}",
889            map.get(INTRINSICS[idx][0])
890        );
891        // Store under the canonical (first) registered path so the `{id}()`
892        // accessors — which probe the registered paths — find it regardless of
893        // whether `name` carried a crate prefix.
894        map.insert(
895            Box::from(INTRINSICS[idx][0]),
896            rustc_internal::internal(tcx, def_id),
897        );
898    };
899
900    let mut loaded_crates = std::collections::HashSet::new();
901    for krate in std::iter::once(rustc_public::local_crate())
902        .chain(rustc_public::external_crates().into_iter())
903        .filter(|krate| CRATES.iter().any(|name| *name == krate.name))
904    {
905        loaded_crates.insert(krate.name.clone());
906        for fn_def in krate.fn_defs() {
907            try_insert(&fn_def.name(), fn_def.def_id());
908        }
909    }
910
911    #[cfg(debug_assertions)]
912    map.sort_unstable_by(|a, _, b, _| a.cmp(b));
913
914    if INTRINSICS.len() != map.len() {
915        // The reason to not make this an assertion is allowing compilation on
916        // missing instrinsics, e.g. no_std crates without using alloc will never
917        // have the dealloc intrinsic.
918        // cc https://github.com/Artisan-Lab/RAPx/issues/190#issuecomment-3303049000
919        let not_found = indices
920            .iter()
921            .filter_map(|(&idx, &found)| {
922                if found {
923                    return None;
924                }
925                // Only report entries whose crate was actually loaded for this
926                // compilation. Entries pointing solely at unloaded crates (e.g.
927                // `alloc` when verifying `core`) are expected to be absent.
928                let in_loaded_crate = INTRINSICS[idx].iter().any(|p| {
929                    p.split("::")
930                        .next()
931                        .is_some_and(|pfx| loaded_crates.contains(pfx))
932                });
933                in_loaded_crate.then_some(INTRINSICS[idx])
934            })
935            .collect::<Vec<_>>();
936        if !not_found.is_empty() {
937            rap_warn!(
938                "Intrinsic functions is incompletely retrieved.\n\
939                 {} fn ids are not found: {not_found:#?}",
940                not_found.len()
941            );
942        }
943    }
944
945    Intrinsics { map }
946}
947
948macro_rules! intrinsics {
949    ($( $(#[$attr:meta])* $id:ident : $paths:expr ,)+) => {
950        const INTRINSICS: &[&[&str]] = &[$( $(#[$attr])* $paths ,)+];
951        $(
952            $(#[$attr])*
953            pub fn $id() -> Option<DefId> {
954                let map = &INIT.get().expect("Intrinsics DefIds haven't been initialized.").map;
955                for path in $paths {
956                    match map.get(*path) {
957                        Some(id) => return Some(*id),
958                        None => ()
959                    }
960                }
961                None
962            }
963        )+
964    };
965}
966
967// for #![no_std] crates, intrinsics fn paths start from core instead of core.
968// cc https://github.com/Artisan-Lab/RAPx/issues/190
969intrinsics! {
970    call_mut: &[
971        "std::ops::FnMut::call_mut",
972        "core::ops::FnMut::call_mut",
973        "std::ops::function::FnMut::call_mut",
974        "core::ops::function::FnMut::call_mut"
975    ],
976    clone: &[
977        "std::clone::Clone::clone",
978        "core::clone::Clone::clone"
979    ],
980    copy_from: &[
981        "std::ptr::mut_ptr::<impl *mut T>::copy_from",
982        "core::ptr::mut_ptr::<impl *mut T>::copy_from"
983    ],
984    copy_from_nonoverlapping: &[
985        "std::ptr::mut_ptr::<impl *mut T>::copy_from_nonoverlapping",
986        "core::ptr::mut_ptr::<impl *mut T>::copy_from_nonoverlapping"
987    ],
988    copy_to: &[
989        "std::ptr::const_ptr::<impl *const T>::copy_to",
990        "core::ptr::const_ptr::<impl *const T>::copy_to",
991    ],
992    copy_to_nonoverlapping: &[
993        "std::ptr::const_ptr::<impl *const T>::copy_to_nonoverlapping",
994        "core::ptr::const_ptr::<impl *const T>::copy_to_nonoverlapping"
995    ],
996    dealloc: &[
997        "std::alloc::dealloc",
998        "alloc::alloc::dealloc"
999    ],
1000    drop: &[
1001        "std::mem::drop",
1002        "core::mem::drop",
1003    ],
1004    drop_in_place: &[
1005        "std::ptr::drop_in_place",
1006        "core::ptr::drop_in_place",
1007    ],
1008    manually_drop: &[
1009        "std::mem::ManuallyDrop::<T>::drop",
1010        "core::mem::ManuallyDrop::<T>::drop",
1011        "std::mem::manually_drop::ManuallyDrop::<T>::drop",
1012        "core::mem::manually_drop::ManuallyDrop::<T>::drop"
1013    ],
1014    replace: &[
1015        "std::mem::replace",
1016        "core::mem::replace"
1017    ],
1018    take: &[
1019        "std::mem::take",
1020        "core::mem::take"
1021    ],
1022    hint_select_unpredictable: &[
1023        "std::hint::select_unpredictable",
1024        "core::hint::select_unpredictable"
1025    ],
1026    ptr_read: &[
1027        "std::ptr::read",
1028        "core::ptr::read"
1029    ],
1030    ptr_read_unaligned: &[
1031        "std::ptr::read_unaligned",
1032        "core::ptr::read_unaligned"
1033    ],
1034    ptr_read_volatile: &[
1035        "std::ptr::read_volatile",
1036        "core::ptr::read_volatile"
1037    ],
1038    ptr_write: &[
1039        "std::ptr::write",
1040        "core::ptr::write"
1041    ],
1042    ptr_write_unaligned: &[
1043        "std::ptr::write_unaligned",
1044        "core::ptr::write_unaligned"
1045    ],
1046    ptr_write_volatile: &[
1047        "std::ptr::write_volatile",
1048        "core::ptr::write_volatile"
1049    ],
1050    ptr_write_bytes: &[
1051        "std::ptr::write_bytes",
1052        "core::ptr::write_bytes"
1053    ],
1054    // ── Core intrinsics ──
1055    intrinsics_copy: &[
1056        "std::intrinsics::copy",
1057        "core::intrinsics::copy"
1058    ],
1059    intrinsics_copy_nonoverlapping: &[
1060        "std::intrinsics::copy_nonoverlapping",
1061        "core::intrinsics::copy_nonoverlapping"
1062    ],
1063    intrinsics_size_of: &[
1064        "std::intrinsics::size_of",
1065        "core::intrinsics::size_of"
1066    ],
1067    intrinsics_align_of: &[
1068        "std::intrinsics::align_of",
1069        "core::intrinsics::align_of"
1070    ],
1071    select_unpredictable: &[
1072        "std::intrinsics::select_unpredictable",
1073        "core::intrinsics::select_unpredictable"
1074    ],
1075    assume_init_read: &[
1076        "std::mem::MaybeUninit::<T>::assume_init_read",
1077        "core::mem::MaybeUninit::<T>::assume_init_read",
1078        "std::mem::maybe_uninit::MaybeUninit::<T>::assume_init_read",
1079        "core::mem::maybe_uninit::MaybeUninit::<T>::assume_init_read"
1080    ],
1081    maybe_uninit_uninit: &[
1082        "std::mem::MaybeUninit::<T>::uninit",
1083        "core::mem::MaybeUninit::<T>::uninit",
1084        "std::mem::maybe_uninit::MaybeUninit::<T>::uninit",
1085        "core::mem::maybe_uninit::MaybeUninit::<T>::uninit"
1086    ],
1087    maybe_uninit_write: &[
1088        "std::mem::MaybeUninit::<T>::write",
1089        "core::mem::MaybeUninit::<T>::write",
1090        "std::mem::maybe_uninit::MaybeUninit::<T>::write",
1091        "core::mem::maybe_uninit::MaybeUninit::<T>::write"
1092    ],
1093    maybe_uninit_as_ptr: &[
1094        "std::mem::MaybeUninit::<T>::as_ptr",
1095        "core::mem::MaybeUninit::<T>::as_ptr",
1096        "std::mem::maybe_uninit::MaybeUninit::<T>::as_ptr",
1097        "core::mem::maybe_uninit::MaybeUninit::<T>::as_ptr"
1098    ],
1099    maybe_uninit_as_mut_ptr: &[
1100        "std::mem::MaybeUninit::<T>::as_mut_ptr",
1101        "core::mem::MaybeUninit::<T>::as_mut_ptr",
1102        "std::mem::maybe_uninit::MaybeUninit::<T>::as_mut_ptr",
1103        "core::mem::maybe_uninit::MaybeUninit::<T>::as_mut_ptr"
1104    ],
1105    maybe_uninit_assume_init: &[
1106        "std::mem::MaybeUninit::<T>::assume_init",
1107        "core::mem::MaybeUninit::<T>::assume_init",
1108        "std::mem::maybe_uninit::MaybeUninit::<T>::assume_init",
1109        "core::mem::maybe_uninit::MaybeUninit::<T>::assume_init"
1110    ],
1111    maybe_uninit_assume_init_ref: &[
1112        "std::mem::MaybeUninit::<T>::assume_init_ref",
1113        "core::mem::MaybeUninit::<T>::assume_init_ref",
1114        "std::mem::maybe_uninit::MaybeUninit::<T>::assume_init_ref",
1115        "core::mem::maybe_uninit::MaybeUninit::<T>::assume_init_ref"
1116    ],
1117    maybe_uninit_assume_init_mut: &[
1118        "std::mem::MaybeUninit::<T>::assume_init_mut",
1119        "core::mem::MaybeUninit::<T>::assume_init_mut",
1120        "std::mem::maybe_uninit::MaybeUninit::<T>::assume_init_mut",
1121        "core::mem::maybe_uninit::MaybeUninit::<T>::assume_init_mut"
1122    ],
1123    mem_size_of: &[
1124        "std::mem::size_of",
1125        "core::mem::size_of"
1126    ],
1127    mem_align_of: &[
1128        "std::mem::align_of",
1129        "core::mem::align_of"
1130    ],
1131    ptr_align_offset: &[
1132        "std::ptr::align_offset",
1133        "core::ptr::align_offset"
1134    ],
1135    nonnull_align_offset: &[
1136        "std::ptr::NonNull::<T>::align_offset",
1137        "core::ptr::NonNull::<T>::align_offset",
1138        "std::ptr::non_null::NonNull::<T>::align_offset",
1139        "core::ptr::non_null::NonNull::<T>::align_offset"
1140    ],
1141    nonnull_as_ref: &[
1142        "std::ptr::NonNull::<T>::as_ref",
1143        "core::ptr::NonNull::<T>::as_ref",
1144        "std::ptr::non_null::NonNull::<T>::as_ref",
1145        "core::ptr::non_null::NonNull::<T>::as_ref"
1146    ],
1147    nonnull_as_mut: &[
1148        "std::ptr::NonNull::<T>::as_mut",
1149        "core::ptr::NonNull::<T>::as_mut",
1150        "std::ptr::non_null::NonNull::<T>::as_mut",
1151        "core::ptr::non_null::NonNull::<T>::as_mut"
1152    ],
1153    nonnull_new: &[
1154        "std::ptr::NonNull::<T>::new",
1155        "core::ptr::NonNull::<T>::new",
1156        "std::ptr::non_null::NonNull::<T>::new",
1157        "core::ptr::non_null::NonNull::<T>::new"
1158    ],
1159    nonnull_new_unchecked: &[
1160        "std::ptr::NonNull::<T>::new_unchecked",
1161        "core::ptr::NonNull::<T>::new_unchecked",
1162        "std::ptr::non_null::NonNull::<T>::new_unchecked",
1163        "core::ptr::non_null::NonNull::<T>::new_unchecked"
1164    ],
1165    const_ptr_align_offset: &[
1166        "std::ptr::const_ptr::<impl *const T>::align_offset",
1167        "core::ptr::const_ptr::<impl *const T>::align_offset"
1168    ],
1169    mut_ptr_align_offset: &[
1170        "std::ptr::mut_ptr::<impl *mut T>::align_offset",
1171        "core::ptr::mut_ptr::<impl *mut T>::align_offset"
1172    ],
1173    const_ptr_add: &[
1174        "std::ptr::const_ptr::<impl *const T>::add",
1175        "core::ptr::const_ptr::<impl *const T>::add"
1176    ],
1177    const_ptr_wrapping_add: &[
1178        "std::ptr::const_ptr::<impl *const T>::wrapping_add",
1179        "core::ptr::const_ptr::<impl *const T>::wrapping_add"
1180    ],
1181    const_ptr_sub: &[
1182        "std::ptr::const_ptr::<impl *const T>::sub",
1183        "core::ptr::const_ptr::<impl *const T>::sub"
1184    ],
1185    const_ptr_wrapping_sub: &[
1186        "std::ptr::const_ptr::<impl *const T>::wrapping_sub",
1187        "core::ptr::const_ptr::<impl *const T>::wrapping_sub"
1188    ],
1189    const_ptr_offset: &[
1190        "std::ptr::const_ptr::<impl *const T>::offset",
1191        "core::ptr::const_ptr::<impl *const T>::offset"
1192    ],
1193    const_ptr_wrapping_offset: &[
1194        "std::ptr::const_ptr::<impl *const T>::wrapping_offset",
1195        "core::ptr::const_ptr::<impl *const T>::wrapping_offset"
1196    ],
1197    const_ptr_byte_add: &[
1198        "std::ptr::const_ptr::<impl *const T>::byte_add",
1199        "core::ptr::const_ptr::<impl *const T>::byte_add"
1200    ],
1201    const_ptr_wrapping_byte_add: &[
1202        "std::ptr::const_ptr::<impl *const T>::wrapping_byte_add",
1203        "core::ptr::const_ptr::<impl *const T>::wrapping_byte_add"
1204    ],
1205    const_ptr_byte_sub: &[
1206        "std::ptr::const_ptr::<impl *const T>::byte_sub",
1207        "core::ptr::const_ptr::<impl *const T>::byte_sub"
1208    ],
1209    const_ptr_wrapping_byte_sub: &[
1210        "std::ptr::const_ptr::<impl *const T>::wrapping_byte_sub",
1211        "core::ptr::const_ptr::<impl *const T>::wrapping_byte_sub"
1212    ],
1213    const_ptr_byte_offset: &[
1214        "std::ptr::const_ptr::<impl *const T>::byte_offset",
1215        "core::ptr::const_ptr::<impl *const T>::byte_offset"
1216    ],
1217    const_ptr_wrapping_byte_offset: &[
1218        "std::ptr::const_ptr::<impl *const T>::wrapping_byte_offset",
1219        "core::ptr::const_ptr::<impl *const T>::wrapping_byte_offset"
1220    ],
1221    mut_ptr_add: &[
1222        "std::ptr::mut_ptr::<impl *mut T>::add",
1223        "core::ptr::mut_ptr::<impl *mut T>::add"
1224    ],
1225    mut_ptr_wrapping_add: &[
1226        "std::ptr::mut_ptr::<impl *mut T>::wrapping_add",
1227        "core::ptr::mut_ptr::<impl *mut T>::wrapping_add"
1228    ],
1229    mut_ptr_sub: &[
1230        "std::ptr::mut_ptr::<impl *mut T>::sub",
1231        "core::ptr::mut_ptr::<impl *mut T>::sub"
1232    ],
1233    mut_ptr_wrapping_sub: &[
1234        "std::ptr::mut_ptr::<impl *mut T>::wrapping_sub",
1235        "core::ptr::mut_ptr::<impl *mut T>::wrapping_sub"
1236    ],
1237    mut_ptr_offset: &[
1238        "std::ptr::mut_ptr::<impl *mut T>::offset",
1239        "core::ptr::mut_ptr::<impl *mut T>::offset"
1240    ],
1241    mut_ptr_wrapping_offset: &[
1242        "std::ptr::mut_ptr::<impl *mut T>::wrapping_offset",
1243        "core::ptr::mut_ptr::<impl *mut T>::wrapping_offset"
1244    ],
1245    mut_ptr_byte_add: &[
1246        "std::ptr::mut_ptr::<impl *mut T>::byte_add",
1247        "core::ptr::mut_ptr::<impl *mut T>::byte_add"
1248    ],
1249    mut_ptr_wrapping_byte_add: &[
1250        "std::ptr::mut_ptr::<impl *mut T>::wrapping_byte_add",
1251        "core::ptr::mut_ptr::<impl *mut T>::wrapping_byte_add"
1252    ],
1253    mut_ptr_byte_sub: &[
1254        "std::ptr::mut_ptr::<impl *mut T>::byte_sub",
1255        "core::ptr::mut_ptr::<impl *mut T>::byte_sub"
1256    ],
1257    mut_ptr_wrapping_byte_sub: &[
1258        "std::ptr::mut_ptr::<impl *mut T>::wrapping_byte_sub",
1259        "core::ptr::mut_ptr::<impl *mut T>::wrapping_byte_sub"
1260    ],
1261    mut_ptr_byte_offset: &[
1262        "std::ptr::mut_ptr::<impl *mut T>::byte_offset",
1263        "core::ptr::mut_ptr::<impl *mut T>::byte_offset"
1264    ],
1265    mut_ptr_wrapping_byte_offset: &[
1266        "std::ptr::mut_ptr::<impl *mut T>::wrapping_byte_offset",
1267        "core::ptr::mut_ptr::<impl *mut T>::wrapping_byte_offset"
1268    ],
1269    nonnull_add: &[
1270        "std::ptr::NonNull::<T>::add",
1271        "core::ptr::NonNull::<T>::add",
1272        "std::ptr::non_null::NonNull::<T>::add",
1273        "core::ptr::non_null::NonNull::<T>::add"
1274    ],
1275    nonnull_sub: &[
1276        "std::ptr::NonNull::<T>::sub",
1277        "core::ptr::NonNull::<T>::sub",
1278        "std::ptr::non_null::NonNull::<T>::sub",
1279        "core::ptr::non_null::NonNull::<T>::sub"
1280    ],
1281    nonnull_byte_add: &[
1282        "std::ptr::NonNull::<T>::byte_add",
1283        "core::ptr::NonNull::<T>::byte_add",
1284        "std::ptr::non_null::NonNull::<T>::byte_add",
1285        "core::ptr::non_null::NonNull::<T>::byte_add"
1286    ],
1287    nonnull_byte_sub: &[
1288        "std::ptr::NonNull::<T>::byte_sub",
1289        "core::ptr::NonNull::<T>::byte_sub",
1290        "std::ptr::non_null::NonNull::<T>::byte_sub",
1291        "core::ptr::non_null::NonNull::<T>::byte_sub"
1292    ],
1293    nonnull_offset: &[
1294        "std::ptr::NonNull::<T>::offset",
1295        "core::ptr::NonNull::<T>::offset",
1296        "std::ptr::non_null::NonNull::<T>::offset",
1297        "core::ptr::non_null::NonNull::<T>::offset"
1298    ],
1299    nonnull_byte_offset: &[
1300        "std::ptr::NonNull::<T>::byte_offset",
1301        "core::ptr::NonNull::<T>::byte_offset",
1302        "std::ptr::non_null::NonNull::<T>::byte_offset",
1303        "core::ptr::non_null::NonNull::<T>::byte_offset"
1304    ],
1305    option_unwrap: &[
1306        "std::option::Option::<T>::unwrap",
1307        "core::option::Option::<T>::unwrap"
1308    ],
1309    option_expect: &[
1310        "std::option::Option::<T>::expect",
1311        "core::option::Option::<T>::expect"
1312    ],
1313    option_unwrap_unchecked: &[
1314        "std::option::Option::<T>::unwrap_unchecked",
1315        "core::option::Option::<T>::unwrap_unchecked"
1316    ],
1317    result_unwrap: &[
1318        "std::result::Result::<T, E>::unwrap",
1319        "core::result::Result::<T, E>::unwrap"
1320    ],
1321    result_unwrap_err: &[
1322        "std::result::Result::<T, E>::unwrap_err",
1323        "core::result::Result::<T, E>::unwrap_err"
1324    ],
1325    result_expect: &[
1326        "std::result::Result::<T, E>::expect",
1327        "core::result::Result::<T, E>::expect"
1328    ],
1329    result_expect_err: &[
1330        "std::result::Result::<T, E>::expect_err",
1331        "core::result::Result::<T, E>::expect_err"
1332    ],
1333    result_unwrap_unchecked: &[
1334        "std::result::Result::<T, E>::unwrap_unchecked",
1335        "core::result::Result::<T, E>::unwrap_unchecked"
1336    ],
1337    cstr_from_ptr: &[
1338        "std::ffi::CStr::from_ptr",
1339        "core::ffi::CStr::from_ptr",
1340        "std::ffi::c_str::CStr::from_ptr",
1341        "core::ffi::c_str::CStr::from_ptr"
1342    ],
1343    cstr_from_bytes_with_nul_unchecked: &[
1344        "std::ffi::CStr::from_bytes_with_nul_unchecked",
1345        "core::ffi::CStr::from_bytes_with_nul_unchecked",
1346        "std::ffi::c_str::CStr::from_bytes_with_nul_unchecked",
1347        "core::ffi::c_str::CStr::from_bytes_with_nul_unchecked"
1348    ],
1349    cstring_from_vec_with_nul_unchecked: &[
1350        "std::ffi::CString::from_vec_with_nul_unchecked",
1351        "alloc::ffi::CString::from_vec_with_nul_unchecked",
1352        "std::ffi::c_str::CString::from_vec_with_nul_unchecked",
1353        "alloc::ffi::c_str::CString::from_vec_with_nul_unchecked"
1354    ],
1355    vec_push: &[
1356        "std::vec::Vec::<T, A>::push",
1357        "alloc::vec::Vec::<T, A>::push"
1358    ],
1359    vec_reserve: &[
1360        "std::vec::Vec::<T, A>::reserve",
1361        "alloc::vec::Vec::<T, A>::reserve"
1362    ],
1363    vec_reserve_exact: &[
1364        "std::vec::Vec::<T, A>::reserve_exact",
1365        "alloc::vec::Vec::<T, A>::reserve_exact"
1366    ],
1367    vec_shrink_to_fit: &[
1368        "std::vec::Vec::<T, A>::shrink_to_fit",
1369        "alloc::vec::Vec::<T, A>::shrink_to_fit"
1370    ],
1371    vec_shrink_to: &[
1372        "std::vec::Vec::<T, A>::shrink_to",
1373        "alloc::vec::Vec::<T, A>::shrink_to"
1374    ],
1375    vec_insert: &[
1376        "std::vec::Vec::<T, A>::insert",
1377        "alloc::vec::Vec::<T, A>::insert"
1378    ],
1379    vec_remove: &[
1380        "std::vec::Vec::<T, A>::remove",
1381        "alloc::vec::Vec::<T, A>::remove"
1382    ],
1383    vec_clear: &[
1384        "std::vec::Vec::<T, A>::clear",
1385        "alloc::vec::Vec::<T, A>::clear"
1386    ],
1387    vec_truncate: &[
1388        "std::vec::Vec::<T, A>::truncate",
1389        "alloc::vec::Vec::<T, A>::truncate"
1390    ],
1391    vec_set_len: &[
1392        "std::vec::Vec::<T, A>::set_len",
1393        "alloc::vec::Vec::<T, A>::set_len"
1394    ],
1395    box_from_raw: &[
1396        "std::boxed::Box::<T>::from_raw",
1397        "alloc::boxed::Box::<T>::from_raw"
1398    ],
1399    cstring_from_raw: &[
1400        "std::ffi::CString::from_raw",
1401        "alloc::ffi::CString::from_raw",
1402        "std::ffi::c_str::CString::from_raw",
1403        "alloc::ffi::c_str::CString::from_raw"
1404    ],
1405    arc_from_raw: &[
1406        "std::sync::Arc::<T>::from_raw",
1407        "alloc::sync::Arc::<T>::from_raw"
1408    ],
1409    rc_from_raw: &[
1410        "std::rc::Rc::<T>::from_raw",
1411        "alloc::rc::Rc::<T>::from_raw"
1412    ],
1413    box_from_raw_in: &[
1414        "std::boxed::Box::<T, A>::from_raw_in",
1415        "alloc::boxed::Box::<T, A>::from_raw_in"
1416    ],
1417    arc_from_raw_in: &[
1418        "std::sync::Arc::<T, A>::from_raw_in",
1419        "alloc::sync::Arc::<T, A>::from_raw_in"
1420    ],
1421    rc_from_raw_in: &[
1422        "std::rc::Rc::<T, A>::from_raw_in",
1423        "alloc::rc::Rc::<T, A>::from_raw_in"
1424    ],
1425    box_into_raw: &[
1426        "std::boxed::Box::<T>::into_raw",
1427        "alloc::boxed::Box::<T>::into_raw"
1428    ],
1429    box_as_ptr: &[
1430        "std::boxed::Box::<T, A>::as_ptr",
1431        "alloc::boxed::Box::<T, A>::as_ptr"
1432    ],
1433    box_as_mut_ptr: &[
1434        "std::boxed::Box::<T, A>::as_mut_ptr",
1435        "alloc::boxed::Box::<T, A>::as_mut_ptr"
1436    ],
1437    cstring_into_raw: &[
1438        "std::ffi::CString::into_raw",
1439        "alloc::ffi::CString::into_raw",
1440        "std::ffi::c_str::CString::into_raw",
1441        "alloc::ffi::c_str::CString::into_raw"
1442    ],
1443    arc_into_raw: &[
1444        "std::sync::Arc::<T>::into_raw",
1445        "alloc::sync::Arc::<T>::into_raw"
1446    ],
1447    arc_as_ptr: &[
1448        "std::sync::Arc::<T>::as_ptr",
1449        "alloc::sync::Arc::<T>::as_ptr",
1450        "std::sync::Arc::<T, A>::as_ptr",
1451        "alloc::sync::Arc::<T, A>::as_ptr"
1452    ],
1453    rc_into_raw: &[
1454        "std::rc::Rc::<T>::into_raw",
1455        "alloc::rc::Rc::<T>::into_raw"
1456    ],
1457    rc_as_ptr: &[
1458        "std::rc::Rc::<T>::as_ptr",
1459        "alloc::rc::Rc::<T>::as_ptr",
1460        "std::rc::Rc::<T, A>::as_ptr",
1461        "alloc::rc::Rc::<T, A>::as_ptr"
1462    ],
1463    vec_from_elem: &[
1464        "std::vec::from_elem",
1465        "alloc::vec::from_elem"
1466    ],
1467    vec_into_boxed_slice: &[
1468        "std::vec::Vec::<T, A>::into_boxed_slice",
1469        "alloc::vec::Vec::<T, A>::into_boxed_slice"
1470    ],
1471    slice_into_vec: &[
1472        "std::slice::<impl [T]>::into_vec",
1473        "alloc::slice::<impl [T]>::into_vec"
1474    ],
1475    slice_to_vec: &[
1476        "std::slice::<impl [T]>::to_vec_in::ConvertVec::to_vec",
1477        "alloc::slice::<impl [T]>::to_vec_in::ConvertVec::to_vec"
1478    ],
1479    #[cfg(rapx_ge_99)]
1480    box_assume_init_into_vec_unsafe: &[
1481        "std::boxed::box_assume_init_into_vec_unsafe",
1482        "alloc::boxed::box_assume_init_into_vec_unsafe"
1483    ],
1484    const_ptr_is_null: &[
1485        "std::ptr::const_ptr::<impl *const T>::is_null",
1486        "core::ptr::const_ptr::<impl *const T>::is_null"
1487    ],
1488    const_ptr_addr: &[
1489        "std::ptr::const_ptr::<impl *const T>::addr",
1490        "core::ptr::const_ptr::<impl *const T>::addr"
1491    ],
1492    const_ptr_cast: &[
1493        "std::ptr::const_ptr::<impl *const T>::cast",
1494        "core::ptr::const_ptr::<impl *const T>::cast"
1495    ],
1496    const_ptr_cast_mut: &[
1497        "std::ptr::const_ptr::<impl *const T>::cast_mut",
1498        "core::ptr::const_ptr::<impl *const T>::cast_mut"
1499    ],
1500    const_ptr_cast_array: &[
1501        "std::ptr::const_ptr::<impl *const T>::cast_array",
1502        "core::ptr::const_ptr::<impl *const T>::cast_array"
1503    ],
1504    const_ptr_slice_is_empty: &[
1505        "std::ptr::const_ptr::<impl *const [T]>::is_empty",
1506        "core::ptr::const_ptr::<impl *const [T]>::is_empty"
1507    ],
1508    const_ptr_slice_len: &[
1509        "std::ptr::const_ptr::<impl *const [T]>::len",
1510        "core::ptr::const_ptr::<impl *const [T]>::len"
1511    ],
1512    const_ptr_slice_as_ptr: &[
1513        "std::ptr::const_ptr::<impl *const [T]>::as_ptr",
1514        "core::ptr::const_ptr::<impl *const [T]>::as_ptr"
1515    ],
1516    mut_ptr_is_null: &[
1517        "std::ptr::mut_ptr::<impl *mut T>::is_null",
1518        "core::ptr::mut_ptr::<impl *mut T>::is_null"
1519    ],
1520    mut_ptr_addr: &[
1521        "std::ptr::mut_ptr::<impl *mut T>::addr",
1522        "core::ptr::mut_ptr::<impl *mut T>::addr"
1523    ],
1524    mut_ptr_cast: &[
1525        "std::ptr::mut_ptr::<impl *mut T>::cast",
1526        "core::ptr::mut_ptr::<impl *mut T>::cast"
1527    ],
1528    mut_ptr_cast_const: &[
1529        "std::ptr::mut_ptr::<impl *mut T>::cast_const",
1530        "core::ptr::mut_ptr::<impl *mut T>::cast_const"
1531    ],
1532    mut_ptr_cast_array: &[
1533        "std::ptr::mut_ptr::<impl *mut T>::cast_array",
1534        "core::ptr::mut_ptr::<impl *mut T>::cast_array"
1535    ],
1536    mut_ptr_slice_is_empty: &[
1537        "std::ptr::mut_ptr::<impl *mut [T]>::is_empty",
1538        "core::ptr::mut_ptr::<impl *mut [T]>::is_empty"
1539    ],
1540    mut_ptr_slice_len: &[
1541        "std::ptr::mut_ptr::<impl *mut [T]>::len",
1542        "core::ptr::mut_ptr::<impl *mut [T]>::len"
1543    ],
1544    mut_ptr_slice_as_mut_ptr: &[
1545        "std::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr",
1546        "core::ptr::mut_ptr::<impl *mut [T]>::as_mut_ptr"
1547    ],
1548    nonnull_addr: &[
1549        "std::ptr::NonNull::<T>::addr",
1550        "core::ptr::NonNull::<T>::addr",
1551        "std::ptr::non_null::NonNull::<T>::addr",
1552        "core::ptr::non_null::NonNull::<T>::addr"
1553    ],
1554    nonnull_cast: &[
1555        "std::ptr::NonNull::<T>::cast",
1556        "core::ptr::NonNull::<T>::cast",
1557        "std::ptr::non_null::NonNull::<T>::cast",
1558        "core::ptr::non_null::NonNull::<T>::cast"
1559    ],
1560    nonnull_as_ptr: &[
1561        "std::ptr::NonNull::<T>::as_ptr",
1562        "core::ptr::NonNull::<T>::as_ptr",
1563        "std::ptr::non_null::NonNull::<T>::as_ptr",
1564        "core::ptr::non_null::NonNull::<T>::as_ptr"
1565    ],
1566    nonnull_slice_is_empty: &[
1567        "std::ptr::NonNull::<[T]>::is_empty",
1568        "core::ptr::NonNull::<[T]>::is_empty",
1569        "std::ptr::non_null::NonNull::<[T]>::is_empty",
1570        "core::ptr::non_null::NonNull::<[T]>::is_empty"
1571    ],
1572    nonnull_slice_len: &[
1573        "std::ptr::NonNull::<[T]>::len",
1574        "core::ptr::NonNull::<[T]>::len",
1575        "std::ptr::non_null::NonNull::<[T]>::len",
1576        "core::ptr::non_null::NonNull::<[T]>::len"
1577    ],
1578    nonnull_slice_as_mut_ptr: &[
1579        "std::ptr::NonNull::<[T]>::as_mut_ptr",
1580        "core::ptr::NonNull::<[T]>::as_mut_ptr",
1581        "std::ptr::non_null::NonNull::<[T]>::as_mut_ptr",
1582        "core::ptr::non_null::NonNull::<[T]>::as_mut_ptr"
1583    ],
1584    slice_len: &[
1585        "std::slice::<impl [T]>::len",
1586        "core::slice::<impl [T]>::len"
1587    ],
1588    slice_is_empty: &[
1589        "std::slice::<impl [T]>::is_empty",
1590        "core::slice::<impl [T]>::is_empty"
1591    ],
1592    slice_as_ptr: &[
1593        "std::slice::<impl [T]>::as_ptr",
1594        "core::slice::<impl [T]>::as_ptr"
1595    ],
1596    slice_as_mut_ptr: &[
1597        "std::slice::<impl [T]>::as_mut_ptr",
1598        "core::slice::<impl [T]>::as_mut_ptr"
1599    ],
1600    str_len: &[
1601        "std::str::<impl str>::len",
1602        "core::str::<impl str>::len"
1603    ],
1604    str_is_empty: &[
1605        "std::str::<impl str>::is_empty",
1606        "core::str::<impl str>::is_empty"
1607    ],
1608    str_as_ptr: &[
1609        "std::str::<impl str>::as_ptr",
1610        "core::str::<impl str>::as_ptr"
1611    ],
1612    str_as_bytes: &[
1613        "std::str::<impl str>::as_bytes",
1614        "core::str::<impl str>::as_bytes"
1615    ],
1616    str_as_mut_ptr: &[
1617        "std::str::<impl str>::as_mut_ptr",
1618        "core::str::<impl str>::as_mut_ptr"
1619    ],
1620    vec_len: &[
1621        "std::vec::Vec::<T, A>::len",
1622        "alloc::vec::Vec::<T, A>::len"
1623    ],
1624    vec_is_empty: &[
1625        "std::vec::Vec::<T, A>::is_empty",
1626        "alloc::vec::Vec::<T, A>::is_empty"
1627    ],
1628    vec_as_ptr: &[
1629        "std::vec::Vec::<T, A>::as_ptr",
1630        "alloc::vec::Vec::<T, A>::as_ptr"
1631    ],
1632    vec_as_mut_ptr: &[
1633        "std::vec::Vec::<T, A>::as_mut_ptr",
1634        "alloc::vec::Vec::<T, A>::as_mut_ptr"
1635    ],
1636    string_len: &[
1637        "std::string::String::len",
1638        "alloc::string::String::len"
1639    ],
1640    string_is_empty: &[
1641        "std::string::String::is_empty",
1642        "alloc::string::String::is_empty"
1643    ],
1644    cstr_as_ptr: &[
1645        "std::ffi::CStr::as_ptr",
1646        "core::ffi::CStr::as_ptr",
1647        "std::ffi::c_str::CStr::as_ptr",
1648        "core::ffi::c_str::CStr::as_ptr"
1649    ],
1650    cstr_is_empty: &[
1651        "std::ffi::CStr::is_empty",
1652        "core::ffi::CStr::is_empty",
1653        "std::ffi::c_str::CStr::is_empty",
1654        "core::ffi::c_str::CStr::is_empty"
1655    ],
1656}
1657
1658/// rustc_public DefId to internal DefId
1659pub fn to_internal<T: CrateDef>(val: &T, tcx: TyCtxt) -> DefId {
1660    rustc_internal::internal(tcx, val.def_id())
1661}
1662
1663/// Find any drop fn. Any of these drop fns can be missing, e.g. for crates like no_std without
1664/// using alloc, dealloc doesn't exist.
1665pub fn is_drop_fn(target: DefId) -> bool {
1666    let drop_fn = [drop(), drop_in_place(), manually_drop(), dealloc()];
1667    contains(&drop_fn, target)
1668}
1669
1670/// Is the targe DefId in the given array.
1671pub fn contains(v: &[Option<DefId>], target: DefId) -> bool {
1672    v.contains(&Some(target))
1673}