cxx_gen/syntax/
unpin.rs

1use crate::syntax::cfg::ComputedCfg;
2use crate::syntax::map::{OrderedMap, UnorderedMap};
3use crate::syntax::set::UnorderedSet;
4use crate::syntax::{Api, Enum, NamedType, Receiver, Ref, SliceRef, Struct, Type, TypeAlias};
5use proc_macro2::Ident;
6
7#[cfg_attr(not(proc_macro), expect(dead_code))]
8pub(crate) enum UnpinReason<'a> {
9    Receiver(&'a Receiver),
10    Ref(&'a Ref),
11    Slice(&'a SliceRef),
12}
13
14pub(crate) fn required_unpin_reasons<'a>(
15    apis: &'a [Api],
16    all: &OrderedMap<&'a Type, ComputedCfg>,
17    structs: &UnorderedMap<&'a Ident, &'a Struct>,
18    enums: &UnorderedMap<&'a Ident, &'a Enum>,
19    cxx: &UnorderedSet<&'a Ident>,
20    aliases: &UnorderedMap<&'a Ident, &'a TypeAlias>,
21) -> UnorderedMap<&'a Ident, UnpinReason<'a>> {
22    let mut reasons = UnorderedMap::new();
23
24    let is_extern_type_alias = |ty: &NamedType| -> bool {
25        cxx.contains(&ty.rust)
26            && !structs.contains_key(&ty.rust)
27            && !enums.contains_key(&ty.rust)
28            && aliases.contains_key(&ty.rust)
29    };
30
31    for (ty, _cfgs) in all {
32        if let Type::SliceRef(slice) = ty {
33            if let Type::Ident(inner) = &slice.inner {
34                if slice.mutable && is_extern_type_alias(inner) {
35                    reasons.insert(&inner.rust, UnpinReason::Slice(slice));
36                }
37            }
38        }
39    }
40
41    for api in apis {
42        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
43            if let Some(receiver) = efn.receiver() {
44                if receiver.mutable && !receiver.pinned && is_extern_type_alias(&receiver.ty) {
45                    reasons.insert(&receiver.ty.rust, UnpinReason::Receiver(receiver));
46                }
47            }
48        }
49    }
50
51    for (ty, _cfg) in all {
52        if let Type::Ref(ty) = ty {
53            if let Type::Ident(inner) = &ty.inner {
54                if ty.mutable && !ty.pinned && is_extern_type_alias(inner) {
55                    reasons.insert(&inner.rust, UnpinReason::Ref(ty));
56                }
57            }
58        }
59    }
60
61    reasons
62}