Skip to main content

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            && let Type::Ident(inner) = &slice.inner
34            && slice.mutable
35            && is_extern_type_alias(inner)
36        {
37            reasons.insert(&inner.rust, UnpinReason::Slice(slice));
38        }
39    }
40
41    for api in apis {
42        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api
43            && let Some(receiver) = efn.receiver()
44            && receiver.mutable
45            && !receiver.pinned
46            && is_extern_type_alias(&receiver.ty)
47        {
48            reasons.insert(&receiver.ty.rust, UnpinReason::Receiver(receiver));
49        }
50    }
51
52    for (ty, _cfg) in all {
53        if let Type::Ref(ty) = ty
54            && let Type::Ident(inner) = &ty.inner
55            && ty.mutable
56            && !ty.pinned
57            && is_extern_type_alias(inner)
58        {
59            reasons.insert(&inner.rust, UnpinReason::Ref(ty));
60        }
61    }
62
63    reasons
64}