cxx_build/syntax/
instantiate.rs

1use crate::syntax::map::UnorderedMap;
2use crate::syntax::resolve::Resolution;
3use crate::syntax::types::Types;
4use crate::syntax::{mangle, Symbol, Ty1, Type};
5use proc_macro2::{Ident, Span};
6use std::hash::{Hash, Hasher};
7
8#[derive(#[automatically_derived]
impl<'a> ::core::cmp::PartialEq for ImplKey<'a> {
    #[inline]
    fn eq(&self, other: &ImplKey<'a>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (ImplKey::RustBox(__self_0), ImplKey::RustBox(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (ImplKey::RustVec(__self_0), ImplKey::RustVec(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (ImplKey::UniquePtr(__self_0), ImplKey::UniquePtr(__arg1_0))
                    => __self_0 == __arg1_0,
                (ImplKey::SharedPtr(__self_0), ImplKey::SharedPtr(__arg1_0))
                    => __self_0 == __arg1_0,
                (ImplKey::WeakPtr(__self_0), ImplKey::WeakPtr(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (ImplKey::CxxVector(__self_0), ImplKey::CxxVector(__arg1_0))
                    => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl<'a> ::core::cmp::Eq for ImplKey<'a> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<NamedImplKey<'a>>;
        let _: ::core::cmp::AssertParamIsEq<NamedImplKey<'a>>;
        let _: ::core::cmp::AssertParamIsEq<NamedImplKey<'a>>;
        let _: ::core::cmp::AssertParamIsEq<NamedImplKey<'a>>;
        let _: ::core::cmp::AssertParamIsEq<NamedImplKey<'a>>;
        let _: ::core::cmp::AssertParamIsEq<NamedImplKey<'a>>;
    }
}Eq, #[automatically_derived]
impl<'a> ::core::hash::Hash for ImplKey<'a> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            ImplKey::RustBox(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            ImplKey::RustVec(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            ImplKey::UniquePtr(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            ImplKey::SharedPtr(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            ImplKey::WeakPtr(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            ImplKey::CxxVector(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash)]
9pub(crate) enum ImplKey<'a> {
10    RustBox(NamedImplKey<'a>),
11    RustVec(NamedImplKey<'a>),
12    UniquePtr(NamedImplKey<'a>),
13    SharedPtr(NamedImplKey<'a>),
14    WeakPtr(NamedImplKey<'a>),
15    CxxVector(NamedImplKey<'a>),
16}
17
18impl<'a> ImplKey<'a> {
19    /// Whether to produce FFI symbols instantiating the given generic type even
20    /// when an explicit `impl Foo<T> {}` is not present in the current bridge.
21    ///
22    /// The main consideration is that the same instantiation must not be
23    /// present in two places, which is accomplished using trait impls and the
24    /// orphan rule. Every instantiation of a C++ template like `CxxVector<T>`
25    /// and Rust generic type like `Vec<T>` requires the implementation of
26    /// traits defined by the `cxx` crate for some local type. (TODO: or for a
27    /// fundamental type like `Box<LocalType>`)
28    pub(crate) fn is_implicit_impl_ok(&self, types: &Types) -> bool {
29        // TODO: relax this for Rust generics to allow Vec<Vec<T>> etc.
30        types.is_local(self.inner())
31    }
32
33    /// Returns the type argument in the generic instantiation described by
34    /// `self`. For example, if `self` represents `UniquePtr<u32>` then this
35    /// will return `u32`.
36    fn inner(&self) -> &'a Type {
37        let named_impl_key = match self {
38            ImplKey::RustBox(key)
39            | ImplKey::RustVec(key)
40            | ImplKey::UniquePtr(key)
41            | ImplKey::SharedPtr(key)
42            | ImplKey::WeakPtr(key)
43            | ImplKey::CxxVector(key) => key,
44        };
45        named_impl_key.inner
46    }
47}
48
49pub(crate) struct NamedImplKey<'a> {
50    #[cfg_attr(not(proc_macro), expect(dead_code))]
51    pub begin_span: Span,
52    /// Mangled form of the `inner` type.
53    pub symbol: Symbol,
54    /// Generic type - e.g. `UniquePtr<u8>`.
55    #[cfg_attr(proc_macro, expect(dead_code))]
56    pub outer: &'a Type,
57    /// Generic type argument - e.g. `u8` from `UniquePtr<u8>`.
58    pub inner: &'a Type,
59    #[cfg_attr(not(proc_macro), expect(dead_code))]
60    pub end_span: Span,
61}
62
63impl Type {
64    pub(crate) fn impl_key(&self, res: &UnorderedMap<&Ident, Resolution>) -> Option<ImplKey> {
65        match self {
66            Type::RustBox(ty) => Some(ImplKey::RustBox(NamedImplKey::new(self, ty, res)?)),
67            Type::RustVec(ty) => Some(ImplKey::RustVec(NamedImplKey::new(self, ty, res)?)),
68            Type::UniquePtr(ty) => Some(ImplKey::UniquePtr(NamedImplKey::new(self, ty, res)?)),
69            Type::SharedPtr(ty) => Some(ImplKey::SharedPtr(NamedImplKey::new(self, ty, res)?)),
70            Type::WeakPtr(ty) => Some(ImplKey::WeakPtr(NamedImplKey::new(self, ty, res)?)),
71            Type::CxxVector(ty) => Some(ImplKey::CxxVector(NamedImplKey::new(self, ty, res)?)),
72            _ => None,
73        }
74    }
75}
76
77impl<'a> PartialEq for NamedImplKey<'a> {
78    fn eq(&self, other: &Self) -> bool {
79        PartialEq::eq(&self.symbol, &other.symbol)
80    }
81}
82
83impl<'a> Eq for NamedImplKey<'a> {}
84
85impl<'a> Hash for NamedImplKey<'a> {
86    fn hash<H: Hasher>(&self, hasher: &mut H) {
87        self.symbol.hash(hasher);
88    }
89}
90
91impl<'a> NamedImplKey<'a> {
92    fn new(outer: &'a Type, ty1: &'a Ty1, res: &UnorderedMap<&Ident, Resolution>) -> Option<Self> {
93        let inner = &ty1.inner;
94        Some(NamedImplKey {
95            symbol: mangle::typename(inner, res)?,
96            begin_span: ty1.name.span(),
97            outer,
98            inner,
99            end_span: ty1.rangle.span,
100        })
101    }
102}